|
|
|
@@ -1,14 +1,172 @@
|
|
|
|
|
<template>
|
|
|
|
|
<div class="grid">
|
|
|
|
|
<div v-for="[generalID, general] of list" :key="generalID" class="row">
|
|
|
|
|
{{ general }}
|
|
|
|
|
<div class="g-thead-tr bg1">
|
|
|
|
|
<div class="row g-tr mx-0 gx-1">
|
|
|
|
|
<template v-for="itemKey of displayColumns.values()" :key="itemKey">
|
|
|
|
|
<template v-for="(itemInfo, _dummyIdx) in [headerMap[itemKey]]" :key="_dummyIdx">
|
|
|
|
|
<div v-if="itemInfo.subType" class="col d-flex flex-column justify-content-center center">
|
|
|
|
|
<div
|
|
|
|
|
v-for="[subItemKey, subItemInfo] of Object.entries(itemInfo.subType)"
|
|
|
|
|
:key="subItemKey"
|
|
|
|
|
:style="subItemInfo.style ?? itemInfo.style"
|
|
|
|
|
>
|
|
|
|
|
<template v-if="subItemInfo.subType">Error: nestedType {{ subItemKey }}</template>
|
|
|
|
|
<template v-else>{{ subItemInfo.title }}</template>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div v-else class="col align-self-center center" :style="itemInfo.style">{{ itemInfo.title }}</div>
|
|
|
|
|
</template>
|
|
|
|
|
</template>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div style="position: relative">
|
|
|
|
|
<div v-for="[generalID, general] of list" :key="generalID" class="row g-tbody-tr g-tr mx-0 gx-1">
|
|
|
|
|
<template v-for="itemKey of displayColumns.values()" :key="itemKey">
|
|
|
|
|
<template v-for="(itemInfo, _dummyIdx) in [headerMap[itemKey]]" :key="_dummyIdx">
|
|
|
|
|
<div v-if="itemInfo.subType" class="col d-flex flex-column justify-content-center center">
|
|
|
|
|
<template v-for="[subItemKey, subItemInfo] of Object.entries(itemInfo.subType)" :key="subItemKey">
|
|
|
|
|
<div v-if="subItemInfo.subType">Error: nestedType {{ subItemKey }}</div>
|
|
|
|
|
<template v-else-if="subItemInfo.converter">
|
|
|
|
|
<!-- eslint-disable-next-line vue/no-v-html -->
|
|
|
|
|
<div :style="subItemInfo.style ?? itemInfo.style" v-html="subItemInfo.converter(general)" />
|
|
|
|
|
</template>
|
|
|
|
|
<div v-else :style="subItemInfo.style ?? itemInfo.style">
|
|
|
|
|
{{general[subItemKey as keyof GeneralListItem]}}
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
</div>
|
|
|
|
|
<template v-else-if="itemInfo.converter">
|
|
|
|
|
<!-- eslint-disable-next-line vue/no-v-html -->
|
|
|
|
|
<div :style="itemInfo.style" class="col align-self-center center" v-html="itemInfo.converter(general)" />
|
|
|
|
|
</template>
|
|
|
|
|
<div v-else class="col align-self-center center" :style="itemInfo.style">
|
|
|
|
|
{{general[itemKey as keyof GeneralListItem]}}
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
</template>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script lang="ts" setup>
|
|
|
|
|
import type { GeneralListItem } from "@/defs/API/Nation";
|
|
|
|
|
import type { PropType } from "vue";
|
|
|
|
|
import type { GeneralListItem, GeneralListItemP2 } from "@/defs/API/Nation";
|
|
|
|
|
import { getIconPath } from "@/util/getIconPath";
|
|
|
|
|
import { ref, type PropType, type StyleValue } from "vue";
|
|
|
|
|
|
|
|
|
|
type headerInfo = {
|
|
|
|
|
title: string;
|
|
|
|
|
info?: string;
|
|
|
|
|
isEnum?: boolean; //default: false
|
|
|
|
|
sortable?: "asc" | "desc" | false | undefined | null; //default: false
|
|
|
|
|
searchable?: boolean; //default: false
|
|
|
|
|
type?: "both" | "display" | "filter" | "custom"; //default: both
|
|
|
|
|
converter?: (a: GeneralListItem) => string;
|
|
|
|
|
subType?: Partial<Record<headerType, headerInfo>>; //n행 표기 시
|
|
|
|
|
style?: StyleValue;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
type headerType =
|
|
|
|
|
| keyof Omit<GeneralListItemP2, "no" | "imgsvr" | "picture" | "lbonus" | "officerLevelText">
|
|
|
|
|
| "stat"
|
|
|
|
|
| "imagePath"
|
|
|
|
|
| "goldRice"
|
|
|
|
|
| "expDedLv"
|
|
|
|
|
| "specials"
|
|
|
|
|
| "killturnAndConnect";
|
|
|
|
|
|
|
|
|
|
const headerMap: Record<headerType, headerInfo> = {
|
|
|
|
|
imagePath: {
|
|
|
|
|
title: "아이콘",
|
|
|
|
|
type: "display",
|
|
|
|
|
style: {
|
|
|
|
|
maxWidth: "64px",
|
|
|
|
|
},
|
|
|
|
|
converter: (gen) => {
|
|
|
|
|
return `<img src="${getIconPath(gen.imgsvr, gen.picture)}" width="64">`;
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
name: { title: "장수명", searchable: true },
|
|
|
|
|
nation: { title: "국가명", isEnum: true },
|
|
|
|
|
npc: { title: "NPC", isEnum: true, type: "filter" },
|
|
|
|
|
injury: { title: "부상", sortable: "asc" },
|
|
|
|
|
leadership: { title: "통솔" },
|
|
|
|
|
strength: { title: "무력" },
|
|
|
|
|
intel: { title: "지력" },
|
|
|
|
|
stat: {
|
|
|
|
|
title: "통/무/지",
|
|
|
|
|
type: "custom",
|
|
|
|
|
subType: {
|
|
|
|
|
leadership: { title: "통" },
|
|
|
|
|
strength: { title: "무" },
|
|
|
|
|
intel: { title: "지" },
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
explevel: { title: "명성Lv" },
|
|
|
|
|
dedlevel: { title: "계급Lv" },
|
|
|
|
|
expDedLv: {
|
|
|
|
|
title: "명성/계급Lv",
|
|
|
|
|
subType: {
|
|
|
|
|
explevel: { title: "명성Lv" },
|
|
|
|
|
dedlevel: { title: "계급Lv" },
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
gold: { title: "금", sortable: "desc" },
|
|
|
|
|
rice: { title: "쌀", sortable: "desc" },
|
|
|
|
|
goldRice: {
|
|
|
|
|
title: "금/쌀",
|
|
|
|
|
type: "custom",
|
|
|
|
|
subType: {
|
|
|
|
|
gold: { title: "금", sortable: "desc" },
|
|
|
|
|
rice: { title: "쌀", sortable: "desc" },
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
age: { title: "연령" },
|
|
|
|
|
specialDomestic: { title: "내특" },
|
|
|
|
|
specialWar: { title: "전특" },
|
|
|
|
|
specials: {
|
|
|
|
|
title: "성격/내특/전특",
|
|
|
|
|
subType: {
|
|
|
|
|
personal: { title: "성격", converter: (g) => g.personal.split("_").pop() as string },
|
|
|
|
|
specialDomestic: { title: "내특", converter: (g) => g.specialDomestic.split("_").pop() as string },
|
|
|
|
|
specialWar: { title: "전특", converter: (g) => g.specialWar.split("_").pop() as string },
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
personal: { title: "성격" },
|
|
|
|
|
belong: { title: "임관" },
|
|
|
|
|
|
|
|
|
|
killturnAndConnect: {
|
|
|
|
|
title: "삭턴/벌점",
|
|
|
|
|
subType: {
|
|
|
|
|
killturn: { title: "삭턴" },
|
|
|
|
|
connect: { title: "벌점" },
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
killturn: { title: "삭턴" },
|
|
|
|
|
connect: { title: "벌점" },
|
|
|
|
|
|
|
|
|
|
officerLevel: { title: "관직" }, //권한에따라 태수,군사,시종 노출 여부가 다름
|
|
|
|
|
ownerName: { title: "소유주" }, //NPC 출력용에 따라 결과가 다름
|
|
|
|
|
honorText: { title: "명성" },
|
|
|
|
|
|
|
|
|
|
city: { title: "도시" },
|
|
|
|
|
experience: { title: "명성" },
|
|
|
|
|
dedication: { title: "계급" },
|
|
|
|
|
|
|
|
|
|
officer_level: { title: "관직" },
|
|
|
|
|
officer_city: { title: "부임지" },
|
|
|
|
|
} as const;
|
|
|
|
|
|
|
|
|
|
const defaultColumns: headerType[] = [
|
|
|
|
|
"imagePath",
|
|
|
|
|
"name",
|
|
|
|
|
"age",
|
|
|
|
|
"stat",
|
|
|
|
|
"goldRice",
|
|
|
|
|
"expDedLv",
|
|
|
|
|
"specials",
|
|
|
|
|
"killturnAndConnect",
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const displayColumns = ref(new Set<headerType>(defaultColumns));
|
|
|
|
|
|
|
|
|
|
defineProps({
|
|
|
|
|
list: {
|
|
|
|
@@ -17,3 +175,15 @@ defineProps({
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
|
|
.g-tr {
|
|
|
|
|
border-bottom: solid gray 1px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.g-thead-tr {
|
|
|
|
|
position: sticky;
|
|
|
|
|
top: 0px;
|
|
|
|
|
z-index: 5;
|
|
|
|
|
}
|
|
|
|
|
</style>
|
|
|
|
|