This commit is contained in:
2025-04-03 17:57:45 +08:00
parent d56afd0695
commit e2099aa047
15 changed files with 744 additions and 42 deletions
+13 -4
View File
@@ -21,7 +21,7 @@ export interface IAlterInfo {
}
export interface ICharacterInfo {
role:string
role: string
alter: string
name: string
equVersion: string
@@ -32,6 +32,7 @@ export interface ICharacterInfo {
weapons: string[]
skills: ISkill[]
suits: ISuit[]
avatar: Record<string, IAvatarInfo[]>
}
export interface IEquipment {
@@ -40,9 +41,9 @@ export interface IEquipment {
itemType: string
itemDetailType: string
name: string
categorize:string
categorize: string
suit: string[]
rarity:string
rarity: string
}
export interface ISkill {
@@ -63,7 +64,6 @@ export interface ISuit {
suitId: number
}
export interface IEnchantingInfo {
id: string | number
fame: number | undefined
@@ -73,3 +73,12 @@ export interface IEnchantingInfo {
rarity?: string
type?: string
}
export interface IAvatarInfo {
id: number
options: string[]
part: string
rarity: string
suit?: string
name: string
}
@@ -0,0 +1,73 @@
<template>
<div class="pos-relative w-300px h-full">
<template v-for="part in infoStore.avatarParts" :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)"
>
{{ partName(part) }}
</div>
</template>
</div>
</template>
<script lang="ts" setup name="EquList">
import { getImageURL } from '@/utils/images'
import { useVModel } from '@vueuse/core'
import { useInfoStore, useConfigStore } from '@/stores'
const props = defineProps({
part: {
type: String,
default: '',
},
})
const partModelValue = useVModel(props, 'part')
const infoStore = useInfoStore()
const infoStyle = (part: string) => {
let x = 15
let y = 5
let index = infoStore.avatarParts.findIndex((p) => p == part)
if (index > 7) {
index += 1
}
// if (index == 13) {
// index -= 7
// } else if (index >= 5 && index <= 12) {
// x += 179
// index -= 5
// }
if(part == '宠物'){
x+= 5*39
y+= 1*40
}
else if (part.includes('宠物装备')) {
x += 6 * 39
y += (index - infoStore.avatarParts.findIndex((p) => p == '宠物装备-红') - 1) * 40
} else {
x += (index % 4) * 39
y += Math.floor(index / 4) * 40
}
const style = {
left: `${x}px`,
top: `${y}px`,
zIndex: 6,
// fontWeight: 900,
}
return style
}
const choosePart = (part: string) => {
partModelValue.value = part
}
const partName = (part: string) => {
if (part == '武器装扮') return '武器'
return part.replace('宠物装备-', '')
}
</script>
<style lang="scss" scoped></style>
@@ -0,0 +1,159 @@
<script lang="tsx">
import { computed, defineComponent, ref, renderList } from 'vue'
import type { IEnchantingInfo } from '@/api/info/type'
import { useInfoStore, useConfigStore } from '@/stores'
import ClothList from '@/components/dnf/Avatar/List/index.vue'
export default defineComponent({
name: 'Clothes',
setup(props) {
const configStore = useConfigStore()
const part = ref('武器装扮')
// const globalStore = useGlobalStore()
/** 是否有徽章 */
const has_socket = computed(() => ['武器装扮', '光环', '皮肤'].includes(part.value as string))
const basicInfoStore = useInfoStore()
const has_enchant = computed(() => {
return !['头发', '帽子', '脸部', '胸部', '上衣', '腰带', '下装', '鞋'].includes(
part.value as string,
)
})
const enchanting_list = computed<IEnchantingInfo[] | undefined>(() => {
return basicInfoStore.enchants
?.filter((item) => item.position.includes(part.value))
.sort((a, b) => (b.fame ?? 0) - (a.fame ?? 0))
})
const emblem_list = computed<IEnchantingInfo[] | undefined>(() => {
return basicInfoStore.emblems.filter((item) => item.position.includes(part.value))
})
const currentInfo = function <T>(name: string, defaultValue?: T) {
return computed<string | number>({
get() {
let key: 'avatar' | 'equips' = 'avatar'
if (part.value == '宠物') key = 'equips'
return (
(configStore.config[key]?.[part.value] as Record<string, any>)?.[name] ??
defaultValue ??
0
)
},
set(val) {
if (val == undefined) {
return
}
let key: 'avatar' | 'equips' = 'avatar'
if (part.value == '宠物') key = 'equips'
if (configStore.config[key][part.value]) {
;(configStore.config[key][part.value] as Record<string, any>)[name] = val
}
},
})
}
// 附魔
const enchanting = currentInfo<string | number>('enchanting')
// 镶嵌栏1
const emblem_0 = currentInfo<string | number>('emblem_0', 0)
// 镶嵌栏2
const emblem_1 = currentInfo<string | number>('emblem_1')
// 品级
const id = currentInfo<string | number>('id')
// 属性
const option = currentInfo<string | number>('option')
/**
* 同步徽章1到徽章2
* @param val
*/
function changeSocket(val: number) {
emblem_1.value = val
}
return () => {
return (
<>
<div class="h-120px flex justify-center items-center">
<ClothList v-model:part={part.value} />
</div>
<div class="flex flex-wrap equ-profile">
<div class="equ-profile-item">
<div class="mr-10px row-name">当前部位</div>
<span> {part.value}</span>
</div>
{has_enchant.value ? (
<div class="equ-profile-item">
<div class="row-name">{part.value == '宠物' ? '附魔' : '属性'}</div>
<calc-select v-model={enchanting.value} class="flex-1 !h-20px">
<calc-option value={0}>无</calc-option>
{renderList(enchanting_list.value ?? [], (item) => (
<calc-option value={item.id}>{item.detail}</calc-option>
))}
</calc-select>
</div>
) : (
<>
<div class="equ-profile-item">
<div class="row-name">品级</div>
<calc-select v-model={id.value} class="flex-1 !h-20px">
{renderList(basicInfoStore.avatars[part.value] ?? [], (item) => (
<calc-option value={item.id}>{item.suit}</calc-option>
))}
</calc-select>
</div>
<div class="equ-profile-item">
<div class="row-name">属性</div>
<calc-select v-model={option.value} class="flex-1 !h-20px">
<calc-option value={0}>无</calc-option>
{renderList(basicInfoStore.avatars[part.value].find(a=>a.id == id.value)?.options ?? [], (item) => (
<calc-option value={item}>{item}</calc-option>
))}
</calc-select>
</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>
</>
)
}
},
})
</script>
<style lang="scss"></style>
@@ -129,7 +129,7 @@ export default defineComponent({
return () => {
return (
<>
<div class="h-180px flex justify-center items-center">
<div class="h-150px flex justify-center items-center">
<EquList v-model:part={part.value}/></div>
<div class="flex flex-wrap equ-profile">
@@ -172,7 +172,7 @@ export default defineComponent({
<div class="equ-profile-item">
<div class="row-name">附魔</div>
<calc-select v-model={enchanting.value} class="flex-1 !h-20px">
<calc-option value={0}>无</calc-option>
<calc-option value={""}>无</calc-option>
{renderList(enchanting_list.value ?? [], (item) => (
<calc-option value={item.id}>{item.detail}</calc-option>
))}
@@ -186,20 +186,20 @@ export default defineComponent({
v-model={emblem_0.value}
class="flex-1 !h-20px"
>
<calc-option value={0}>无</calc-option>
<calc-option value={""}>无</calc-option>
{renderList(emblem_list.value ?? [], (item) => (
<calc-option
value={item.id}
>{`${item.rarity}${item.type}徽章[${item.detail}]`}</calc-option>
>{`${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={0}>无</calc-option>
<calc-option value={""}>无</calc-option>
{renderList(emblem_list.value ?? [], (item) => (
<calc-option
value={item.id}
>{`${item.rarity}${item.type}徽章[${item.detail}]`}</calc-option>
>{`${item.rarity}${item.categorize}徽章[${item.detail}]`}</calc-option>
))}
</calc-select>
)}
+9 -2
View File
@@ -1,12 +1,19 @@
<template>
<div class="w-400px">
<calc-collapse class="w-100%" title="装备打造(点击人物部位切换)">
<equipment />
<calc-collapse class="w-100%" title="装备/时装打造(点击部位切换)">
<calc-tabs v-model="partTab" class="!mb-2">
<calc-tab :value="0">装备栏</calc-tab>
<calc-tab :value="1">时装栏</calc-tab>
</calc-tabs>
<equipment v-if="partTab === 0"></equipment>
<clothes v-if="partTab === 1"></clothes>
</calc-collapse>
</div>
</template>
<script setup lang="ts">
import equipment from './components/equipment.vue'
import clothes from './components/avatar.vue';
const partTab = ref(0)
</script>
<style lang="scss">
+43 -15
View File
@@ -22,7 +22,7 @@ export interface IConfig {
id: string
reinforce: number
reinforceType: number
enchant: number
enchant: string
emblem_0: string
emblem_1: string
upgrade: number
@@ -32,26 +32,45 @@ export interface IConfig {
}
>
jades: Record<string, number>
avatar: Record<
string,
{
id: string
enchant: string
emblem_0: string
emblem_1: string
option: string
}
>
}
const defaultEqusConfig = {
id: '',
reinforce: 0,
reinforceType: 0,
enchant: 0,
emblem_0: "0",
emblem_1: "0",
enchant: '',
emblem_0: '',
emblem_1: '',
upgrade: 0,
refine: 0,
adaptation: 0,
fusion: '',
}
const defaultAvatarConfig = {
id: '',
enchant: '',
emblem_0: '',
emblem_1: '',
option: '0',
}
export const useConfigStore = defineStore('configStore', () => {
const config = ref<IConfig>({
skills: {},
equips: {},
jades: {},
avatar: {},
})
const loadConfig = () => {
@@ -69,12 +88,17 @@ export const useConfigStore = defineStore('configStore', () => {
skills: {},
equips: {},
jades: {},
avatar: {},
}
if (!config.value?.equips) config.value.equips = {}
if (!config.value?.skills) config.value.skills = {}
if (!config.value?.jades) config.value.jades = {}
if (!config.value?.avatar) config.value.avatar = {}
const part = infoStore.parts.filter((a) => !config.value?.equips.hasOwnProperty(a))
const part = [...infoStore.parts, '宠物'].filter((a) => !config.value?.equips.hasOwnProperty(a))
const avatarPart = infoStore.avatarParts
.filter((a) => a != '宠物')
.filter((a) => !config.value?.avatar.hasOwnProperty(a))
const skillIDs = infoStore.skills
.map((skill) => skill.id.toString())
@@ -84,6 +108,10 @@ export const useConfigStore = defineStore('configStore', () => {
config.value && (config.value.equips[p] = { ...defaultEqusConfig })
})
avatarPart.forEach((p) => {
config.value && (config.value.avatar[p] = { ...defaultAvatarConfig })
})
skillIDs.forEach((id) => {
config.value &&
(config.value.skills[id] = {
@@ -101,39 +129,39 @@ export const useConfigStore = defineStore('configStore', () => {
}
const calc = async () => {
if(!useInfoStore().infos?.alter) return undefined
if (!useInfoStore().infos?.alter) return undefined
return await api.calc(config.value)
}
const chooseEqu = async(equip: IEquipment | undefined,isFusion:boolean = false) => {
if (equip && config.value.equips[equip.itemDetailType]) {
const chooseEqu = async (equip: IEquipment | undefined, isFusion: boolean = false) => {
if (!equip) return
const part = equip?.itemType == '武器' ? '武器' : equip?.itemDetailType
if (equip && config.value.equips[part]) {
const key = isFusion ? 'fusion' : 'id'
if (config.value.equips[equip.itemDetailType][key] == equip.id) {
config.value.equips[equip.itemDetailType][key] = ""
if (config.value.equips[part][key] == equip.id) {
config.value.equips[part][key] = ''
} else {
config.value.equips[equip.itemDetailType][key] = equip.id
config.value.equips[part][key] = equip.id
}
}
}
const result = useAsyncState(
() => {
return calc()
},
{
skills:[]
skills: [],
},
{ resetOnExecute: false },
)
return {
config,
loadConfig,
saveConfig,
calc,
result,
chooseEqu
chooseEqu,
}
})
+23 -2
View File
@@ -18,6 +18,8 @@ export const useInfoStore = defineStore('infoStore', () => {
const stones = computed(() => infos.value?.stones ?? [])
const avatars = computed(() => infos.value?.avatar ?? {})
const parts = [
'头肩',
'上衣',
@@ -31,8 +33,25 @@ export const useInfoStore = defineStore('infoStore', () => {
'辅助装备',
'戒指',
'耳环',
'魔法石',
'魔法石'
]
const avatarParts = [
'武器装扮',
'头发',
'帽子',
'脸部',
'光环',
'胸部',
'上衣',
'皮肤',
'腰带',
'下装',
'鞋',
'宠物',
'宠物装备-红',
'宠物装备-绿',
'宠物装备-蓝'
]
const createCharacter = async (alter: string, equVersion?: string) => {
@@ -51,6 +70,8 @@ export const useInfoStore = defineStore('infoStore', () => {
enchants,
emblems,
parts,
stones
stones,
avatarParts,
avatars,
}
})