feat: 메인 도시 정보를 Ref와 일치
도시 소유 국가색과 태수·군사·종사를 general.me에 추가한다. 주민 영역, 반응형 grid와 국가색 대비를 Ref 카드와 같은 geometry로 맞추고 API 및 production Chromium 회귀 검증을 추가한다.
This commit is contained in:
@@ -3,6 +3,14 @@ import { computed } from 'vue';
|
||||
import SkeletonLines from '../ui/SkeletonLines.vue';
|
||||
import LegacyProgressBar from '../ui/LegacyProgressBar.vue';
|
||||
import { ratioPercent } from '../../utils/legacyProgress';
|
||||
import { legacyLuminanceTextColor } from '../../utils/legacyNationColor';
|
||||
import { getNpcColor } from '../../utils/npcColor';
|
||||
|
||||
interface CityOfficer {
|
||||
id: number;
|
||||
name: string;
|
||||
npcState: number;
|
||||
}
|
||||
|
||||
interface CityInfo {
|
||||
id: number;
|
||||
@@ -12,6 +20,7 @@ interface CityInfo {
|
||||
regionName: string;
|
||||
nationId: number;
|
||||
nationName: string;
|
||||
nationColor: string;
|
||||
population: number;
|
||||
populationMax: number;
|
||||
agriculture: number;
|
||||
@@ -28,6 +37,7 @@ interface CityInfo {
|
||||
wallMax: number;
|
||||
supplyState: number;
|
||||
frontState: number;
|
||||
officers?: Partial<Record<2 | 3 | 4, CityOfficer | null>>;
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
@@ -59,97 +69,170 @@ const metrics = computed(() => {
|
||||
{ label: '시세', percent: city.trade ? ratioPercent(city.trade - 95, 10) : 0, text: tradeText },
|
||||
];
|
||||
});
|
||||
|
||||
const officerRows = computed(() => {
|
||||
const city = props.city;
|
||||
if (!city) return [];
|
||||
return [
|
||||
{ level: 4 as const, label: '태수', officer: city.officers?.[4] },
|
||||
{ level: 3 as const, label: '군사', officer: city.officers?.[3] },
|
||||
{ level: 2 as const, label: '종사', officer: city.officers?.[2] },
|
||||
];
|
||||
});
|
||||
|
||||
const nationStyle = computed(() => {
|
||||
const backgroundColor = props.city?.nationColor ?? '#000000';
|
||||
return {
|
||||
backgroundColor,
|
||||
color: legacyLuminanceTextColor(backgroundColor),
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="city-card">
|
||||
<div class="city-card" data-city-basic-card>
|
||||
<div v-if="props.loading">
|
||||
<SkeletonLines :lines="4" />
|
||||
</div>
|
||||
<div v-else-if="!props.city" class="empty">도시 정보를 불러오지 못했습니다.</div>
|
||||
<div v-else class="city-body">
|
||||
<div class="title">
|
||||
【{{ props.city.regionName }} | {{ props.city.levelName }}】 {{ props.city.name }} ·
|
||||
<div v-else class="city-grid">
|
||||
<div class="city-title" :style="nationStyle">
|
||||
【{{ props.city.regionName }} | {{ props.city.levelName }}】 {{ props.city.name }}
|
||||
</div>
|
||||
<div class="city-nation" :style="nationStyle">
|
||||
{{ props.city.nationId > 0 ? `지배 국가 【 ${props.city.nationName} 】` : '공 백 지' }}
|
||||
</div>
|
||||
<div class="progress-grid">
|
||||
<div
|
||||
v-for="metric of metrics"
|
||||
:key="metric.label"
|
||||
class="city-progress"
|
||||
:data-city-progress="metric.label"
|
||||
>
|
||||
<span class="city-progress__label">{{ metric.label }}</span>
|
||||
<div class="city-progress__body">
|
||||
<LegacyProgressBar
|
||||
:height="7"
|
||||
:percent="metric.percent"
|
||||
:label="`${metric.label} ${metric.text}`"
|
||||
/>
|
||||
<span class="city-progress__text">{{ metric.text }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-for="metric of metrics"
|
||||
:key="metric.label"
|
||||
class="city-panel city-progress"
|
||||
:class="{ 'city-panel--population': metric.label === '주민' }"
|
||||
:data-city-progress="metric.label"
|
||||
>
|
||||
<span class="city-panel__head city-progress__label">{{ metric.label }}</span>
|
||||
<div class="city-panel__body city-progress__body">
|
||||
<LegacyProgressBar
|
||||
:height="7"
|
||||
:percent="metric.percent"
|
||||
:label="`${metric.label} ${metric.text}`"
|
||||
/>
|
||||
<span class="city-progress__text">{{ metric.text }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-for="row of officerRows"
|
||||
:key="row.level"
|
||||
class="city-panel city-officer"
|
||||
:class="`city-panel--officer-${row.level}`"
|
||||
:data-city-officer="row.level"
|
||||
>
|
||||
<span class="city-panel__head">{{ row.label }}</span>
|
||||
<span
|
||||
class="city-panel__body city-officer__name"
|
||||
:style="{ color: getNpcColor(row.officer?.npcState ?? 0) }"
|
||||
>
|
||||
{{ row.officer?.name ?? '-' }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.title {
|
||||
.city-card,
|
||||
.city-grid {
|
||||
box-sizing: border-box;
|
||||
min-height: 20px;
|
||||
padding: 1px 6px;
|
||||
border-bottom: 1px solid #666;
|
||||
background: #173d27;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.progress-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.city-progress {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 2fr;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
min-height: 31px;
|
||||
border-right: 1px solid #666;
|
||||
border-bottom: 1px solid #666;
|
||||
}
|
||||
|
||||
.city-progress__label {
|
||||
.city-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
border-right: 1px solid gray;
|
||||
border-bottom: 1px solid gray;
|
||||
background-color: #172a52;
|
||||
background-image: var(--sammo-texture-blue);
|
||||
}
|
||||
|
||||
.city-title,
|
||||
.city-nation {
|
||||
grid-column: 1 / -1;
|
||||
min-width: 0;
|
||||
border-top: 1px solid gray;
|
||||
border-left: 1px solid gray;
|
||||
overflow: hidden;
|
||||
font-weight: 700;
|
||||
text-align: center;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.city-panel {
|
||||
display: grid;
|
||||
min-width: 0;
|
||||
grid-template-columns: 1fr 2fr;
|
||||
border-top: 1px solid gray;
|
||||
border-left: 1px solid gray;
|
||||
}
|
||||
|
||||
.city-panel--population {
|
||||
grid-column: 1 / 3;
|
||||
grid-template-columns: 1fr 5fr;
|
||||
}
|
||||
|
||||
.city-panel__head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: rgb(20 75 42 / 70%);
|
||||
}
|
||||
|
||||
.city-panel__body {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.city-progress__body {
|
||||
display: grid;
|
||||
min-width: 0;
|
||||
align-content: center;
|
||||
padding: 1px 3px;
|
||||
}
|
||||
|
||||
.city-progress__text {
|
||||
overflow: hidden;
|
||||
line-height: 14px;
|
||||
line-height: 1.2em;
|
||||
text-align: center;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.city-officer__name {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.empty {
|
||||
color: rgba(232, 221, 196, 0.6);
|
||||
}
|
||||
|
||||
@media (max-width: 939.98px) {
|
||||
.progress-grid {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
@media (min-width: 940px) {
|
||||
.city-grid {
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.city-panel--officer-4 {
|
||||
grid-column: 4 / 5;
|
||||
grid-row: 3 / 4;
|
||||
}
|
||||
|
||||
.city-panel--officer-3 {
|
||||
grid-column: 4 / 5;
|
||||
grid-row: 4 / 5;
|
||||
}
|
||||
|
||||
.city-panel--officer-2 {
|
||||
grid-column: 4 / 5;
|
||||
grid-row: 5 / 6;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user