복구 2배속의 게임·실제 시간 표시 설정과 시계 빠른 전환 추가

This commit is contained in:
2026-09-10 04:22:18 +00:00
parent 3a5d4e7833
commit 73e1743a3d
26 changed files with 537 additions and 165 deletions
+5 -3
View File
@@ -1,4 +1,6 @@
<script setup lang="ts">
import { useClockDisplay } from '../composables/useClockDisplay';
const { formatTime: formatGameTime } = useClockDisplay();
import { formatServerDateTime } from '@sammo-ts/common/time/ServerDateTime';
import { computed, onMounted, reactive, ref, watch } from 'vue';
import { useRoute } from 'vue-router';
@@ -42,8 +44,8 @@ const resolveErrorMessage = (value: unknown): string => {
const formatNumber = (value: number | null | undefined): string => (value ?? 0).toLocaleString();
const displayCode = (value: string | null | undefined): string =>
!value || /^\d+$/u.test(value) ? '-' : value.replace(/^che_(?:event_)?/u, '');
const cutDateTime = (value: string | null | undefined, showSecond = false): string => {
return formatServerDateTime(value, {
const cutDateTime = (value: string | null | undefined, showSecond = false, gameTime = true): string => {
return (gameTime ? formatGameTime : formatServerDateTime)(value, {
format: showSecond ? 'monthDayTimeSeconds' : 'monthDayTime',
fallback: '-',
});
@@ -413,7 +415,7 @@ onMounted(() => {
<div v-for="bid in uniqueDetail.bids" :key="bid.id" class="bid-row">
<span :class="{ 'is-me': bid.isCaller }">{{ bid.bidderName }}</span>
<span class="tnum">{{ formatNumber(bid.amount) }}</span>
<time class="tnum">{{ cutDateTime(bid.eventAt) }}</time>
<time class="tnum">{{ cutDateTime(bid.eventAt, false, false) }}</time>
</div>
<template v-if="uniqueDetail.auction.status === 'OPEN'">
<h3 class="subsection-title bg1">입찰하기</h3>
@@ -1,4 +1,6 @@
<script setup lang="ts">
import { useClockDisplay } from '../composables/useClockDisplay';
const { formatTime: formatGameTime } = useClockDisplay();
import { formatServerDateTime } from '@sammo-ts/common/time/ServerDateTime';
import { computed, onMounted, reactive, ref, watch } from 'vue';
import { useRoute } from 'vue-router';
@@ -130,7 +132,7 @@ const selectedGeneral = computed(() => {
const formatGeneralLabel = (general: GeneralEntry): string => {
const name = general.officerLevel > 4 ? `*${general.name}*` : general.name;
const time = formatServerDateTime(general.turnTime, { format: 'hourMinute', fallback: '--:--' });
const time = formatGameTime(general.turnTime, { format: 'hourMinute', fallback: '--:--' });
if (orderBy.value === 'recentWar') {
return `${name} (${formatServerDateTime(general.recentWar, { format: 'hourMinute', fallback: '--:--' })})`;
}
+3 -2
View File
@@ -1,5 +1,6 @@
<script setup lang="ts">
import { formatServerDateTime } from '@sammo-ts/common/time/ServerDateTime';
import { useClockDisplay } from '../composables/useClockDisplay';
const { formatTime: formatGameTime } = useClockDisplay();
import { storeToRefs } from 'pinia';
import { computed, nextTick, onMounted, onUnmounted, ref } from 'vue';
import TournamentBracket from '../components/tournament/TournamentBracket.vue';
@@ -53,7 +54,7 @@ const ratio = (id: number) => {
return amount ? (totalAmount.value / amount).toFixed(2) : '0';
};
const openingTime = computed(() =>
formatServerDateTime(snapshot.value?.state?.nextAt, { format: 'hourMinute', fallback: '--:--' })
formatGameTime(snapshot.value?.state?.nextAt, { format: 'hourMinute', fallback: '--:--' })
);
const selectedRatio = computed(() => {
const targetId = selectedTarget.value?.id;
@@ -1,9 +1,10 @@
<script setup lang="ts">
import { useClockDisplay } from '../composables/useClockDisplay';
const { formatTime: formatGameTime } = useClockDisplay();
import { computed, onMounted, ref, watch } from 'vue';
import { useMediaQuery } from '@vueuse/core';
import { addMinutes } from 'date-fns';
import { useRouter } from 'vue-router';
import { formatServerDateTime } from '@sammo-ts/common/time/ServerDateTime';
import SkeletonLines from '../components/ui/SkeletonLines.vue';
import ChiefTurnCard from '../components/chief/ChiefTurnCard.vue';
import ChiefCommandEditor from '../components/chief/ChiefCommandEditor.vue';
@@ -220,8 +221,8 @@ const buildTurnRows = (chief: ChiefEntry): TurnRow[] => {
baseTime && Number.isFinite(turnTermMinutes) ? addMinutes(baseTime, idx * turnTermMinutes) : null;
const timeLabel = turnDate
? turnTermMinutes >= 5
? formatServerDateTime(turnDate, { format: 'hourMinute' })
: formatServerDateTime(turnDate, { format: 'minuteSecond' })
? formatGameTime(turnDate, { format: 'hourMinute' })
: formatGameTime(turnDate, { format: 'minuteSecond' })
: '--:--';
const actionLabel =
formatReservedCommandBrief('nation', turn.action, turn.args, commandTable.value) ??
+2 -1
View File
@@ -10,7 +10,8 @@ import { sortGeneralsByTypeThenName } from '../utils/generalOrder';
import { useSessionStore } from '../stores/session';
import { cityLevelMap, formatOfficerLevelText, regionMap } from '../utils/nationFormat';
import { getNpcColor } from '../utils/npcColor';
import { formatSeoulDateTime } from '../utils/legacyDateTime';
import { useClockDisplay } from '../composables/useClockDisplay';
const { formatTime: formatSeoulDateTime } = useClockDisplay();
import { resolveGeneralIconUrl, useDefaultGeneralIcon } from '../utils/generalIcon';
import { abilityLeadint, abilityLeadpow, abilityPowint, abilityRand, type GeneralStats } from '../utils/generalStats';
import { legacyLuminanceTextColor } from '../utils/legacyNationColor';
+2 -1
View File
@@ -3,7 +3,8 @@ import { JosaUtil } from '@sammo-ts/common/util/JosaUtil';
import { computed, onMounted, reactive, ref } from 'vue';
import { trpc } from '../utils/trpc';
import { formatLog } from '../utils/formatLog';
import { formatSeoulDateTime } from '../utils/legacyDateTime';
import { useClockDisplay } from '../composables/useClockDisplay';
const { formatTime: formatSeoulDateTime } = useClockDisplay();
import { isDefenceTrainPenaltyWaivedByScenarioEffect } from '@sammo-ts/logic/scenario/scenarioEffect.js';
import { useSessionStore } from '../stores/session';
import GeneralInformationPanel from '../components/main/GeneralInformationPanel.vue';
@@ -1,4 +1,6 @@
<script setup lang="ts">
import { useClockDisplay } from '../composables/useClockDisplay';
const { mode: clockDisplayMode } = useClockDisplay();
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue';
import { trpc } from '../utils/trpc';
import { formatSeoulDateTime } from '../utils/legacyDateTime';
@@ -148,6 +150,18 @@ onBeforeUnmount(() => {
</div>
</div>
<div class="screen-mode-row">
<span
>가속 시간 표시 기준<br /><small
> 기기에 저장하며, 2배속 중에는 시계를 눌러 바꿀 있습니다.</small
></span
>
<div class="button-group" role="radiogroup" aria-label="가속 시간 표시 기준">
<label><input v-model="clockDisplayMode" type="radio" value="game" />게임 시간 기준</label>
<label><input v-model="clockDisplayMode" type="radio" value="real" />실제 시간 기준</label>
</div>
</div>
<div class="mobile-layout-setting-row">
<span>
모바일 메인 레이아웃<br />
@@ -1,5 +1,6 @@
<script setup lang="ts">
import { formatServerDateTime } from '@sammo-ts/common/time/ServerDateTime';
import { useClockDisplay } from '../composables/useClockDisplay';
const { formatTime: formatGameTime } = useClockDisplay();
import { JosaUtil } from '@sammo-ts/common/util/JosaUtil';
import { computed, onMounted, ref } from 'vue';
import { useRouter } from 'vue-router';
@@ -700,7 +701,7 @@ onMounted(async () => {
</template>
</td>
<td>{{ general.killTurn }}</td>
<td>{{ formatServerDateTime(general.turnTime, { format: 'minuteSecond' }) }}</td>
<td>{{ formatGameTime(general.turnTime, { format: 'minuteSecond' }) }}</td>
</tr>
</tbody>
</table>
@@ -1,4 +1,6 @@
<script setup lang="ts">
import { useClockDisplay } from '../composables/useClockDisplay';
const { formatTime: formatGameTime } = useClockDisplay();
import { formatServerDateTime } from '@sammo-ts/common/time/ServerDateTime';
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue';
import { useRouter } from 'vue-router';
@@ -495,7 +497,7 @@ const cellValue = (general: General, columnId: NationGeneralColumnId): CellValue
case 'reservedCommand':
return commandText(general, false);
case 'turntime':
return formatServerDateTime(details(general).turnTime, { format: 'minuteSecond', fallback: '?' });
return formatGameTime(details(general).turnTime, { format: 'minuteSecond', fallback: '?' });
case 'recent_war':
return formatServerDateTime(details(general).recentWar, { format: 'minuteSecond', fallback: '-' });
case 'years_1':
@@ -1,5 +1,6 @@
<script setup lang="ts">
import { formatServerDateTime } from '@sammo-ts/common/time/ServerDateTime';
import { useClockDisplay } from '../composables/useClockDisplay';
const { formatTime: formatGameTime } = useClockDisplay();
import { computed, onMounted, ref } from 'vue';
import { formatReservedCommandBrief } from '../components/command/reservedCommandBrief';
import type { CommandTable } from '../components/command/types';
@@ -332,7 +333,7 @@ onMounted(load);
>
</td>
<td>{{ general.killTurn }}</td>
<td>{{ formatServerDateTime(general.turnTime, { format: 'minuteSecond' }) }}</td>
<td>{{ formatGameTime(general.turnTime, { format: 'minuteSecond' }) }}</td>
</tr>
</tbody>
</table>
@@ -4,7 +4,8 @@ import { useRouter } from 'vue-router';
import { useGameFeedback } from '../composables/useGameFeedback';
import { useSessionStore } from '../stores/session';
import { formatSeoulDateTime } from '../utils/legacyDateTime';
import { useClockDisplay } from '../composables/useClockDisplay';
const { formatTime: formatSeoulDateTime } = useClockDisplay();
import { resolveGeneralIconUrl, useDefaultGeneralIcon } from '../utils/generalIcon';
import { legacyLuminanceTextColor } from '../utils/legacyNationColor';
import { trpc } from '../utils/trpc';
@@ -1,5 +1,6 @@
<script setup lang="ts">
import { formatServerDateTime } from '@sammo-ts/common/time/ServerDateTime';
import { useClockDisplay } from '../composables/useClockDisplay';
const { formatTime: formatGameTime } = useClockDisplay();
import { storeToRefs } from 'pinia';
import { computed, nextTick, onMounted, onUnmounted, ref } from 'vue';
import TournamentBracket from '../components/tournament/TournamentBracket.vue';
@@ -55,7 +56,7 @@ const matchesAt = (stage: number) =>
.sort((a, b) => a.roundIndex - b.roundIndex);
const nameOf = (id?: number) => (id ? (participantsById.value.get(id)?.name ?? `#${id}`) : '-');
const openingTime = computed(() =>
formatServerDateTime(snapshot.value?.state?.nextAt, { format: 'hourMinute', fallback: '--:--' })
formatGameTime(snapshot.value?.state?.nextAt, { format: 'hourMinute', fallback: '--:--' })
);
const isParticipant = computed(() =>
(snapshot.value?.participants ?? []).some((participant) => participant.id === myGeneralId.value)
+3 -2
View File
@@ -1,5 +1,6 @@
<script setup lang="ts">
import { formatServerDateTime } from '@sammo-ts/common/time/ServerDateTime';
import { useClockDisplay } from '../composables/useClockDisplay';
const { formatTime: formatGameTime } = useClockDisplay();
import { computed, onMounted, ref } from 'vue';
import { useRouter } from 'vue-router';
@@ -170,7 +171,7 @@ const hideMemberPopup = () => {
const iconPath = (troop: Troop): string => resolveGeneralIconUrl(troop.leader ?? {});
const formatTurn = (turnTime: string | null): string => {
return formatServerDateTime(turnTime, { format: 'minuteSecond', fallback: '--:--' });
return formatGameTime(turnTime, { format: 'minuteSecond', fallback: '--:--' });
};
onMounted(() => {