dev
This commit is contained in:
+26
-24
@@ -17,6 +17,7 @@ router = APIRouter()
|
|||||||
|
|
||||||
register_gzip_request(router)
|
register_gzip_request(router)
|
||||||
|
|
||||||
|
|
||||||
def replace_placeholders(template):
|
def replace_placeholders(template):
|
||||||
# 匹配 <int>、<float>、<float1>、<float2> 等
|
# 匹配 <int>、<float>、<float1>、<float2> 等
|
||||||
pattern = re.compile(r'<(int|float\d*)>')
|
pattern = re.compile(r'<(int|float\d*)>')
|
||||||
@@ -30,44 +31,43 @@ def replace_placeholders(template):
|
|||||||
return pattern.sub(repl, template)
|
return pattern.sub(repl, template)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@router.get('/adventure')
|
@router.get('/adventure')
|
||||||
async def get_adventure_info(request: Request, redis: RedisDep):
|
async def get_adventure_info(request: Request, redis: RedisDep):
|
||||||
adventure_info = get_redis_info(redis, 'dcalc:adventure', get_adv_list)
|
adventure_info = get_redis_info(redis, 'dcalc:adventure', get_adv_list)
|
||||||
|
|
||||||
return response(data=adventure_info)
|
return response(data=adventure_info)
|
||||||
|
|
||||||
@router.get("/token/get/{alter}")
|
|
||||||
async def getToken(redis:RedisDep,
|
@router.get('/token/get/{alter}')
|
||||||
alter: str, request: Request, version: str = None, equVersion: str = "0"
|
async def getToken(redis: RedisDep, alter: str, request: Request, version: str = None, equVersion: str = '0'):
|
||||||
):
|
|
||||||
token = createToken(alter, equVersion, redis)
|
token = createToken(alter, equVersion, redis)
|
||||||
return response(data=token)
|
return response(data=token)
|
||||||
|
|
||||||
@router.get("/character")
|
|
||||||
async def get_character_info(
|
@router.get('/character')
|
||||||
request: Request, state: AltersDep ,redis:RedisDep
|
async def get_character_info(request: Request, state: AltersDep, redis: RedisDep):
|
||||||
):
|
|
||||||
character = createCharacter(state.alter, state.equVersion)
|
character = createCharacter(state.alter, state.equVersion)
|
||||||
|
|
||||||
def get_character():
|
def get_character():
|
||||||
return character.getInfo()
|
return character.getInfo()
|
||||||
info = get_redis_info(redis, f"dcalc:character:{state.alter}:{state.equVersion}", get_character)
|
|
||||||
|
info = get_redis_info(redis, f'dcalc:character:{state.alter}:{state.equVersion}', get_character)
|
||||||
# info = character.getInfo()
|
# info = character.getInfo()
|
||||||
return response(data=info)
|
return response(data=info)
|
||||||
|
|
||||||
@router.get("/skill/{skillId}/{level}")
|
|
||||||
async def get_skill_info(
|
@router.get('/skill/{skillId}/{level}')
|
||||||
state: AltersDep, skillId: str, level: int, redis: RedisDep
|
async def get_skill_info(state: AltersDep, skillId: str, level: int, redis: RedisDep):
|
||||||
):
|
|
||||||
"""
|
"""
|
||||||
获取技能信息
|
获取技能信息
|
||||||
"""
|
"""
|
||||||
alter = state.alter
|
alter = state.alter
|
||||||
jobId = alter.split(".")[1]
|
jobId = alter.split('.')[1]
|
||||||
jobGrowId = alter.split(".")[2]
|
jobGrowId = alter.split('.')[2]
|
||||||
skill_info = {}
|
skill_info = {}
|
||||||
key = f'openapi:{jobId}:{jobGrowId}:{skillId}'
|
key = f'openapi:{jobId}:{jobGrowId}:{skillId}'
|
||||||
try:
|
try:
|
||||||
|
|
||||||
def get_skill_info():
|
def get_skill_info():
|
||||||
# This function should retrieve the skill info based on job and jobGrow
|
# This function should retrieve the skill info based on job and jobGrow
|
||||||
# For now, we return a placeholder dictionary
|
# For now, we return a placeholder dictionary
|
||||||
@@ -97,7 +97,7 @@ async def get_skill_info(
|
|||||||
return response(data=skill_info)
|
return response(data=skill_info)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/dnfhelper/{uid}/")
|
@router.get('/dnfhelper/{uid}/')
|
||||||
async def get_info_by_dnfhelper(uid: str, state: AltersDep, redis: RedisDep):
|
async def get_info_by_dnfhelper(uid: str, state: AltersDep, redis: RedisDep):
|
||||||
try:
|
try:
|
||||||
result = await get_user_info_by_id(uid, state)
|
result = await get_user_info_by_id(uid, state)
|
||||||
@@ -105,17 +105,19 @@ async def get_info_by_dnfhelper(uid: str, state: AltersDep, redis: RedisDep):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
if isinstance(e, ResponseException):
|
if isinstance(e, ResponseException):
|
||||||
return response(code=500, message=str(e), data=None)
|
return response(code=500, message=str(e), data=None)
|
||||||
return response(code=500, message="Failed to fetch DNFHelper info", data=None)
|
print(e)
|
||||||
|
return response(code=500, message='Failed to fetch DNFHelper info', data=None)
|
||||||
|
|
||||||
@router.post("/skillTree/")
|
|
||||||
|
@router.post('/skillTree/')
|
||||||
async def get_skill_by_code(state: AltersDep, code=Body(None)):
|
async def get_skill_by_code(state: AltersDep, code=Body(None)):
|
||||||
try:
|
try:
|
||||||
skills = get_skill_tree_info(code.get("code", ""))
|
skills = get_skill_tree_info(code.get('code', ''))
|
||||||
if skills.get("job",{}).get("class","") != state.alter:
|
if skills.get('job', {}).get('class', '') != state.alter:
|
||||||
return response(code=500, message="技能加点代码职业与登录职业不匹配", data=None)
|
return response(code=500, message='技能加点代码职业与登录职业不匹配', data=None)
|
||||||
return response(data=skills)
|
return response(data=skills)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error fetching skill tree info: {e}")
|
print(f'Error fetching skill tree info: {e}')
|
||||||
if isinstance(e, ResponseException):
|
if isinstance(e, ResponseException):
|
||||||
return response(code=500, message=str(e), data=None)
|
return response(code=500, message=str(e), data=None)
|
||||||
return response(code=500, message="解析技能加点失败", data=None)
|
return response(code=500, message='解析技能加点失败', data=None)
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ class CalcEquipMixin(CharacterBase):
|
|||||||
max_point_oath_suit = max((suit for suit in oathSuitInfo if oathSuitInfo[suit]['point'] > 0), key=lambda suit: oathSuitInfo[suit]['point'], default=None)
|
max_point_oath_suit = max((suit for suit in oathSuitInfo if oathSuitInfo[suit]['point'] > 0), key=lambda suit: oathSuitInfo[suit]['point'], default=None)
|
||||||
zero_point_suits = [suit for suit in suitInfo if suitInfo[suit]['point'] == 0]
|
zero_point_suits = [suit for suit in suitInfo if suitInfo[suit]['point'] == 0]
|
||||||
# 套装没有到太初的时候,优先把誓约套装的点数加到装备套装上,以达到更高的套装等级
|
# 套装没有到太初的时候,优先把誓约套装的点数加到装备套装上,以达到更高的套装等级
|
||||||
if 0 < suitInfo[max_point_suit]['point'] < 2550 and oathSuitInfo.get('max_point_oath_suit', None) is not None:
|
if suitInfo is not None and 0 < suitInfo[max_point_suit]['point'] < 2550 and oathSuitInfo.get('max_point_oath_suit', None) is not None:
|
||||||
suitInfo[max_point_suit]['point'] += min(2550 - suitInfo[max_point_suit]['point'], oathSuitInfo[max_point_oath_suit]['point'])
|
suitInfo[max_point_suit]['point'] += min(2550 - suitInfo[max_point_suit]['point'], oathSuitInfo[max_point_oath_suit]['point'])
|
||||||
oathSuitInfo[max_point_oath_suit]['point'] -= min(2550 - suitInfo[max_point_suit]['point'], oathSuitInfo[max_point_oath_suit]['point'])
|
oathSuitInfo[max_point_oath_suit]['point'] -= min(2550 - suitInfo[max_point_suit]['point'], oathSuitInfo[max_point_oath_suit]['point'])
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -79,12 +79,12 @@ job_mapping = {
|
|||||||
|
|
||||||
async def get_user_info_by_id(user_id: str, alter: AltersDep):
|
async def get_user_info_by_id(user_id: str, alter: AltersDep):
|
||||||
if alter is None:
|
if alter is None:
|
||||||
raise ResponseException("登录过期或无效Token,请刷新后重试")
|
raise ResponseException('登录过期或无效Token,请刷新后重试')
|
||||||
name = next((k for k, v in job_mapping.items() if v == alter.origin), '')
|
name = next((k for k, v in job_mapping.items() if v == alter.origin), '')
|
||||||
# 通过OCR助手获取用户信息
|
# 通过OCR助手获取用户信息
|
||||||
helper_info = await get_main_user_info_by_id(user_id, name)
|
helper_info = await get_main_user_info_by_id(user_id, name)
|
||||||
if helper_info is None:
|
if helper_info is None:
|
||||||
raise ResponseException("当前助手ID不存在或已隐藏,请确认后重试")
|
raise ResponseException('当前助手ID不存在或已隐藏,请确认后重试')
|
||||||
else:
|
else:
|
||||||
return trans_to_dcalc_set(helper_info, alter)
|
return trans_to_dcalc_set(helper_info, alter)
|
||||||
pass
|
pass
|
||||||
@@ -93,7 +93,7 @@ async def get_user_info_by_id(user_id: str, alter: AltersDep):
|
|||||||
def trans_to_dcalc_set(detail, alter: AltersDep):
|
def trans_to_dcalc_set(detail, alter: AltersDep):
|
||||||
job = job_mapping.get(detail.get('job', ''), '')
|
job = job_mapping.get(detail.get('job', ''), '')
|
||||||
if job != alter.origin:
|
if job != alter.origin:
|
||||||
raise ResponseException("未能匹配到当前职业对应的角色信息,请确认后重试")
|
raise ResponseException('未能匹配到当前职业对应的角色信息,请确认后重试')
|
||||||
basic = get_equipment('0')
|
basic = get_equipment('0')
|
||||||
basicAvatars = basic.funs.get_dress_list([])
|
basicAvatars = basic.funs.get_dress_list([])
|
||||||
equs = detail.get('equs', [])
|
equs = detail.get('equs', [])
|
||||||
@@ -126,9 +126,9 @@ def trans_to_dcalc_set(detail, alter: AltersDep):
|
|||||||
# 贴膜
|
# 贴膜
|
||||||
if dcalcEqu:
|
if dcalcEqu:
|
||||||
info['id'] = dcalcEqu.id
|
info['id'] = dcalcEqu.id
|
||||||
dcalcEquFusion = next((item for item in basic.stones if item.name == equ.get('upgrade', '')), None)
|
# dcalcEquFusion = next((item for item in basic.stones if item.name == equ.get('upgrade', '')), None)
|
||||||
if dcalcEquFusion:
|
# if dcalcEquFusion:
|
||||||
info['fusion'] = dcalcEquFusion.id
|
# info['fusion'] = dcalcEquFusion.id
|
||||||
info['enchant'] = getEnchatIdByName(equ.get('enchant', ''), equ.get('posName', ''), basic.enchants)
|
info['enchant'] = getEnchatIdByName(equ.get('enchant', ''), equ.get('posName', ''), basic.enchants)
|
||||||
emblems = [getEmblemIdByName(i.get('detail', ''), i.get('categorize', ''), i.get('rarity', ''), basic.emblems) for i in equ.get('emblems', [])]
|
emblems = [getEmblemIdByName(i.get('detail', ''), i.get('categorize', ''), i.get('rarity', ''), basic.emblems) for i in equ.get('emblems', [])]
|
||||||
info['emblem_0'] = emblems[0] if len(emblems) > 0 else 0
|
info['emblem_0'] = emblems[0] if len(emblems) > 0 else 0
|
||||||
@@ -182,11 +182,14 @@ def trans_to_dcalc_set(detail, alter: AltersDep):
|
|||||||
'equips': equips,
|
'equips': equips,
|
||||||
'avatars': avatar,
|
'avatars': avatar,
|
||||||
'avatarLink': detail.get('avatarLink', ''),
|
'avatarLink': detail.get('avatarLink', ''),
|
||||||
'dressInfo': [{
|
'dressInfo': [
|
||||||
|
{
|
||||||
'dress': i.get('name', ''),
|
'dress': i.get('name', ''),
|
||||||
'clone': i.get('clone', ''),
|
'clone': i.get('clone', ''),
|
||||||
'part': i.get('posName', ''),
|
'part': i.get('posName', ''),
|
||||||
} for i in detail.get('avatars', [])]
|
}
|
||||||
|
for i in detail.get('avatars', [])
|
||||||
|
],
|
||||||
}
|
}
|
||||||
# 处理装备
|
# 处理装备
|
||||||
# 处理时装
|
# 处理时装
|
||||||
|
|||||||
Binary file not shown.
+1
-1
Submodule backend/openapi updated: 03f3bbf037...680ed85d6e
@@ -21,6 +21,7 @@ export interface IResultSkill {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IResultUserInfo {
|
export interface IResultUserInfo {
|
||||||
|
id: number
|
||||||
name: string
|
name: string
|
||||||
value: string | number
|
value: string | number
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,13 +72,13 @@ export interface IEquipment {
|
|||||||
Buffer: number[]
|
Buffer: number[]
|
||||||
detail: string
|
detail: string
|
||||||
bufferDetail: string
|
bufferDetail: string
|
||||||
}
|
|
||||||
|
|
||||||
export interface IOathInfo extends IEquipment {
|
|
||||||
position: string[]
|
position: string[]
|
||||||
wearUrl: string[]
|
wearUrl: string[]
|
||||||
|
oathPos: string
|
||||||
|
displayUrl?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export interface ISkill {
|
export interface ISkill {
|
||||||
icon: string
|
icon: string
|
||||||
name: string
|
name: string
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import {
|
|||||||
renderList,
|
renderList,
|
||||||
watch,
|
watch,
|
||||||
} from 'vue'
|
} from 'vue'
|
||||||
|
import { getElementZoom } from '@/utils/position'
|
||||||
|
|
||||||
type HandleChangeFunction = (value: string | number) => string[] | Promise<string[]>
|
type HandleChangeFunction = (value: string | number) => string[] | Promise<string[]>
|
||||||
|
|
||||||
@@ -55,10 +56,12 @@ export default defineComponent({
|
|||||||
function onResize() {
|
function onResize() {
|
||||||
if (triggerRef.value) {
|
if (triggerRef.value) {
|
||||||
const { width, height, left, top } = triggerRef.value.getBoundingClientRect()
|
const { width, height, left, top } = triggerRef.value.getBoundingClientRect()
|
||||||
|
const zoom = getElementZoom('body')
|
||||||
|
|
||||||
dropdownPosition.value = {
|
dropdownPosition.value = {
|
||||||
w: width,
|
w: width / zoom,
|
||||||
x: left,
|
x: left / zoom,
|
||||||
y: top + height + 2,
|
y: (top + height + 2) / zoom,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import type { CSSProperties, PropType } from 'vue'
|
|||||||
import { Teleport, Transition, computed, defineComponent, onDeactivated, ref, watch } from 'vue'
|
import { Teleport, Transition, computed, defineComponent, onDeactivated, ref, watch } from 'vue'
|
||||||
|
|
||||||
import { onClickOutside, useVModel } from '@vueuse/core'
|
import { onClickOutside, useVModel } from '@vueuse/core'
|
||||||
|
import { getElementZoom } from '@/utils/position'
|
||||||
interface ICascaderItem {
|
interface ICascaderItem {
|
||||||
label: string
|
label: string
|
||||||
id?: string | number
|
id?: string | number
|
||||||
@@ -74,18 +75,19 @@ export default defineComponent({
|
|||||||
function onResize() {
|
function onResize() {
|
||||||
if (triggerRef.value) {
|
if (triggerRef.value) {
|
||||||
const { width, height, left, top } = triggerRef.value.getBoundingClientRect()
|
const { width, height, left, top } = triggerRef.value.getBoundingClientRect()
|
||||||
|
const zoom = getElementZoom('body')
|
||||||
if (window.innerHeight - top > 160) {
|
if (window.innerHeight - top > 160) {
|
||||||
dropdownPosition.value = {
|
dropdownPosition.value = {
|
||||||
w: width,
|
w: width / zoom,
|
||||||
x: left,
|
x: left / zoom,
|
||||||
y: top + height + 2,
|
y: (top + height + 2) / zoom,
|
||||||
z: 0,
|
z: 0,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dropdownPosition.value = {
|
dropdownPosition.value = {
|
||||||
w: width,
|
w: width / zoom,
|
||||||
x: left,
|
x: left / zoom,
|
||||||
z: window.innerHeight - top + 2,
|
z: (window.innerHeight - top + 2) / zoom,
|
||||||
y: 0,
|
y: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
} from 'vue'
|
} from 'vue'
|
||||||
|
|
||||||
import { onClickOutside } from '@vueuse/core'
|
import { onClickOutside } from '@vueuse/core'
|
||||||
|
import { getElementZoom } from '@/utils/position'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'IIconselect',
|
name: 'IIconselect',
|
||||||
@@ -72,20 +73,24 @@ export default defineComponent({
|
|||||||
const dropdownPosition = ref({ x: 0, y: 0, w: 0 })
|
const dropdownPosition = ref({ x: 0, y: 0, w: 0 })
|
||||||
// 下拉框位置
|
// 下拉框位置
|
||||||
const dropdownStyle = computed<CSSProperties>(() => {
|
const dropdownStyle = computed<CSSProperties>(() => {
|
||||||
|
const zoom = getElementZoom(appendToRef.value)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
left: `${dropdownPosition.value.x}px`,
|
left: `${dropdownPosition.value.x}px`,
|
||||||
top: `${dropdownPosition.value.y}px`,
|
top: `${dropdownPosition.value.y}px`,
|
||||||
width: `${columnNum.value * 32 + 11}px`,
|
width: `${(columnNum.value * 32 + 11) / zoom}px`,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
function onResize() {
|
function onResize() {
|
||||||
if (triggerRef.value) {
|
if (triggerRef.value) {
|
||||||
const { width, height, left, top } = triggerRef.value.getBoundingClientRect()
|
const { width, height, left, top } = triggerRef.value.getBoundingClientRect()
|
||||||
|
const zoom = getElementZoom(appendToRef.value)
|
||||||
|
|
||||||
dropdownPosition.value = {
|
dropdownPosition.value = {
|
||||||
w: width,
|
w: width / zoom,
|
||||||
x: left - 2,
|
x: (left - 2) / zoom,
|
||||||
y: (top + height + 2),
|
y: (top + height + 2) / zoom,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import {
|
|||||||
|
|
||||||
import { onClickOutside, useVModel } from '@vueuse/core'
|
import { onClickOutside, useVModel } from '@vueuse/core'
|
||||||
import { classPropType, labelPropType } from '@/components/hooks/types'
|
import { classPropType, labelPropType } from '@/components/hooks/types'
|
||||||
|
import { getElementZoom } from '@/utils/position'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'ISelect',
|
name: 'ISelect',
|
||||||
@@ -98,18 +99,19 @@ export default defineComponent({
|
|||||||
function onResize() {
|
function onResize() {
|
||||||
if (triggerRef.value) {
|
if (triggerRef.value) {
|
||||||
const { width, height, left, top } = triggerRef.value.getBoundingClientRect()
|
const { width, height, left, top } = triggerRef.value.getBoundingClientRect()
|
||||||
|
const zoom = getElementZoom(appendToRef.value)
|
||||||
if (window.innerHeight - top > 160) {
|
if (window.innerHeight - top > 160) {
|
||||||
dropdownPosition.value = {
|
dropdownPosition.value = {
|
||||||
w: width,
|
w: width / zoom,
|
||||||
x: left,
|
x: left / zoom,
|
||||||
y: (top + height + 2),
|
y: (top + height + 2) / zoom,
|
||||||
z: 0,
|
z: 0,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dropdownPosition.value = {
|
dropdownPosition.value = {
|
||||||
w: width,
|
w: width / zoom,
|
||||||
x: left,
|
x: left / zoom,
|
||||||
z: (window.innerHeight - top + 2),
|
z: (window.innerHeight - top + 2) / zoom,
|
||||||
y: 0,
|
y: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,9 @@
|
|||||||
<div class="relative" :class="{ inactive: props.inactive }">
|
<div class="relative" :class="{ inactive: props.inactive }">
|
||||||
<div
|
<div
|
||||||
class="w-28px h-28px"
|
class="w-28px h-28px"
|
||||||
:style="{ backgroundImage: `url(${getImageURL(props.equipment?.imageUrl)})` }"
|
:style="{
|
||||||
|
backgroundImage: `url(${getImageURL((useDisplayUrl ? props.equipment?.displayUrl : props.equipment?.imageUrl) || '')})`,
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<img :src="getLocalImageURL(rarity)" />
|
<img :src="getLocalImageURL(rarity)" />
|
||||||
</div>
|
</div>
|
||||||
@@ -21,6 +23,7 @@ import { getImageURL } from '@/utils/images'
|
|||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
equipment?: IEquipment
|
equipment?: IEquipment
|
||||||
inactive?: boolean
|
inactive?: boolean
|
||||||
|
useDisplayUrl?: boolean
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const rarity = computed(() => {
|
const rarity = computed(() => {
|
||||||
|
|||||||
@@ -38,16 +38,12 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- 装备属性 -->
|
<!-- 装备属性 -->
|
||||||
<div class="divide"></div>
|
<div class="divide"></div>
|
||||||
<div
|
<div class="flex flex-col items-start my-1px whitespace-pre-wrap leading-15px">
|
||||||
class="flex flex-col items-start my-1px whitespace-pre-wrap leading-15px"
|
|
||||||
>
|
|
||||||
<div class="text-#DED29A py-4px whitespace-pre-wrap" v-html="detail"></div>
|
<div class="text-#DED29A py-4px whitespace-pre-wrap" v-html="detail"></div>
|
||||||
</div>
|
</div>
|
||||||
<template v-if="bufferDetail">
|
<template v-if="bufferDetail">
|
||||||
<div class="divide"></div>
|
<div class="divide"></div>
|
||||||
<div
|
<div class="flex flex-col items-start my-1px whitespace-pre-wrap leading-15px">
|
||||||
class="flex flex-col items-start my-1px whitespace-pre-wrap leading-15px"
|
|
||||||
>
|
|
||||||
<div class="text-#A48B2E mb-10px pt-4px">辅助职业专属属性</div>
|
<div class="text-#A48B2E mb-10px pt-4px">辅助职业专属属性</div>
|
||||||
<div class="text-#DED29A pb-10px whitespace-pre-wrap" v-html="bufferDetail"></div>
|
<div class="text-#DED29A pb-10px whitespace-pre-wrap" v-html="bufferDetail"></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -95,16 +91,18 @@ const mainAttr = computed(() => {
|
|||||||
// a.match(/\[(?!.*?技能).*?]/g)
|
// a.match(/\[(?!.*?技能).*?]/g)
|
||||||
|
|
||||||
const detail = computed(() =>
|
const detail = computed(() =>
|
||||||
props.equipment?.detail.replace(
|
props.equipment?.detail?.replace(
|
||||||
/\[(?![^\]]*技能)[^\[\]]+\]/g, match => `<span style="color:#3d9147">${match}</span>`
|
/\[(?![^\]]*技能)[^\[\]]+\]/g,
|
||||||
)
|
(match) => `<span style="color:#3d9147">${match}</span>`,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
const bufferDetail = computed(() => {
|
const bufferDetail = computed(() => {
|
||||||
const detail = props.equipment?.bufferDetail
|
const detail = props.equipment?.bufferDetail
|
||||||
if (!detail || detail == '-') return undefined
|
if (!detail || detail == '-') return undefined
|
||||||
return props.equipment?.bufferDetail.replace(
|
return props.equipment?.bufferDetail.replace(
|
||||||
/\[(?![^\]]*技能)[^\[\]]+\]/g, match => `<span style="color:#3d9147">${match}</span>`
|
/\[(?![^\]]*技能)[^\[\]]+\]/g,
|
||||||
|
(match) => `<span style="color:#3d9147">${match}</span>`,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ const equ = (id: string) => {
|
|||||||
|
|
||||||
const infoStyle = (part: string) => {
|
const infoStyle = (part: string) => {
|
||||||
let x = 10
|
let x = 10
|
||||||
let y = 5
|
let y = 10
|
||||||
let index = infoStore.parts.findIndex((p) => p == part)
|
let index = infoStore.parts.findIndex((p) => p == part)
|
||||||
if (index == 13) {
|
if (index == 13) {
|
||||||
index -= 7
|
index -= 7
|
||||||
|
|||||||
@@ -0,0 +1,182 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="pos-relative w-264px h-full"
|
||||||
|
:style="{ backgroundImage: withBg ? `url(${getImageURL('/common/oath/head.png')})` : 'none' }"
|
||||||
|
>
|
||||||
|
<template v-for="part in parts" :key="part">
|
||||||
|
<div
|
||||||
|
class="pos-absolute text-white/50 w-26px h-26px border-1px border-solid border-#7a7a7a/50 flex items-center justify-center"
|
||||||
|
:style="infoStyle(part)"
|
||||||
|
@click="choosePart(part)"
|
||||||
|
>
|
||||||
|
<template v-if="detail?.[part]?.id">
|
||||||
|
<EquipmentIcon :equipment="equ(detail[part].id, part)" useDisplayUrl />
|
||||||
|
</template>
|
||||||
|
<template v-else-if="!withBg">
|
||||||
|
{{ part != '11' ? '星蕴' : '誓约' }}
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
<!-- <div v-if="detail?.[part]?.fusion" class="pos-absolute" :style="fusionStyle(part)">
|
||||||
|
<EquipmentIcon :equipment="oaths(detail[part].fusion)" />
|
||||||
|
</div> -->
|
||||||
|
</template>
|
||||||
|
<!-- <img
|
||||||
|
v-if="props.avatar"
|
||||||
|
:src="props.avatar"
|
||||||
|
alt="Avatar"
|
||||||
|
class="pos-absolute w-70% left-1/2 translate-x--1/2 -bottom-10px"
|
||||||
|
/> -->
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup name="EquList">
|
||||||
|
import { getImageURL } from '@/utils/images'
|
||||||
|
import EquipmentIcon from '@/components/dnf/Equipment/Icon/index.vue'
|
||||||
|
import { useInfoStore, type IConfigOath } from '@/stores'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
withBg: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
detail: {
|
||||||
|
type: Object as PropType<Record<string, IConfigOath>>,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const partModelValue = defineModel('part', { default: '0' })
|
||||||
|
const infoStore = useInfoStore()
|
||||||
|
|
||||||
|
const parts = computed(() => {
|
||||||
|
const parts = infoStore.oathParts
|
||||||
|
return parts
|
||||||
|
})
|
||||||
|
|
||||||
|
const equ = (id: string, part: string) => {
|
||||||
|
return infoStore.oaths.find((e) => e.id == id && e.oathPos == part)
|
||||||
|
}
|
||||||
|
|
||||||
|
const position = [
|
||||||
|
{
|
||||||
|
x: 30,
|
||||||
|
y: 12,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: 30,
|
||||||
|
y: 46,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: 30,
|
||||||
|
y: 80.5,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: 30,
|
||||||
|
y: 114,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: 206,
|
||||||
|
y: 12,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: 206,
|
||||||
|
y: 46,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: 206,
|
||||||
|
y: 80.5,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: 206,
|
||||||
|
y: 114,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: 74,
|
||||||
|
y: 131.5,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: 118,
|
||||||
|
y: 145.5,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: 162,
|
||||||
|
y: 131.5,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: 118,
|
||||||
|
y: 111,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const positionSimple = [
|
||||||
|
{
|
||||||
|
x: 30,
|
||||||
|
y: 12,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: 30,
|
||||||
|
y: 46,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: 30,
|
||||||
|
y: 80.5,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: 30,
|
||||||
|
y: 114,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: 206,
|
||||||
|
y: 12,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: 206,
|
||||||
|
y: 46,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: 206,
|
||||||
|
y: 80.5,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: 206,
|
||||||
|
y: 114,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: 74,
|
||||||
|
y: 114,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: 118,
|
||||||
|
y: 114,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: 162,
|
||||||
|
y: 114,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: 118,
|
||||||
|
y: 80.5,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const infoStyle = (part: string) => {
|
||||||
|
if (props.withBg)
|
||||||
|
return {
|
||||||
|
left: `${position[parseInt(part)].x}px`,
|
||||||
|
top: `${position[parseInt(part)].y}px`,
|
||||||
|
zIndex: 6,
|
||||||
|
// fontWeight: 900,
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return {
|
||||||
|
left: `${positionSimple[parseInt(part)].x}px`,
|
||||||
|
top: `${positionSimple[parseInt(part)].y}px`,
|
||||||
|
zIndex: 6,
|
||||||
|
// fontWeight: 900,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const choosePart = (part: string) => {
|
||||||
|
partModelValue.value = part
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
`<!-- 每排总计6+4+4,共计14个排列 -->
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="flex flex-wrap gap-4px content-start" :style="{ width: `${rowCount * 32}px` }">
|
|
||||||
<template v-for="(equip, _) in equs" :key="_">
|
|
||||||
<EquipmentIcon
|
|
||||||
:inactive="configStore.config.equips[equip?.itemDetailType ?? '']?.fusion != equip?.id"
|
|
||||||
:equipment="equip"
|
|
||||||
@click="configStore.chooseEqu(equip, true)"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup StoneUniversal>
|
|
||||||
import type { IEquipment } from '@/api/info/type'
|
|
||||||
import { useConfigStore, useInfoStore } from '@/stores'
|
|
||||||
import { getImageURL } from '@/utils/images'
|
|
||||||
import EquipmentIcon from '@/components/dnf/Equipment/Icon/index.vue'
|
|
||||||
|
|
||||||
const props = defineProps<{
|
|
||||||
rowCount?: number
|
|
||||||
}>()
|
|
||||||
|
|
||||||
const rowCount = Math.max(props.rowCount ?? 0, 14)
|
|
||||||
const infoStore = useInfoStore()
|
|
||||||
const configStore = useConfigStore()
|
|
||||||
|
|
||||||
const equs = computed(() => {
|
|
||||||
const items = infoStore.stones.filter((equip) => equip.categorize.includes('神界'))
|
|
||||||
const res: (IEquipment | undefined)[] = []
|
|
||||||
res.push(
|
|
||||||
...items.filter((a) => a.rarity === '太初'),
|
|
||||||
...Array(Math.max(0, rowCount - items.filter((a) => a.rarity === '太初').length)).fill(
|
|
||||||
undefined,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
;['手镯', '项链', '戒指', '', '辅助装备', '魔法石', '耳环', ''].forEach((cat) => {
|
|
||||||
const equ: (IEquipment | undefined)[] = items.filter(
|
|
||||||
(a) => a.rarity === '史诗' && a.itemDetailType == cat,
|
|
||||||
)
|
|
||||||
res.push(...equ, ...Array(Math.max(0, 7 - equ.length)).fill(undefined))
|
|
||||||
})
|
|
||||||
|
|
||||||
// const categorize = Array.from(new Set(items.map((item) => item.categorize)))
|
|
||||||
// raritiyList.forEach((rarity) => {
|
|
||||||
// categorize.forEach((cat) => {
|
|
||||||
// const equ : (IEquipment | undefined)[] = items.filter((a) => a.rarity === rarity && a.categorize === cat)
|
|
||||||
// equ.splice(5,0,undefined)
|
|
||||||
// res.push(
|
|
||||||
// ...equ,
|
|
||||||
// ...Array(Math.max(0,rowCount - equ.length)).fill(undefined),
|
|
||||||
// )
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
return res
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
`
|
|
||||||
@@ -15,7 +15,6 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { IEquipment } from '@/api/info/type'
|
import type { IEquipment } from '@/api/info/type'
|
||||||
import { useConfigStore, useInfoStore } from '@/stores'
|
import { useConfigStore, useInfoStore } from '@/stores'
|
||||||
import { getImageURL } from '@/utils/images'
|
|
||||||
import EquipmentIcon from '@/components/dnf/Equipment/Icon/index.vue'
|
import EquipmentIcon from '@/components/dnf/Equipment/Icon/index.vue'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ import PartSelect from '@/components/dnf/Equipment/PartSelect/index.vue'
|
|||||||
import EquipmentRaritySelect from '@/components/dnf/Equipment/RaritySelect/index.vue'
|
import EquipmentRaritySelect from '@/components/dnf/Equipment/RaritySelect/index.vue'
|
||||||
import { getImageURL } from '@/utils/images'
|
import { getImageURL } from '@/utils/images'
|
||||||
import { rarityClass } from '@/utils'
|
import { rarityClass } from '@/utils'
|
||||||
import type { IEquipment, IOathInfo } from '@/api/info/type'
|
import type { IEquipment } from '@/api/info/type'
|
||||||
import EquipmentIcon from '@/components/dnf/Equipment/Icon/index.vue'
|
import EquipmentIcon from '@/components/dnf/Equipment/Icon/index.vue'
|
||||||
import Info from '@/components/dnf/Equipment/Info/index.vue'
|
import Info from '@/components/dnf/Equipment/Info/index.vue'
|
||||||
import SuitInfo from '@/components/dnf/Equipment/SuitInfo/index.vue'
|
import SuitInfo from '@/components/dnf/Equipment/SuitInfo/index.vue'
|
||||||
@@ -259,7 +259,7 @@ const equs = computed(() => {
|
|||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
return formatOath(
|
return formatOath(
|
||||||
total as unknown as IOathInfo[],
|
total as unknown as IEquipment[],
|
||||||
suitList.value.find((a) => a.value == curSuit.value),
|
suitList.value.find((a) => a.value == curSuit.value),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -275,7 +275,7 @@ const isActive = computed(() => {
|
|||||||
return configStore.config.equips[item.itemDetailType].id == item.id
|
return configStore.config.equips[item.itemDetailType].id == item.id
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// return configStore.config.equips[item.itemDetailType].fusion == item.id
|
return configStore.config.oaths[item.oathPos].id == item.id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -288,8 +288,8 @@ const chooseEqu = (item?: IEquipment) => {
|
|||||||
? configStore.config.equips[
|
? configStore.config.equips[
|
||||||
item.itemType.includes('武器') ? item.itemType : item.itemDetailType
|
item.itemType.includes('武器') ? item.itemType : item.itemDetailType
|
||||||
]
|
]
|
||||||
: configStore.config.equips[item.itemDetailType]
|
: configStore.config.oaths[item.oathPos]
|
||||||
target[type.value === 'equ' ? 'id' : 'fusion'] = isActive.value(item) ? '' : item.id
|
target['id'] = isActive.value(item) ? '' : item.id
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { IEquipment, IOathInfo } from '@/api/info/type'
|
import type { IEquipment } from '@/api/info/type'
|
||||||
|
|
||||||
export const rowCount = 10
|
export const rowCount = 10
|
||||||
|
|
||||||
@@ -293,7 +293,7 @@ export const formatStone = (total: IEquipment[], curSuit?: string) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const formatOath = (
|
export const formatOath = (
|
||||||
total: IOathInfo[],
|
total: IEquipment[],
|
||||||
curSuit?: { name: string; value: number; imageUrl: string },
|
curSuit?: { name: string; value: number; imageUrl: string },
|
||||||
) => {
|
) => {
|
||||||
// oath
|
// oath
|
||||||
@@ -303,7 +303,7 @@ export const formatOath = (
|
|||||||
const primer = []
|
const primer = []
|
||||||
const primerItem = total.filter((equip) => equip.itemDetailType == '星蕴石')
|
const primerItem = total.filter((equip) => equip.itemDetailType == '星蕴石')
|
||||||
for (let i = 0; i < 11; i++) {
|
for (let i = 0; i < 11; i++) {
|
||||||
const temp = primerItem.filter((a) => a.position.includes(i.toString()))
|
const temp = primerItem.filter((a) => a.oathPos == i.toString())
|
||||||
primer.push(
|
primer.push(
|
||||||
...temp,
|
...temp,
|
||||||
...Array(temp.length == 0 ? rowCount : rowCount - (temp.length % rowCount)).fill(undefined),
|
...Array(temp.length == 0 ? rowCount : rowCount - (temp.length % rowCount)).fill(undefined),
|
||||||
|
|||||||
@@ -5,14 +5,12 @@ import { useInfoStore, useConfigStore } from '@/stores'
|
|||||||
import ClothList from '@/components/dnf/Avatar/List/index.vue'
|
import ClothList from '@/components/dnf/Avatar/List/index.vue'
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'Clothes',
|
name: 'Clothes',
|
||||||
setup(props) {
|
setup() {
|
||||||
const configStore = useConfigStore()
|
const configStore = useConfigStore()
|
||||||
const part = ref('武器装扮')
|
const part = ref('武器装扮')
|
||||||
|
|
||||||
// const globalStore = useGlobalStore()
|
// const globalStore = useGlobalStore()
|
||||||
|
|
||||||
/** 是否有徽章 */
|
|
||||||
const has_socket = computed(() => ['武器装扮', '光环', '皮肤'].includes(part.value as string))
|
|
||||||
const basicInfoStore = useInfoStore()
|
const basicInfoStore = useInfoStore()
|
||||||
const has_enchant = computed(() => {
|
const has_enchant = computed(() => {
|
||||||
return !['头部', '帽子', '脸部', '胸部', '上衣', '腰带', '下装', '鞋'].includes(
|
return !['头部', '帽子', '脸部', '胸部', '上衣', '腰带', '下装', '鞋'].includes(
|
||||||
@@ -26,9 +24,9 @@ export default defineComponent({
|
|||||||
.sort((a, b) => (b.fame ?? 0) - (a.fame ?? 0))
|
.sort((a, b) => (b.fame ?? 0) - (a.fame ?? 0))
|
||||||
})
|
})
|
||||||
|
|
||||||
const emblem_list = computed<IEnchantingInfo[] | undefined>(() => {
|
// const emblem_list = computed<IEnchantingInfo[] | undefined>(() => {
|
||||||
return basicInfoStore.emblems.filter((item) => item.position.includes(part.value))
|
// return basicInfoStore.emblems.filter((item) => item.position.includes(part.value))
|
||||||
})
|
// })
|
||||||
|
|
||||||
const currentInfo = function <T>(name: string, defaultValue?: T) {
|
const currentInfo = function <T>(name: string, defaultValue?: T) {
|
||||||
return computed<string | number>({
|
return computed<string | number>({
|
||||||
@@ -36,7 +34,7 @@ export default defineComponent({
|
|||||||
let key: 'avatar' | 'equips' = 'avatar'
|
let key: 'avatar' | 'equips' = 'avatar'
|
||||||
if (part.value == '宠物') key = 'equips'
|
if (part.value == '宠物') key = 'equips'
|
||||||
return (
|
return (
|
||||||
(configStore.config[key]?.[part.value] as Record<string, any>)?.[name] ??
|
(configStore.config[key]?.[part.value] as Record<string, string | number>)?.[name] ??
|
||||||
defaultValue ??
|
defaultValue ??
|
||||||
0
|
0
|
||||||
)
|
)
|
||||||
@@ -48,10 +46,13 @@ export default defineComponent({
|
|||||||
let key: 'avatar' | 'equips' = 'avatar'
|
let key: 'avatar' | 'equips' = 'avatar'
|
||||||
if (part.value == '宠物') key = 'equips'
|
if (part.value == '宠物') key = 'equips'
|
||||||
if (!configStore.config[key][part.value]) {
|
if (!configStore.config[key][part.value]) {
|
||||||
configStore.config[key][part.value] = key === 'avatar' ? { ...configStore.defaultAvatarConfig } : { ...configStore.defaultEqusConfig }
|
configStore.config[key][part.value] =
|
||||||
|
key === 'avatar'
|
||||||
|
? { ...configStore.defaultAvatarConfig }
|
||||||
|
: { ...configStore.defaultEqusConfig }
|
||||||
}
|
}
|
||||||
if (configStore.config[key][part.value]) {
|
if (configStore.config[key][part.value]) {
|
||||||
;(configStore.config[key][part.value] as Record<string, any>)[name] = val
|
;(configStore.config[key][part.value] as Record<string, string | number>)[name] = val
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -60,11 +61,11 @@ export default defineComponent({
|
|||||||
// 附魔
|
// 附魔
|
||||||
const enchant = currentInfo<string | number>('enchant')
|
const enchant = currentInfo<string | number>('enchant')
|
||||||
|
|
||||||
// 镶嵌栏1
|
// // 镶嵌栏1
|
||||||
const emblem_0 = currentInfo<string | number>('emblem_0', 0)
|
// const emblem_0 = currentInfo<string | number>('emblem_0', 0)
|
||||||
|
|
||||||
// 镶嵌栏2
|
// // 镶嵌栏2
|
||||||
const emblem_1 = currentInfo<string | number>('emblem_1')
|
// const emblem_1 = currentInfo<string | number>('emblem_1')
|
||||||
|
|
||||||
// 品级
|
// 品级
|
||||||
const id = currentInfo<string | number>('id')
|
const id = currentInfo<string | number>('id')
|
||||||
@@ -76,9 +77,9 @@ export default defineComponent({
|
|||||||
* 同步徽章1到徽章2
|
* 同步徽章1到徽章2
|
||||||
* @param val
|
* @param val
|
||||||
*/
|
*/
|
||||||
function changeSocket(val: number) {
|
// function changeSocket(val: number) {
|
||||||
emblem_1.value = val
|
// emblem_1.value = val
|
||||||
}
|
// }
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
return (
|
return (
|
||||||
@@ -127,33 +128,6 @@ export default defineComponent({
|
|||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{has_socket.value ? (
|
|
||||||
<div class="equ-profile-item">
|
|
||||||
<div class="row-name">徽章</div>
|
|
||||||
<calc-select
|
|
||||||
onChange={changeSocket}
|
|
||||||
v-model={emblem_0.value}
|
|
||||||
class="flex-1 !h-20px"
|
|
||||||
>
|
|
||||||
<calc-option value={0}>无</calc-option>
|
|
||||||
{renderList(emblem_list.value ?? [], (item) => (
|
|
||||||
<calc-option
|
|
||||||
value={item.id}
|
|
||||||
>{`${item.rarity}${item.categorize}徽章[${item.detail}]`}</calc-option>
|
|
||||||
))}
|
|
||||||
</calc-select>
|
|
||||||
<calc-select v-model={emblem_1.value} class="flex-1 !h-20px">
|
|
||||||
<calc-option value={0}>无</calc-option>
|
|
||||||
{renderList(emblem_list.value ?? [], (item) => (
|
|
||||||
<calc-option
|
|
||||||
value={item.id}
|
|
||||||
>{`${item.rarity}${item.categorize}徽章[${item.detail}]`}</calc-option>
|
|
||||||
))}
|
|
||||||
</calc-select>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div></div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<template>
|
||||||
|
<div></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup name="Emblems"></script>
|
||||||
@@ -6,7 +6,7 @@ import EquList from '@/components/dnf/Equipment/List/index.vue'
|
|||||||
import { getImageURL } from '@/utils/images'
|
import { getImageURL } from '@/utils/images'
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'Equip',
|
name: 'Equip',
|
||||||
setup(props) {
|
setup() {
|
||||||
const configStore = useConfigStore()
|
const configStore = useConfigStore()
|
||||||
const part = ref('头肩')
|
const part = ref('头肩')
|
||||||
const can_upgrade = computed(() => {
|
const can_upgrade = computed(() => {
|
||||||
@@ -15,14 +15,6 @@ export default defineComponent({
|
|||||||
|
|
||||||
// const globalStore = useGlobalStore()
|
// const globalStore = useGlobalStore()
|
||||||
|
|
||||||
/** 是否有徽章 */
|
|
||||||
const has_socket = computed(
|
|
||||||
() => !['称号', '宠物', '耳环', '武器'].includes(part.value as string),
|
|
||||||
)
|
|
||||||
/** 是否有右侧徽章 */
|
|
||||||
const has_emblem_1 = computed(
|
|
||||||
() => has_socket.value && !['辅助装备', '魔法石'].includes(part.value as string),
|
|
||||||
)
|
|
||||||
/** 是否可以设置秘宝精度 */
|
/** 是否可以设置秘宝精度 */
|
||||||
const can_set_secret = computed(() => {
|
const can_set_secret = computed(() => {
|
||||||
return ['武器', '辅助装备', '魔法石', '耳环'].includes(part.value as string)
|
return ['武器', '辅助装备', '魔法石', '耳环'].includes(part.value as string)
|
||||||
@@ -40,9 +32,9 @@ export default defineComponent({
|
|||||||
.sort((a, b) => (b.fame ?? 0) - (a.fame ?? 0))
|
.sort((a, b) => (b.fame ?? 0) - (a.fame ?? 0))
|
||||||
})
|
})
|
||||||
|
|
||||||
const emblem_list = computed<IEnchantingInfo[] | undefined>(() => {
|
// const emblem_list = computed<IEnchantingInfo[] | undefined>(() => {
|
||||||
return basicInfoStore.emblems.filter((item) => item.position.includes(part.value))
|
// return basicInfoStore.emblems.filter((item) => item.position.includes(part.value))
|
||||||
})
|
// })
|
||||||
|
|
||||||
const global_change = ref(false)
|
const global_change = ref(false)
|
||||||
|
|
||||||
@@ -50,6 +42,7 @@ export default defineComponent({
|
|||||||
return computed<string | number>({
|
return computed<string | number>({
|
||||||
get() {
|
get() {
|
||||||
return (
|
return (
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
(configStore.config.equips?.[part.value] as Record<string, any>)?.[name] ??
|
(configStore.config.equips?.[part.value] as Record<string, any>)?.[name] ??
|
||||||
defaultValue ??
|
defaultValue ??
|
||||||
0
|
0
|
||||||
@@ -59,10 +52,10 @@ export default defineComponent({
|
|||||||
if (val == undefined && name !== 'weaponFusion') {
|
if (val == undefined && name !== 'weaponFusion') {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (name == 'emblem_1' && !has_emblem_1.value) {
|
// if (name == 'emblem_1' && !has_emblem_1.value) {
|
||||||
// configStore.setForge(part.value, name, 0)
|
// // configStore.setForge(part.value, name, 0)
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
|
|
||||||
let parts: string[] = []
|
let parts: string[] = []
|
||||||
|
|
||||||
@@ -75,16 +68,16 @@ export default defineComponent({
|
|||||||
parts = enchant.position
|
parts = enchant.position
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (['emblem_0', 'emblem_1'].includes(name)) {
|
// if (['emblem_0', 'emblem_1'].includes(name)) {
|
||||||
const emblem = basicInfoStore?.emblems?.find(
|
// const emblem = basicInfoStore?.emblems?.find(
|
||||||
(item) => item.id.toString() == val.toString(),
|
// (item) => item.id.toString() == val.toString(),
|
||||||
) as IEnchantingInfo | undefined
|
// ) as IEnchantingInfo | undefined
|
||||||
if (emblem?.position) {
|
// if (emblem?.position) {
|
||||||
parts = emblem.position.filter(
|
// parts = emblem.position.filter(
|
||||||
(item) => !['皮肤', '武器装扮', '光环'].includes(item),
|
// (item) => !['皮肤', '武器装扮', '光环'].includes(item),
|
||||||
)
|
// )
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
if (['reinforceType', 'reinforce', 'adaptation'].includes(name)) {
|
if (['reinforceType', 'reinforce', 'adaptation'].includes(name)) {
|
||||||
parts = basicInfoStore.parts.filter((e) => !['称号', '宠物'].includes(e))
|
parts = basicInfoStore.parts.filter((e) => !['称号', '宠物'].includes(e))
|
||||||
}
|
}
|
||||||
@@ -96,6 +89,7 @@ export default defineComponent({
|
|||||||
configStore.config.equips[part] = { ...configStore.defaultEqusConfig }
|
configStore.config.equips[part] = { ...configStore.defaultEqusConfig }
|
||||||
}
|
}
|
||||||
if (configStore.config.equips[part]) {
|
if (configStore.config.equips[part]) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
;(configStore.config.equips[part] as Record<string, any>)[name] = val
|
;(configStore.config.equips[part] as Record<string, any>)[name] = val
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -106,11 +100,11 @@ export default defineComponent({
|
|||||||
// 附魔
|
// 附魔
|
||||||
const enchant = currentInfo<string | number>('enchant')
|
const enchant = currentInfo<string | number>('enchant')
|
||||||
|
|
||||||
// 镶嵌栏1
|
// // 镶嵌栏1
|
||||||
const emblem_0 = currentInfo<string | number>('emblem_0', 0)
|
// const emblem_0 = currentInfo<string | number>('emblem_0', 0)
|
||||||
|
|
||||||
// 镶嵌栏2
|
// // 镶嵌栏2
|
||||||
const emblem_1 = currentInfo<string | number>('emblem_1')
|
// const emblem_1 = currentInfo<string | number>('emblem_1')
|
||||||
|
|
||||||
// 增幅
|
// 增幅
|
||||||
const reinforce_type = currentInfo<string | number>('reinforceType', 1)
|
const reinforce_type = currentInfo<string | number>('reinforceType', 1)
|
||||||
@@ -133,11 +127,11 @@ export default defineComponent({
|
|||||||
* 同步徽章1到徽章2
|
* 同步徽章1到徽章2
|
||||||
* @param val
|
* @param val
|
||||||
*/
|
*/
|
||||||
function changeSocket(val: number) {
|
// function changeSocket(val: number) {
|
||||||
if (has_emblem_1.value) {
|
// if (has_emblem_1.value) {
|
||||||
emblem_1.value = val
|
// emblem_1.value = val
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
const setWeaponFusion = (val: number) => {
|
const setWeaponFusion = (val: number) => {
|
||||||
if (val == weaponFusion.value) {
|
if (val == weaponFusion.value) {
|
||||||
@@ -240,37 +234,6 @@ export default defineComponent({
|
|||||||
))}
|
))}
|
||||||
</calc-select>
|
</calc-select>
|
||||||
</div>
|
</div>
|
||||||
{has_socket.value ? (
|
|
||||||
<div class="equ-profile-item">
|
|
||||||
<div class="row-name">徽章</div>
|
|
||||||
<calc-select
|
|
||||||
onChange={changeSocket}
|
|
||||||
v-model={emblem_0.value}
|
|
||||||
class="flex-1 !h-20px"
|
|
||||||
>
|
|
||||||
<calc-option value={''}>无</calc-option>
|
|
||||||
{renderList(emblem_list.value ?? [], (item) => (
|
|
||||||
<calc-option
|
|
||||||
value={item.id}
|
|
||||||
key={item.id}
|
|
||||||
>{`${item.rarity}${item.categorize}徽章[${item.detail}]`}</calc-option>
|
|
||||||
))}
|
|
||||||
</calc-select>
|
|
||||||
{has_emblem_1.value && (
|
|
||||||
<calc-select v-model={emblem_1.value} class="flex-1 !h-20px">
|
|
||||||
<calc-option value={''}>无</calc-option>
|
|
||||||
{renderList(emblem_list.value ?? [], (item) => (
|
|
||||||
<calc-option
|
|
||||||
value={item.id}
|
|
||||||
key={item.id}
|
|
||||||
>{`${item.rarity}${item.categorize}徽章[${item.detail}]`}</calc-option>
|
|
||||||
))}
|
|
||||||
</calc-select>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div></div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{can_upgrade.value ? (
|
{can_upgrade.value ? (
|
||||||
<div class="equ-profile-item">
|
<div class="equ-profile-item">
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<div class="flex gap-2 mt-5px">
|
<div class="flex gap-2 mt-5px">
|
||||||
<calc-select class="flex-1 !h-20px" v-model="configStore.config.jades[key].id">
|
<calc-select class="flex-1 !h-20px" v-model="configStore.config.jades[key].id">
|
||||||
<calc-option :value="0">无</calc-option>
|
<calc-option :value="0">无</calc-option>
|
||||||
<calc-option v-for="(item, index) in infoStore.jades" :key="item.id" :value="item.id">
|
<calc-option v-for="item in infoStore.jades" :key="item.id" :value="item.id">
|
||||||
{{ item.name }}
|
{{ item.name }}
|
||||||
</calc-option>
|
</calc-option>
|
||||||
</calc-select>
|
</calc-select>
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
></calc-slider> -->
|
></calc-slider> -->
|
||||||
<calc-select class="flex-1 !h-20px" v-model="configStore.config.jades[key].value">
|
<calc-select class="flex-1 !h-20px" v-model="configStore.config.jades[key].value">
|
||||||
<calc-option
|
<calc-option
|
||||||
v-for="(item, index) in valueList(configStore.config.jades[key].id)"
|
v-for="item in valueList(configStore.config.jades[key].id)"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
:value="item.id"
|
:value="item.id"
|
||||||
>
|
>
|
||||||
@@ -38,26 +38,25 @@ import { getFloat } from '@/utils'
|
|||||||
const configStore = useConfigStore()
|
const configStore = useConfigStore()
|
||||||
const infoStore = useInfoStore()
|
const infoStore = useInfoStore()
|
||||||
|
|
||||||
const currentJade = computed(() => {
|
// const currentJade = computed(() => {
|
||||||
return function (id: number = -1) {
|
// return function (id: number = -1) {
|
||||||
if (id == -1) {
|
// if (id == -1) {
|
||||||
return undefined
|
// return undefined
|
||||||
} else {
|
// } else {
|
||||||
const res = []
|
// const cur = infoStore.jades?.find((e) => e.id == id) as IJade
|
||||||
const cur = infoStore.jades?.find((e) => e.id == id) as IJade
|
// return cur
|
||||||
return cur
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// })
|
||||||
})
|
|
||||||
|
|
||||||
const formatValue = (id: number) => {
|
// const formatValue = (id: number) => {
|
||||||
return (value: number) => {
|
// return (value: number) => {
|
||||||
if (currentJade.value(id)?.unit.includes('等级')) {
|
// if (currentJade.value(id)?.unit.includes('等级')) {
|
||||||
return `$等级 +${value}`
|
// return `$等级 +${value}`
|
||||||
}
|
// }
|
||||||
return `${getFloat(value, 1)}${currentJade.value(id)?.unit}`
|
// return `${getFloat(value, 1)}${currentJade.value(id)?.unit}`
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
const valueList = computed(() => {
|
const valueList = computed(() => {
|
||||||
return function (id: number = -1) {
|
return function (id: number = -1) {
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
<template>
|
||||||
|
<div class="h-150px flex justify-center items-center">
|
||||||
|
<Oath v-model:part="part" :withBg="false" />
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-wrap equ-profile">
|
||||||
|
<div class="equ-profile-item">
|
||||||
|
<div class="mr-10px row-name">当前部位</div>
|
||||||
|
<span>{{ part == '11' ? '誓约' : `星蕴石-${parseInt(part) + 1}` }}</span>
|
||||||
|
<calc-checkbox
|
||||||
|
style="margin-left: auto"
|
||||||
|
v-model="global_change"
|
||||||
|
label="全局修改"
|
||||||
|
></calc-checkbox>
|
||||||
|
</div>
|
||||||
|
<div class="equ-profile-item">
|
||||||
|
<div class="row-name">调适</div>
|
||||||
|
<calc-select v-model="adaptation" class="flex-1 !h-20px">
|
||||||
|
<template v-for="i in Array.from({ length: 4 }, (_, i) => i)" :key="i">
|
||||||
|
<calc-option :value="i">{{ i }}</calc-option>
|
||||||
|
</template>
|
||||||
|
</calc-select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup name="Oaths">
|
||||||
|
import Oath from '@/components/dnf/Equipment/Oath/index.vue'
|
||||||
|
import { useConfigStore, useInfoStore } from '@/stores'
|
||||||
|
|
||||||
|
const part = ref('0')
|
||||||
|
|
||||||
|
const global_change = ref(false)
|
||||||
|
|
||||||
|
const configStore = useConfigStore()
|
||||||
|
|
||||||
|
const infoStore = useInfoStore()
|
||||||
|
|
||||||
|
const currentInfo = function <T>(name: string, defaultValue?: T) {
|
||||||
|
return computed<string | number>({
|
||||||
|
get() {
|
||||||
|
return (
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
(configStore.config.oaths?.[part.value] as Record<string, any>)?.[name] ?? defaultValue ?? 0
|
||||||
|
)
|
||||||
|
},
|
||||||
|
set(val) {
|
||||||
|
if (val == undefined) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// if (name == 'emblem_1' && !has_emblem_1.value) {
|
||||||
|
// // configStore.setForge(part.value, name, 0)
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
|
||||||
|
let parts: string[] = []
|
||||||
|
|
||||||
|
if (global_change.value) {
|
||||||
|
parts = infoStore.oathParts
|
||||||
|
} else {
|
||||||
|
parts = [part.value]
|
||||||
|
}
|
||||||
|
for (const part of parts) {
|
||||||
|
if (!configStore.config.oaths[part]) {
|
||||||
|
configStore.config.oaths[part] = { ...configStore.defaultOathConfig }
|
||||||
|
}
|
||||||
|
if (configStore.config.oaths[part]) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
;(configStore.config.oaths[part] as Record<string, any>)[name] = val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调适
|
||||||
|
const adaptation = currentInfo<string | number>('adaptation')
|
||||||
|
</script>
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
class="flex-1 !h-20px"
|
class="flex-1 !h-20px"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="equ-profile-item">
|
<!-- <div class="equ-profile-item">
|
||||||
<div class="row-name">勋章</div>
|
<div class="row-name">勋章</div>
|
||||||
<calc-select
|
<calc-select
|
||||||
v-for="(key, index) in ['medal_rarity', 'medal_reinforce']"
|
v-for="(key, index) in ['medal_rarity', 'medal_reinforce']"
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
{{ item.name }}
|
{{ item.name }}
|
||||||
</calc-option>
|
</calc-option>
|
||||||
</calc-select>
|
</calc-select>
|
||||||
</div>
|
</div> -->
|
||||||
<div class="equ-profile-item">
|
<div class="equ-profile-item">
|
||||||
<div class="row-name">冒险团</div>
|
<div class="row-name">冒险团</div>
|
||||||
<calc-slider
|
<calc-slider
|
||||||
|
|||||||
@@ -2,11 +2,15 @@
|
|||||||
<div class="w-420px overflow-auto">
|
<div class="w-420px overflow-auto">
|
||||||
<calc-collapse class="w-100%" title="装备/时装打造(点击部位切换)">
|
<calc-collapse class="w-100%" title="装备/时装打造(点击部位切换)">
|
||||||
<calc-tabs v-model="partTab" class="!mb-2">
|
<calc-tabs v-model="partTab" class="!mb-2">
|
||||||
<calc-tab :value="0">装备栏</calc-tab>
|
<calc-tab :value="0">装备</calc-tab>
|
||||||
<calc-tab :value="1">时装栏</calc-tab>
|
<calc-tab :value="2">誓约</calc-tab>
|
||||||
|
<calc-tab :value="1">时装</calc-tab>
|
||||||
|
<calc-tab :value="3">徽章</calc-tab>
|
||||||
</calc-tabs>
|
</calc-tabs>
|
||||||
<equipment v-if="partTab === 0"></equipment>
|
<equipment v-if="partTab === 0"></equipment>
|
||||||
<clothes v-if="partTab === 1"></clothes>
|
<clothes v-if="partTab === 1"></clothes>
|
||||||
|
<oaths v-if="partTab === 2"></oaths>
|
||||||
|
<emblems v-if="partTab === 3"></emblems>
|
||||||
</calc-collapse>
|
</calc-collapse>
|
||||||
<calc-collapse class="w-100%" title="辟邪玉">
|
<calc-collapse class="w-100%" title="辟邪玉">
|
||||||
<jade></jade>
|
<jade></jade>
|
||||||
@@ -19,6 +23,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import equipment from './components/Equipments.vue'
|
import equipment from './components/Equipments.vue'
|
||||||
import clothes from './components/Avatars.vue'
|
import clothes from './components/Avatars.vue'
|
||||||
|
import emblems from './components/Emblems.vue'
|
||||||
|
import oaths from './components/Oaths.vue'
|
||||||
import jade from './components/Jades.vue'
|
import jade from './components/Jades.vue'
|
||||||
import sundry from './components/Sundry.vue'
|
import sundry from './components/Sundry.vue'
|
||||||
const partTab = ref(0)
|
const partTab = ref(0)
|
||||||
|
|||||||
@@ -5,11 +5,30 @@
|
|||||||
<calc-button class="flex-1" @click="setStandard">设为基准</calc-button>
|
<calc-button class="flex-1" @click="setStandard">设为基准</calc-button>
|
||||||
<calc-button class="flex-1" @click="clearStandard">清空基准</calc-button>
|
<calc-button class="flex-1" @click="clearStandard">清空基准</calc-button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex bg-#101012 h-40px text-#6C5E4A font-bold z-10">
|
||||||
|
<div
|
||||||
|
class="flex-1 text-15px flex items-center justify-center"
|
||||||
|
@click="chooseCategory('equ')"
|
||||||
|
:class="{ active: type === 'equ' }"
|
||||||
|
>
|
||||||
|
装备
|
||||||
|
</div>
|
||||||
|
<div class="w-auto text-18px flex items-center justify-center !font-normal">|</div>
|
||||||
|
<div
|
||||||
|
class="flex-1 text-15px flex items-center justify-center"
|
||||||
|
@click="chooseCategory('oath')"
|
||||||
|
:class="{ active: type === 'oath' }"
|
||||||
|
>
|
||||||
|
誓约
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<Info
|
<Info
|
||||||
:suits="configStore.result.state.suits"
|
:suits="configStore.result.state.suits"
|
||||||
:info="configStore.result.state.info"
|
:info="configStore.result.state.info"
|
||||||
:equs="configStore.config.equips"
|
:equs="configStore.config.equips"
|
||||||
:avatar="configStore.config.avatarLink"
|
:avatar="configStore.config.avatarLink"
|
||||||
|
:oaths="configStore.config.oaths"
|
||||||
|
:display="type"
|
||||||
></Info>
|
></Info>
|
||||||
</div>
|
</div>
|
||||||
<Skill
|
<Skill
|
||||||
@@ -31,10 +50,10 @@ import { useConfigStore, useInfoStore } from '@/stores'
|
|||||||
import Info from './components/Info.vue'
|
import Info from './components/Info.vue'
|
||||||
import Skill from './components/Skill.vue'
|
import Skill from './components/Skill.vue'
|
||||||
import BufferSkill from './components/BufferSkill.vue'
|
import BufferSkill from './components/BufferSkill.vue'
|
||||||
import type { IResultSkill } from '@/api/calc/type'
|
|
||||||
|
|
||||||
const configStore = useConfigStore()
|
const configStore = useConfigStore()
|
||||||
const infoStore = useInfoStore()
|
const infoStore = useInfoStore()
|
||||||
|
const type = ref<'equ' | 'oath'>('equ')
|
||||||
|
|
||||||
const setStandard = () => {
|
const setStandard = () => {
|
||||||
if (!configStore?.result?.state?.uuid) return
|
if (!configStore?.result?.state?.uuid) return
|
||||||
@@ -44,6 +63,45 @@ const setStandard = () => {
|
|||||||
const clearStandard = () => {
|
const clearStandard = () => {
|
||||||
infoStore.setStandard(undefined)
|
infoStore.setStandard(undefined)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const chooseCategory = (cat: 'equ' | 'oath') => {
|
||||||
|
type.value = cat
|
||||||
|
console.log(type.value)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss"></style>
|
<style lang="scss" scoped>
|
||||||
|
.active {
|
||||||
|
color: #ccc088;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
width: 60px;
|
||||||
|
height: 15px;
|
||||||
|
opacity: 0.35;
|
||||||
|
background: #bf8d20;
|
||||||
|
filter: blur(7px);
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
background: url('@/assets/img/active.png') no-repeat;
|
||||||
|
width: 148px;
|
||||||
|
height: 16px;
|
||||||
|
bottom: 2px;
|
||||||
|
transform: translate(0, 50%);
|
||||||
|
z-index: 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-head {
|
||||||
|
background: linear-gradient(#2b2817, #171407);
|
||||||
|
border-top: 1px solid #423d2c;
|
||||||
|
border-bottom: 1px solid #211d15;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -5,7 +5,9 @@
|
|||||||
:detail="props.equs"
|
:detail="props.equs"
|
||||||
:with-sub-weapon="(infoStore.infos?.subweapons?.length ?? 0) > 0"
|
:with-sub-weapon="(infoStore.infos?.subweapons?.length ?? 0) > 0"
|
||||||
:avatar="props.avatar"
|
:avatar="props.avatar"
|
||||||
|
v-show="display == 'equ'"
|
||||||
></EquList>
|
></EquList>
|
||||||
|
<Oath :detail="props.oaths" v-show="display == 'oath'"></Oath>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-wrap border-y-1px my-1px border-y-solid border-#FFFF/10 gap-1% px-1%">
|
<div class="flex flex-wrap border-y-1px my-1px border-y-solid border-#FFFF/10 gap-1% px-1%">
|
||||||
<template v-for="info in props.info" :key="info.id">
|
<template v-for="info in props.info" :key="info.id">
|
||||||
@@ -37,9 +39,10 @@
|
|||||||
<div class="border-y-1px border-y-solid my-1px border-#FFFF/10">
|
<div class="border-y-1px border-y-solid my-1px border-#FFFF/10">
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<div class="flex-1 flex items-center justify-center bg-#221A08 text-#9A7E4A">
|
<div class="flex-1 flex items-center justify-center bg-#221A08 text-#9A7E4A">
|
||||||
穿戴装备信息
|
穿戴{{ display == 'equ' ? '装备' : '誓约' }}信息
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<template v-if="display == 'equ'">
|
||||||
<template v-for="part in partOrder" :key="part">
|
<template v-for="part in partOrder" :key="part">
|
||||||
<div class="flex p-2px partItem gap-5px">
|
<div class="flex p-2px partItem gap-5px">
|
||||||
<img
|
<img
|
||||||
@@ -69,6 +72,39 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<template v-for="part in oathOrder" :key="part">
|
||||||
|
<div class="flex p-2px partItem gap-5px">
|
||||||
|
<img
|
||||||
|
:src="getImageURL(`/equipment/part/${part == '11' ? '誓约' : '星蕴石'}.png`)"
|
||||||
|
alt=""
|
||||||
|
class="w-20px h-20px object-contain"
|
||||||
|
/>
|
||||||
|
<div class="flex items-center justify-center" v-if="adaptation(part) > 0">
|
||||||
|
<img
|
||||||
|
:src="getImageURL(`/equipment/adaptation/${adaptation(part)}.png`)"
|
||||||
|
alt=""
|
||||||
|
class="w-11px h-10px object-contain"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<!-- <div
|
||||||
|
class="flex items-center"
|
||||||
|
v-if="props.equs[part]?.reinforce > 0"
|
||||||
|
:class="props.equs[part]?.reinforceType == 1 ? 'artifact' : 'advanced'"
|
||||||
|
>
|
||||||
|
+{{ props.equs[part]?.reinforce }}
|
||||||
|
</div> -->
|
||||||
|
<!-- <div class="rare" v-if="props.equs[part]?.refine > 0">
|
||||||
|
({{ props.equs[part]?.refine }})
|
||||||
|
</div> -->
|
||||||
|
{{ equ(props.equs?.[part]?.id) }}
|
||||||
|
<div :class="rarityClass(equ(props.oaths?.[part]?.id)?.rarity ?? '')">
|
||||||
|
{{ equ(props.oaths?.[part]?.id)?.name }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<div class="h-40px w-full"></div>
|
<div class="h-40px w-full"></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -79,14 +115,17 @@ import { getImageURL } from '@/utils/images'
|
|||||||
import { rarityClass } from '@/utils'
|
import { rarityClass } from '@/utils'
|
||||||
import type { IResultUserInfo, IResultSuit } from '@/api/calc/type'
|
import type { IResultUserInfo, IResultSuit } from '@/api/calc/type'
|
||||||
import EquList from '@/components/dnf/Equipment/List/index.vue'
|
import EquList from '@/components/dnf/Equipment/List/index.vue'
|
||||||
import type { IConfigEquip } from '@/stores/config'
|
import Oath from '@/components/dnf/Equipment/Oath/index.vue'
|
||||||
|
import type { IConfigEquip, IConfigOath } from '@/stores/config'
|
||||||
import { useInfoStore } from '@/stores'
|
import { useInfoStore } from '@/stores'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
info: IResultUserInfo[]
|
info: IResultUserInfo[]
|
||||||
suits: IResultSuit[]
|
suits: IResultSuit[]
|
||||||
equs: Record<string, IConfigEquip>
|
equs: Record<string, IConfigEquip>
|
||||||
|
oaths: Record<string, IConfigOath>
|
||||||
avatar: string
|
avatar: string
|
||||||
|
display: 'oath' | 'equ'
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const partOrder = [
|
const partOrder = [
|
||||||
@@ -103,9 +142,15 @@ const partOrder = [
|
|||||||
'魔法石',
|
'魔法石',
|
||||||
'耳环',
|
'耳环',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
const oathOrder = Array.from({ length: 12 }, (_, i) => (11 - i).toString())
|
||||||
const infoStore = useInfoStore()
|
const infoStore = useInfoStore()
|
||||||
|
|
||||||
const equ = (id: string) => {
|
const equ = (id: string) => {
|
||||||
|
if (props.display == 'oath') {
|
||||||
|
console.log(props.oaths, id)
|
||||||
|
return infoStore.oaths.find((e) => e.id == id)
|
||||||
|
}
|
||||||
return infoStore.equips.find((e) => e.id == id)
|
return infoStore.equips.find((e) => e.id == id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,24 @@
|
|||||||
|
|
||||||
<script lang="ts" name="index" setup>
|
<script lang="ts" name="index" setup>
|
||||||
const zoom = computed(() => {
|
const zoom = computed(() => {
|
||||||
const DPI = Math.max(0.85,Math.min(/macintosh|mac os x/i.test(navigator.userAgent.toLowerCase()) ? 1 : window.devicePixelRatio || 1,2)) * 0.95
|
const DPI =
|
||||||
return Math.max(1,/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent || navigator.vendor || (window as any).opera) ? 1 :(window.screen.width / 1800 / DPI))
|
Math.max(
|
||||||
|
0.85,
|
||||||
|
Math.min(
|
||||||
|
/macintosh|mac os x/i.test(navigator.userAgent.toLowerCase())
|
||||||
|
? 1
|
||||||
|
: window.devicePixelRatio || 1,
|
||||||
|
2,
|
||||||
|
),
|
||||||
|
) * 0.95
|
||||||
|
return Math.max(
|
||||||
|
1,
|
||||||
|
/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(
|
||||||
|
navigator.userAgent || navigator.vendor || (window as any).opera,
|
||||||
|
)
|
||||||
|
? 1
|
||||||
|
: window.screen.width / 1800 / DPI,
|
||||||
|
)
|
||||||
})
|
})
|
||||||
import { useDialog } from '@/components/hooks/dialog'
|
import { useDialog } from '@/components/hooks/dialog'
|
||||||
|
|
||||||
|
|||||||
@@ -31,9 +31,15 @@ export interface IConfigEquip {
|
|||||||
weaponFusion: number
|
weaponFusion: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IConfigOath {
|
||||||
|
id: string
|
||||||
|
adaptation: number
|
||||||
|
}
|
||||||
|
|
||||||
export interface IConfig {
|
export interface IConfig {
|
||||||
skills: Record<string, { lv: number ,vp:number, up: number}>
|
skills: Record<string, { lv: number; vp: number; up: number }>
|
||||||
equips: Record<string, IConfigEquip>
|
equips: Record<string, IConfigEquip>
|
||||||
|
oaths: Record<string, IConfigOath>
|
||||||
jades: Record<
|
jades: Record<
|
||||||
string,
|
string,
|
||||||
{
|
{
|
||||||
@@ -84,10 +90,16 @@ const defaultAvatarConfig = {
|
|||||||
option: '0',
|
option: '0',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const defaultOathConfig = {
|
||||||
|
id: '',
|
||||||
|
adaptation: 0,
|
||||||
|
}
|
||||||
|
|
||||||
export const useConfigStore = defineStore('configStore', () => {
|
export const useConfigStore = defineStore('configStore', () => {
|
||||||
const config = ref<IConfig>({
|
const config = ref<IConfig>({
|
||||||
skills: {},
|
skills: {},
|
||||||
equips: {},
|
equips: {},
|
||||||
|
oaths: {},
|
||||||
jades: {},
|
jades: {},
|
||||||
avatar: {},
|
avatar: {},
|
||||||
sundry: {},
|
sundry: {},
|
||||||
@@ -114,10 +126,11 @@ export const useConfigStore = defineStore('configStore', () => {
|
|||||||
skillCountConfig.value = JSON.parse(localSkillConfig)
|
skillCountConfig.value = JSON.parse(localSkillConfig)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!config.value)
|
if (!config.value) {
|
||||||
config.value = {
|
config.value = {
|
||||||
skills: {},
|
skills: {},
|
||||||
equips: {},
|
equips: {},
|
||||||
|
oaths: {},
|
||||||
jades: {},
|
jades: {},
|
||||||
avatar: {},
|
avatar: {},
|
||||||
sundry: {},
|
sundry: {},
|
||||||
@@ -127,6 +140,7 @@ export const useConfigStore = defineStore('configStore', () => {
|
|||||||
options: {},
|
options: {},
|
||||||
avatarLink: '',
|
avatarLink: '',
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (!config.value?.equips) config.value.equips = {}
|
if (!config.value?.equips) config.value.equips = {}
|
||||||
if (!config.value?.skills) config.value.skills = {}
|
if (!config.value?.skills) config.value.skills = {}
|
||||||
if (!config.value?.jades) config.value.jades = {}
|
if (!config.value?.jades) config.value.jades = {}
|
||||||
@@ -134,6 +148,8 @@ export const useConfigStore = defineStore('configStore', () => {
|
|||||||
if (!config.value?.sundry) config.value.sundry = {}
|
if (!config.value?.sundry) config.value.sundry = {}
|
||||||
if (!config.value?.bindAwake) config.value.bindAwake = 50
|
if (!config.value?.bindAwake) config.value.bindAwake = 50
|
||||||
if (!config.value?.options) config.value.options = {}
|
if (!config.value?.options) config.value.options = {}
|
||||||
|
if (!config.value?.oaths) config.value.oaths = {}
|
||||||
|
console.log(config.value.oaths)
|
||||||
|
|
||||||
const part = [...infoStore.parts, '宠物', '副武器'].filter(
|
const part = [...infoStore.parts, '宠物', '副武器'].filter(
|
||||||
(a) => !config.value?.equips.hasOwnProperty(a),
|
(a) => !config.value?.equips.hasOwnProperty(a),
|
||||||
@@ -156,6 +172,13 @@ export const useConfigStore = defineStore('configStore', () => {
|
|||||||
config.value && (config.value.avatar[p] = { ...defaultAvatarConfig })
|
config.value && (config.value.avatar[p] = { ...defaultAvatarConfig })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
infoStore.oathParts.forEach((p) => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
||||||
|
config.value &&
|
||||||
|
!config.value?.oaths.hasOwnProperty(p) &&
|
||||||
|
(config.value.oaths[p.toString()] = { ...defaultOathConfig })
|
||||||
|
})
|
||||||
|
|
||||||
infoStore.options.forEach((option) => {
|
infoStore.options.forEach((option) => {
|
||||||
if (Object.keys(config.value.options).includes(option.id.toString())) return
|
if (Object.keys(config.value.options).includes(option.id.toString())) return
|
||||||
config.value.options[option.id.toString()] = 0
|
config.value.options[option.id.toString()] = 0
|
||||||
@@ -238,5 +261,6 @@ export const useConfigStore = defineStore('configStore', () => {
|
|||||||
skillCountConfig,
|
skillCountConfig,
|
||||||
defaultEqusConfig,
|
defaultEqusConfig,
|
||||||
defaultAvatarConfig,
|
defaultAvatarConfig,
|
||||||
|
defaultOathConfig,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import api from '@/api'
|
import api from '@/api'
|
||||||
import type { ICharacterInfo } from '@/api/info/type'
|
import type { ICharacterInfo, IEquipment } from '@/api/info/type'
|
||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import { useConfigStore } from './config'
|
import { useConfigStore } from './config'
|
||||||
import type { IResult, IResultSkill, IResultSkillCount } from '@/api/calc/type'
|
import type { IResult, IResultSkill, IResultSkillCount } from '@/api/calc/type'
|
||||||
@@ -28,7 +28,22 @@ export const useInfoStore = defineStore('infoStore', () => {
|
|||||||
|
|
||||||
const options = computed(() => infos.value?.options ?? [])
|
const options = computed(() => infos.value?.options ?? [])
|
||||||
|
|
||||||
const oaths = computed(() => infos.value?.oaths ?? [])
|
const oaths = computed(() => {
|
||||||
|
const origin = infos.value?.oaths ?? []
|
||||||
|
const result: IEquipment[] = []
|
||||||
|
origin.forEach((o) => {
|
||||||
|
o.position.forEach((p, i) => {
|
||||||
|
result.push({
|
||||||
|
...o,
|
||||||
|
oathPos: p,
|
||||||
|
displayUrl: o.wearUrl?.[parseInt(p)]
|
||||||
|
? `/equipment/icon/oathprimer/primer_equip/${o.wearUrl?.[parseInt(p)]}`
|
||||||
|
: o.imageUrl,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return result
|
||||||
|
})
|
||||||
|
|
||||||
const standardUUID = ref<string>()
|
const standardUUID = ref<string>()
|
||||||
|
|
||||||
@@ -93,6 +108,10 @@ export const useInfoStore = defineStore('infoStore', () => {
|
|||||||
'宠物装备-蓝',
|
'宠物装备-蓝',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
const oathParts = Array.from({ length: 12 }, (_, i) => i.toString())
|
||||||
|
|
||||||
|
const emblemParts = ['彩色', '红色', '蓝色', '绿色', '黄色']
|
||||||
|
|
||||||
const createCharacter = async (alter: string, equVersion?: string) => {
|
const createCharacter = async (alter: string, equVersion?: string) => {
|
||||||
const time = new Date().getTime()
|
const time = new Date().getTime()
|
||||||
alter_token.value = btoa(JSON.stringify({ alter, equVersion, time }))
|
alter_token.value = btoa(JSON.stringify({ alter, equVersion, time }))
|
||||||
@@ -112,6 +131,8 @@ export const useInfoStore = defineStore('infoStore', () => {
|
|||||||
parts,
|
parts,
|
||||||
oaths,
|
oaths,
|
||||||
avatarParts,
|
avatarParts,
|
||||||
|
oathParts,
|
||||||
|
emblemParts,
|
||||||
avatars,
|
avatars,
|
||||||
jades,
|
jades,
|
||||||
setStandard,
|
setStandard,
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
export function resolveTeleportTarget(target?: string | Element | null) {
|
||||||
|
if (typeof window === 'undefined') {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof target === 'string') {
|
||||||
|
return document.querySelector(target)
|
||||||
|
}
|
||||||
|
|
||||||
|
return target ?? document.body
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getElementZoom(target?: string | Element | null) {
|
||||||
|
if (typeof window === 'undefined') {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
let zoom = 1
|
||||||
|
let current = resolveTeleportTarget(target) as HTMLElement | null
|
||||||
|
|
||||||
|
while (current) {
|
||||||
|
const currentZoom = Number.parseFloat(window.getComputedStyle(current).zoom)
|
||||||
|
|
||||||
|
if (Number.isFinite(currentZoom) && currentZoom > 0) {
|
||||||
|
zoom *= currentZoom
|
||||||
|
}
|
||||||
|
|
||||||
|
current = current.parentElement
|
||||||
|
}
|
||||||
|
|
||||||
|
return zoom || 1
|
||||||
|
}
|
||||||
+1
-1
Submodule images updated: 2dc49b5e8f...965adcfe7e
Reference in New Issue
Block a user