Browse Source

作战时间与推演时间轴匹配

master
ctw 2 months ago
parent
commit
82f4c31624
  1. 63
      ruoyi-ui/src/views/childRoom/TopHeader.vue
  2. 67
      ruoyi-ui/src/views/childRoom/index.vue

63
ruoyi-ui/src/views/childRoom/TopHeader.vue

@ -234,16 +234,22 @@
</div>
<div
class="info-box"
class="info-box combat-time-box"
:class="{ 'clickable': true }"
@click="$emit('set-k-time')"
>
<i class="el-icon-timer info-icon"></i>
<div class="info-content">
<div class="info-label">{{ $t('topHeader.info.combatTime') }}</div>
<div class="info-value">
<div class="info-content combat-time-content">
<div v-if="kTimeDisplay" class="combat-k-time">
<span class="k-time-label">K </span>
<span class="k-time-value">{{ kTimeDisplay }}</span>
</div>
<div class="combat-time-row">
<span class="info-label">{{ $t('topHeader.info.combatTime') }}</span>
<span class="combat-time-value">
{{ combatTime }}
<i v-if="canSetKTime" class="el-icon-edit-outline set-k-hint" title="点击设定或修改 K 时(房主/管理员可随时更改)"></i>
</span>
</div>
</div>
</div>
@ -315,6 +321,11 @@ export default {
type: String,
default: 'K+01:30:45'
},
/** 格式化的 K 时基准时刻,如 "2025-02-06 08:00:00" */
kTimeDisplay: {
type: String,
default: ''
},
astroTime: {
type: String,
default: ''
@ -877,9 +888,43 @@ export default {
box-shadow: 0 4px 12px rgba(0, 138, 255, 0.1);
}
.combat-info-group .info-box:nth-child(3) .info-value {
color: #409EFF;
/* 作战时间区域:显示 K 时 + 当前作战时间 */
.combat-time-box {
min-width: 180px;
}
.combat-time-content {
gap: 6px;
}
.combat-k-time {
display: flex;
align-items: center;
gap: 6px;
font-size: 11px;
color: #666;
}
.combat-k-time .k-time-label {
color: #008aff;
font-weight: 600;
flex-shrink: 0;
}
.combat-k-time .k-time-value {
color: #333;
font-weight: 500;
}
.combat-time-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
}
.combat-time-row .info-label {
flex-shrink: 0;
}
.combat-time-value {
font-size: 14px;
color: #008aff;
font-weight: 700;
letter-spacing: 0.5px;
}
.combat-info-group .info-box:nth-child(4) .info-value {
@ -897,6 +942,12 @@ export default {
color: #008aff;
vertical-align: middle;
}
.combat-time-box .set-k-hint {
opacity: 0.85;
}
.combat-time-box .set-k-hint:hover {
opacity: 1;
}
.info-icon {
font-size: 20px;

67
ruoyi-ui/src/views/childRoom/index.vue

@ -64,6 +64,7 @@
:room-code="roomCode"
:online-count="onlineCount"
:combat-time="combatTime"
:k-time-display="kTimeDisplay"
:astro-time="astroTime"
:room-detail="roomDetail"
:can-set-k-time="canSetKTime"
@ -395,7 +396,7 @@ export default {
//
roomCode: 'JTF-7-ALPHA',
onlineCount: 30,
combatTime: 'K+01:30:45',
combatTime: 'K+00:00:00', //
astroTime: '',
roomDetail: null,
showKTimeSetDialog: false,
@ -512,9 +513,9 @@ export default {
seaPlatforms: [],
groundPlatforms: [],
//
timeProgress: 45,
currentTime: 'K+01:15:30',
// K+00:00:00
timeProgress: 0,
currentTime: 'K+00:00:00',
deductionMinutesFromK: 0,
deductionWarnings: [],
isPlaying: false,
@ -531,6 +532,19 @@ export default {
this.updateTimeFromProgress();
},
immediate: true
},
/** 点开航线时:用当前固定作战时间同步时间轴与图标位置 */
activeRouteIds: {
handler(ids) {
if (!ids || ids.length === 0) return;
this.$nextTick(() => {
const minutes = this.combatTimeToMinutes(this.combatTime);
const { minMinutes, maxMinutes } = this.getDeductionTimeRange();
const span = Math.max(0, maxMinutes - minMinutes) || 120;
const progress = Math.max(0, Math.min(100, ((minutes - minMinutes) / span) * 100));
this.timeProgress = progress;
});
}
}
},
computed: {
@ -550,6 +564,11 @@ export default {
},
canSetKTime() {
return this.isRoomOwner || this.isAdmin;
},
/** 格式化的 K 时(基准时刻),供右上角显示 */
kTimeDisplay() {
if (!this.roomDetail || !this.roomDetail.kAnchorTime) return '';
return this.formatKTimeForPicker(this.roomDetail.kAnchorTime) || '';
}
},
mounted() {
@ -1090,20 +1109,32 @@ export default {
this.astroTime = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
},
/** 是否有选中的航线用于推演(有则作战时间随推演时间轴变化) */
hasDeductionRange() {
return this.activeRouteIds && this.activeRouteIds.length > 0;
},
updateCombatTime() {
if (this.roomDetail && this.roomDetail.kAnchorTime) {
const k0 = new Date(this.roomDetail.kAnchorTime).getTime();
const now = Date.now();
const offsetMs = now - k0;
const sign = offsetMs >= 0 ? '+' : '-';
const absMs = Math.abs(offsetMs);
const hours = Math.floor(absMs / 3600000);
const minutes = Math.floor((absMs % 3600000) / 60000);
const seconds = Math.floor((absMs % 60000) / 1000);
this.combatTime = `K${sign}${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
} else {
this.combatTime = '未设定';
// 线 = updateTimeFromProgress
if (this.hasDeductionRange()) {
const sign = this.deductionMinutesFromK >= 0 ? '+' : '-';
const absMin = Math.abs(Math.floor(this.deductionMinutesFromK));
const hours = Math.floor(absMin / 60);
const minutes = absMin % 60;
this.combatTime = `K${sign}${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:00`;
return;
}
// 线
this.combatTime = 'K+00:00:00';
},
/** 将作战时间字符串(如 K+01:30:00)解析为相对 K 的分钟数 */
combatTimeToMinutes(str) {
if (!str || str === '未设定') return 0;
const m = String(str).match(/K([+-])(\d{1,2}):(\d{2})(?::(\d{2}))?/);
if (!m) return 0;
const sign = m[1] === '+' ? 1 : -1;
const h = parseInt(m[2], 10);
const min = parseInt(m[3], 10);
return sign * (h * 60 + min);
},
getRoomDetail() {
if (!this.currentRoomId) return;
@ -1706,6 +1737,10 @@ export default {
const hours = Math.floor(absMin / 60);
const minutes = absMin % 60;
this.currentTime = `K${sign}${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:00`;
//
if (this.hasDeductionRange()) {
this.combatTime = this.currentTime;
}
this.updateDeductionPositions();
},

Loading…
Cancel
Save