merge: 최신 core2026 main을 접속 제한 작업에 통합
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { computed, onUnmounted, ref, watch } from 'vue';
|
||||
import { addMinutes } from 'date-fns';
|
||||
import ReservedCommandEditor from '../command/ReservedCommandEditor.vue';
|
||||
import { formatSeoulTimeSeconds } from '../../utils/legacyDateTime';
|
||||
import { formatLocalTimeSeconds } from '../../utils/legacyDateTime';
|
||||
import type {
|
||||
CommandMapData,
|
||||
CommandMapLayout,
|
||||
@@ -19,6 +19,8 @@ const props = defineProps<{
|
||||
currentYear?: number;
|
||||
currentMonth?: number;
|
||||
turnTermMinutes?: number;
|
||||
serverTime?: string;
|
||||
clockMode?: 'realtime' | 'manual';
|
||||
autorunLimit?: number | null;
|
||||
storageKey?: string;
|
||||
mapData?: CommandMapData | null;
|
||||
@@ -56,16 +58,48 @@ const rows = computed<ReservedCommandRow[]>(() => {
|
||||
autonomous: props.autorunLimit != null && absoluteMonth <= props.autorunLimit - 1,
|
||||
time: date
|
||||
? term >= 5
|
||||
? `${String(date.getUTCHours()).padStart(2, '0')}:${String(date.getUTCMinutes()).padStart(2, '0')}`
|
||||
: `${String(date.getUTCMinutes()).padStart(2, '0')}:${String(date.getUTCSeconds()).padStart(2, '0')}`
|
||||
? `${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`
|
||||
: `${String(date.getMinutes()).padStart(2, '0')}:${String(date.getSeconds()).padStart(2, '0')}`
|
||||
: '--:--',
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
const currentTurnTime = computed(() =>
|
||||
props.general?.turnTime ? formatSeoulTimeSeconds(props.general.turnTime) : '--:--:--'
|
||||
const currentServerTime = ref('--:--:--');
|
||||
let sampledServerTimeMs: number | null = null;
|
||||
let sampledClientTimeMs = 0;
|
||||
let serverClockTimer: ReturnType<typeof setTimeout> | undefined;
|
||||
|
||||
const updateServerClock = () => {
|
||||
if (serverClockTimer !== undefined) clearTimeout(serverClockTimer);
|
||||
serverClockTimer = undefined;
|
||||
if (sampledServerTimeMs === null) {
|
||||
currentServerTime.value = '--:--:--';
|
||||
return;
|
||||
}
|
||||
const projectedTime = new Date(
|
||||
props.clockMode === 'manual' ? sampledServerTimeMs : sampledServerTimeMs + Date.now() - sampledClientTimeMs
|
||||
);
|
||||
currentServerTime.value = formatLocalTimeSeconds(projectedTime);
|
||||
if (props.clockMode !== 'manual') {
|
||||
serverClockTimer = setTimeout(updateServerClock, 1_000 - projectedTime.getMilliseconds());
|
||||
}
|
||||
};
|
||||
|
||||
watch(
|
||||
() => [props.serverTime, props.clockMode] as const,
|
||||
([serverTime]) => {
|
||||
const parsed = serverTime ? new Date(serverTime).getTime() : Number.NaN;
|
||||
sampledServerTimeMs = Number.isFinite(parsed) ? parsed : null;
|
||||
sampledClientTimeMs = Date.now();
|
||||
updateServerClock();
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
onUnmounted(() => {
|
||||
if (serverClockTimer !== undefined) clearTimeout(serverClockTimer);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -75,7 +109,7 @@ const currentTurnTime = computed(() =>
|
||||
:command-table="props.commandTable"
|
||||
:loading="props.loading"
|
||||
:storage-key="props.storageKey ?? `core2026:general:${props.general?.id ?? 0}`"
|
||||
:current-time="currentTurnTime"
|
||||
:current-time="currentServerTime"
|
||||
:map-data="props.mapData"
|
||||
:map-layout="props.mapLayout"
|
||||
@reserve-bulk="emit('set-general-turns', $event)"
|
||||
|
||||
@@ -3,7 +3,7 @@ import { computed } from 'vue';
|
||||
|
||||
import SkeletonLines from '../ui/SkeletonLines.vue';
|
||||
import LegacyProgressBar from '../ui/LegacyProgressBar.vue';
|
||||
import { formatSeoulTimeSeconds } from '../../utils/legacyDateTime';
|
||||
import { formatLocalTimeSeconds } from '../../utils/legacyDateTime';
|
||||
import { legacyExperiencePercent, ratioPercent } from '../../utils/legacyProgress';
|
||||
import { DEFAULT_GENERAL_ICON_URL, resolveGeneralIconBackgroundImage } from '../../utils/generalIcon';
|
||||
import { configuredGameAssetUrl } from '../../utils/imageAssets';
|
||||
@@ -232,7 +232,7 @@ const specialText = computed(() => {
|
||||
{{ props.general.officerLevelText }} | {{ props.general.generalType ?? '-' }} |
|
||||
<span :style="{ color: injuryInfo.color }">{{ injuryInfo.text }}</span> 】
|
||||
<span data-general-turn-time>{{
|
||||
props.general.turnTime ? formatSeoulTimeSeconds(props.general.turnTime) : '-'
|
||||
props.general.turnTime ? formatLocalTimeSeconds(props.general.turnTime) : '-'
|
||||
}}</span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -7,3 +7,11 @@ export const formatSeoulHourMinute = (value: string | Date): string =>
|
||||
|
||||
export const formatSeoulTimeSeconds = (value: string | Date): string =>
|
||||
formatServerDateTime(value, { format: 'timeSeconds' });
|
||||
|
||||
export const formatLocalTimeSeconds = (value: string | Date): string => {
|
||||
const parsed = value instanceof Date ? value : new Date(value);
|
||||
if (!Number.isFinite(parsed.getTime())) return '-';
|
||||
return [parsed.getHours(), parsed.getMinutes(), parsed.getSeconds()]
|
||||
.map((part) => String(part).padStart(2, '0'))
|
||||
.join(':');
|
||||
};
|
||||
|
||||
@@ -726,10 +726,26 @@ onUnmounted(() => {
|
||||
</div>
|
||||
|
||||
<div class="stat-actions" role="group" aria-label="능력치 빠른 설정">
|
||||
<button type="button" @click="applyRandomStats">랜덤형</button>
|
||||
<button type="button" @click="applyLeadpowStats">통솔무력형</button>
|
||||
<button type="button" @click="applyLeadintStats">통솔지력형</button>
|
||||
<button type="button" @click="applyPowintStats">무력지력형</button>
|
||||
<button class="legacy-button legacy-button--navigation" type="button" @click="applyRandomStats">
|
||||
랜덤형
|
||||
</button>
|
||||
<button
|
||||
class="legacy-button legacy-button--navigation"
|
||||
type="button"
|
||||
@click="applyLeadpowStats"
|
||||
>
|
||||
통솔무력형
|
||||
</button>
|
||||
<button
|
||||
class="legacy-button legacy-button--navigation"
|
||||
type="button"
|
||||
@click="applyLeadintStats"
|
||||
>
|
||||
통솔지력형
|
||||
</button>
|
||||
<button class="legacy-button legacy-button--navigation" type="button" @click="applyPowintStats">
|
||||
무력지력형
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-if="accountIcons.length" class="icon-choice">
|
||||
@@ -1385,26 +1401,21 @@ onUnmounted(() => {
|
||||
|
||||
.stat-actions button {
|
||||
flex: 1 1 140px;
|
||||
height: 40px;
|
||||
min-height: 40px;
|
||||
border: 1px solid #004f28;
|
||||
border-radius: 3px;
|
||||
background: #00582c;
|
||||
padding: 8px 14px;
|
||||
color: #fff;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 700;
|
||||
line-height: 1.2;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.stat-actions button:hover {
|
||||
border-color: #005f30;
|
||||
background: #006d37;
|
||||
.stat-actions button:not(:disabled):hover {
|
||||
height: 39px;
|
||||
min-height: 39px;
|
||||
}
|
||||
|
||||
.stat-actions button:active {
|
||||
border-color: #003d1f;
|
||||
background: #004523;
|
||||
.stat-actions button:not(:disabled):active {
|
||||
height: 38px;
|
||||
min-height: 38px;
|
||||
}
|
||||
|
||||
.stat-summary {
|
||||
|
||||
@@ -205,6 +205,8 @@ watch(
|
||||
:current-year="lobbyInfo?.year"
|
||||
:current-month="lobbyInfo?.month"
|
||||
:turn-term-minutes="lobbyInfo?.turnTerm"
|
||||
:server-time="lobbyInfo?.serverTime"
|
||||
:clock-mode="lobbyInfo?.clockMode"
|
||||
:autorun-limit="reservedGeneralAutorunLimit"
|
||||
:map-data="worldMap"
|
||||
:map-layout="mapLayout"
|
||||
@@ -331,6 +333,8 @@ watch(
|
||||
:current-year="lobbyInfo?.year"
|
||||
:current-month="lobbyInfo?.month"
|
||||
:turn-term-minutes="lobbyInfo?.turnTerm"
|
||||
:server-time="lobbyInfo?.serverTime"
|
||||
:clock-mode="lobbyInfo?.clockMode"
|
||||
:autorun-limit="reservedGeneralAutorunLimit"
|
||||
:map-data="worldMap"
|
||||
:map-layout="mapLayout"
|
||||
@@ -666,11 +670,21 @@ button {
|
||||
}
|
||||
|
||||
.record-line {
|
||||
box-sizing: border-box;
|
||||
height: 21px;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
overflow-wrap: normal;
|
||||
line-height: 21px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.record-line :deep(.small_war_log) {
|
||||
height: 21px;
|
||||
line-height: 21px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.record-line :deep(.hidden_but_copyable) {
|
||||
color: transparent !important;
|
||||
font-size: 0;
|
||||
|
||||
Reference in New Issue
Block a user