Files
dcalc/frontendNew/src/components/dnf/Equipment/List/index.vue
T
2026-07-11 11:14:12 +08:00

186 lines
4.5 KiB
Vue

<script setup lang="ts" name="EquList">
import { computed } from "vue";
import { useInfoStore, type IConfigEquip } from "@/stores";
import { getImageURL } from "@/utils";
import LegacyEquipmentIcon from "@/components/dnf/Equipment/Icon/index.vue";
const baseWidth = 264;
const baseHeight = 172;
const props = withDefaults(
defineProps<{
withBg?: boolean;
withPet?: boolean;
detail?: Record<string, IConfigEquip>;
withSubWeapon?: boolean;
avatar?: string;
}>(),
{
withBg: true,
withPet: true,
withSubWeapon: false,
avatar: "",
},
);
const partModelValue = defineModel<string>("part", { default: "" });
const infoStore = useInfoStore();
const parts = computed(() => {
return infoStore.parts.filter((part) => {
if (part === "宠物" && !props.withPet) return false;
return !!props.detail?.[part];
});
});
const equ = (id: string) => infoStore.equips.find((item) => item.id === id);
const infoStyle = (part: string) => {
let x = 10;
let y = 10;
let index = infoStore.parts.findIndex((current) => current === part);
if (index === 13) {
index -= 7;
} else if (index >= 5 && index <= 12) {
x += 179;
index -= 5;
}
x += (index % 2) * 39;
y += Math.floor(index / 2) * 34;
return {
left: `${(x / baseWidth) * 100}%`,
top: `${(y / baseHeight) * 100}%`,
zIndex: 6,
};
};
const choosePart = (part: string) => {
partModelValue.value = part;
};
const partName = (part: string) => {
if (part === "辅助装备") return "左槽";
if (part === "魔法石") return "右槽";
return part;
};
</script>
<template>
<div
class="equ-list"
:class="{ 'equ-list--plain': !withBg }"
:style="withBg ? { backgroundImage: `url(${getImageURL('/common/head.png')})` } : undefined"
>
<template v-for="part in parts" :key="part">
<button class="equ-slot" :style="infoStyle(part)" type="button" @click="choosePart(part)">
<template v-if="detail?.[part]?.id">
<LegacyEquipmentIcon :equipment="equ(detail[part].id)" />
</template>
<template v-else>
<span class="equ-slot-text">{{ partName(part) }}</span>
</template>
</button>
</template>
<button
v-if="withSubWeapon"
class="equ-slot"
:style="{ left: `${(150 / baseWidth) * 100}%`, top: `${(5 / baseHeight) * 100}%`, zIndex: 8 }"
type="button"
@click="choosePart('副武器')"
>
<template v-if="detail?.['副武器']?.id">
<LegacyEquipmentIcon :equipment="equ(detail['副武器'].id)" />
</template>
<template v-else>
<span class="equ-slot-text">副武</span>
</template>
</button>
<img v-if="avatar" :src="avatar" alt="Avatar" class="equ-avatar" />
</div>
</template>
<style scoped>
.equ-list {
position: relative;
width: min(100%, 264px);
aspect-ratio: 264 / 172;
flex: 0 0 auto;
border: 1px solid rgba(85, 72, 46, 0.55);
box-shadow:
inset 0 0 0 1px rgba(24, 20, 14, 0.8),
0 8px 20px rgba(0, 0, 0, 0.32);
background-position: center;
background-repeat: no-repeat;
background-size: 100% 100%;
overflow: hidden;
}
.equ-list::before {
content: "";
position: absolute;
inset: 0;
pointer-events: none;
background:
radial-gradient(circle at 50% 8%, rgba(88, 161, 255, 0.24), transparent 35%),
linear-gradient(180deg, rgba(0, 0, 0, 0.12), rgba(0, 0, 0, 0.28));
}
.equ-list--plain {
background:
linear-gradient(180deg, rgba(19, 21, 24, 0.96), rgba(10, 10, 12, 0.98)),
radial-gradient(circle at 50% 0, rgba(55, 95, 138, 0.24), transparent 45%);
}
.equ-slot {
position: absolute;
box-sizing: border-box;
width: 9.848%;
height: 15.116%;
border: 1px solid rgba(122, 122, 122, 0.5);
display: flex;
align-items: center;
justify-content: center;
color: rgb(255 255 255 / 0.5);
background: rgba(0, 0, 0, 0.16);
padding: 0;
transition:
border-color 0.18s ease,
box-shadow 0.18s ease,
background-color 0.18s ease;
}
.equ-slot:hover {
border-color: rgba(229, 196, 113, 0.72);
box-shadow:
0 0 0 1px rgba(229, 196, 113, 0.38),
inset 0 0 8px rgba(255, 210, 122, 0.22);
background: rgba(47, 35, 14, 0.28);
}
.equ-slot:focus-visible {
outline: none;
border-color: rgba(235, 211, 141, 0.88);
box-shadow:
0 0 0 2px rgba(235, 211, 141, 0.35),
inset 0 0 8px rgba(255, 210, 122, 0.25);
}
.equ-slot-text {
font-size: 0.6rem;
line-height: 1;
}
.equ-avatar {
position: absolute;
width: 70%;
left: 50%;
bottom: -5.814%;
transform: translateX(-50%);
}
</style>