fix(game-ui): 내정보와 감찰부 장수 패널을 통일한다
두 화면이 같은 장수 정보 패널에서 전투 통계와 숙련도를 렌더링하도록 정리한다. 감찰부 통계를 rank_data에서 읽고 삭턴, 사관, 최근 전투와 승률·살상률 계약을 맞춘다.
This commit is contained in:
@@ -22,6 +22,7 @@ interface GeneralProgression {
|
||||
dedicationText?: string;
|
||||
statExperience?: { leadership: number; strength: number; intelligence: number };
|
||||
statUpgradeLimit?: number;
|
||||
dex?: number[];
|
||||
}
|
||||
|
||||
interface ItemDisplayNames {
|
||||
@@ -65,7 +66,7 @@ interface GeneralRefreshScore {
|
||||
text: string;
|
||||
}
|
||||
|
||||
interface GeneralInfo {
|
||||
export interface GeneralBasicCardData {
|
||||
id: number;
|
||||
name: string;
|
||||
picture?: string | null;
|
||||
@@ -107,7 +108,7 @@ interface GeneralInfo {
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
general: GeneralInfo | null;
|
||||
general: GeneralBasicCardData | null;
|
||||
loading: boolean;
|
||||
nationColor?: string | null;
|
||||
defenceText?: string | null;
|
||||
|
||||
@@ -11,6 +11,7 @@ export type GeneralBattleSummaryData = {
|
||||
wins?: number | null;
|
||||
losses?: number | null;
|
||||
strategies?: number | null;
|
||||
serviceYears?: number | null;
|
||||
killCrew?: number | null;
|
||||
deathCrew?: number | null;
|
||||
winRate?: number | null;
|
||||
@@ -30,7 +31,7 @@ const props = withDefaults(
|
||||
const numberText = (value: number | null | undefined): string =>
|
||||
typeof value === 'number' && Number.isFinite(value) ? value.toLocaleString('ko-KR') : '-';
|
||||
|
||||
const rateText = (value: number): string => `${(props.rateScale === 'percent' ? value : value * 100).toFixed(1)}%`;
|
||||
const rateText = (value: number): string => `${(props.rateScale === 'percent' ? value : value * 100).toFixed(2)}%`;
|
||||
|
||||
const winRate = computed(() => {
|
||||
if (typeof props.summary.winRate === 'number' && Number.isFinite(props.summary.winRate)) {
|
||||
@@ -39,7 +40,7 @@ const winRate = computed(() => {
|
||||
const battles = props.summary.warnum;
|
||||
const wins = props.summary.wins;
|
||||
if (typeof battles !== 'number' || battles <= 0 || typeof wins !== 'number') return '-';
|
||||
return `${((wins / battles) * 100).toFixed(1)}%`;
|
||||
return `${((wins / battles) * 100).toFixed(2)}%`;
|
||||
});
|
||||
|
||||
const killRate = computed(() => {
|
||||
@@ -49,7 +50,7 @@ const killRate = computed(() => {
|
||||
const killed = props.summary.killCrew;
|
||||
const lost = props.summary.deathCrew;
|
||||
if (typeof killed !== 'number' || typeof lost !== 'number' || lost <= 0) return '-';
|
||||
return `${((killed / lost) * 100).toFixed(1)}%`;
|
||||
return `${((killed / lost) * 100).toFixed(2)}%`;
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -64,8 +65,15 @@ const killRate = computed(() => {
|
||||
><strong>{{ numberText(summary.warnum) }}<template v-if="summary.warnum != null">회</template></strong>
|
||||
<span>승리</span><strong>{{ numberText(summary.wins) }}</strong> <span>패배</span
|
||||
><strong>{{ numberText(summary.losses) }}</strong> <span>계략</span
|
||||
><strong>{{ numberText(summary.strategies) }}</strong> <span>사살</span
|
||||
><strong>{{ numberText(summary.killCrew) }}</strong> <span>피살</span
|
||||
><strong>{{ numberText(summary.strategies) }}</strong>
|
||||
<template v-if="summary.serviceYears !== undefined">
|
||||
<span>사관</span
|
||||
><strong
|
||||
>{{ numberText(summary.serviceYears)
|
||||
}}<template v-if="summary.serviceYears != null">년</template></strong
|
||||
>
|
||||
</template>
|
||||
<span>사살</span><strong>{{ numberText(summary.killCrew) }}</strong> <span>피살</span
|
||||
><strong>{{ numberText(summary.deathCrew) }}</strong>
|
||||
<template v-if="showWinRate">
|
||||
<span>승률</span><strong>{{ winRate }}</strong> <span>살상률</span><strong>{{ killRate }}</strong>
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
<script setup lang="ts">
|
||||
import GeneralBasicCard, { type GeneralBasicCardData } from './GeneralBasicCard.vue';
|
||||
import GeneralBattleSummary, { type GeneralBattleSummaryData } from './GeneralBattleSummary.vue';
|
||||
import LegacyGeneralProgress from '../ui/LegacyGeneralProgress.vue';
|
||||
|
||||
type BasicProgression = NonNullable<GeneralBasicCardData['progression']>;
|
||||
|
||||
export type GeneralInformationPanelData = GeneralBasicCardData & {
|
||||
progression: BasicProgression & {
|
||||
statExperience: NonNullable<BasicProgression['statExperience']>;
|
||||
statUpgradeLimit: number;
|
||||
dex: number[];
|
||||
};
|
||||
};
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
general: GeneralInformationPanelData | null;
|
||||
summary: GeneralBattleSummaryData | null;
|
||||
loading: boolean;
|
||||
nationColor?: string | null;
|
||||
defenceText?: string | null;
|
||||
killTurn?: number | null;
|
||||
remainingMinutes?: number | null;
|
||||
troopText?: string | null;
|
||||
penaltyText?: string | number | null;
|
||||
}>(),
|
||||
{
|
||||
nationColor: '#173d27',
|
||||
defenceText: null,
|
||||
killTurn: null,
|
||||
remainingMinutes: null,
|
||||
troopText: null,
|
||||
penaltyText: null,
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<GeneralBasicCard
|
||||
data-general-information-panel
|
||||
:general="props.general"
|
||||
:loading="props.loading"
|
||||
:nation-color="props.nationColor"
|
||||
:defence-text="props.defenceText"
|
||||
:kill-turn="props.killTurn"
|
||||
:remaining-minutes="props.remainingMinutes"
|
||||
:troop-text="props.troopText"
|
||||
:penalty-text="props.penaltyText"
|
||||
>
|
||||
<template v-if="props.general" #details>
|
||||
<GeneralBattleSummary v-if="props.summary" :summary="props.summary" show-win-rate />
|
||||
<LegacyGeneralProgress :general="props.general" :show-primary="false" />
|
||||
</template>
|
||||
</GeneralBasicCard>
|
||||
</template>
|
||||
Reference in New Issue
Block a user