|
@@ -304,7 +304,12 @@
|
|
|
<!-- 时间轴轨道 -->
|
|
<!-- 时间轴轨道 -->
|
|
|
<div :class="['timeline-track', { 'is-playing': isTimelinePlaying }]" ref="timelineTrackRef">
|
|
<div :class="['timeline-track', { 'is-playing': isTimelinePlaying }]" ref="timelineTrackRef">
|
|
|
<!-- 时间轴进度指示器 -->
|
|
<!-- 时间轴进度指示器 -->
|
|
|
- <div class="timeline-progress" :style="{ width: `${timelineProgress}%` }"></div>
|
|
|
|
|
|
|
+ <div class="timeline-progress" :style="{ width: `${timelineProgress}%` }">
|
|
|
|
|
+ <!-- 巡航时显示当前时间 -->
|
|
|
|
|
+ <div v-if="isTimelinePlaying" class="progress-time">
|
|
|
|
|
+ {{ formatTimelineTime(currentPlayTime) }}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
<!-- 关键点 - 竖线风格 -->
|
|
<!-- 关键点 - 竖线风格 -->
|
|
|
<div
|
|
<div
|
|
|
v-for="point in timelinePoints"
|
|
v-for="point in timelinePoints"
|
|
@@ -760,6 +765,10 @@ const timelinePoints = ref<TimelinePoint[]>([])
|
|
|
const selectedPoint = ref<TimelinePoint | null>(null)
|
|
const selectedPoint = ref<TimelinePoint | null>(null)
|
|
|
const isTimelinePlaying = ref(false)
|
|
const isTimelinePlaying = ref(false)
|
|
|
const timelineProgress = ref(0)
|
|
const timelineProgress = ref(0)
|
|
|
|
|
+// 当前播放时间(秒)
|
|
|
|
|
+const currentPlayTime = computed(() => {
|
|
|
|
|
+ return Math.round((timelineProgress.value / 100) * timelineDuration.value)
|
|
|
|
|
+})
|
|
|
const savingPreset = ref(false)
|
|
const savingPreset = ref(false)
|
|
|
const isLoopEnabled = ref(false) // 是否循环巡航
|
|
const isLoopEnabled = ref(false) // 是否循环巡航
|
|
|
let timelinePlayAbort: AbortController | null = null
|
|
let timelinePlayAbort: AbortController | null = null
|
|
@@ -2410,6 +2419,33 @@ onMounted(async () => {
|
|
|
border-radius: 2px 0 0 2px;
|
|
border-radius: 2px 0 0 2px;
|
|
|
pointer-events: none;
|
|
pointer-events: none;
|
|
|
transition: width 0.3s ease;
|
|
transition: width 0.3s ease;
|
|
|
|
|
+
|
|
|
|
|
+ // 当前播放时间显示
|
|
|
|
|
+ .progress-time {
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ right: 0;
|
|
|
|
|
+ top: calc(100% + 4px);
|
|
|
|
|
+ transform: translateX(50%);
|
|
|
|
|
+ background: #ef4444;
|
|
|
|
|
+ color: #fff;
|
|
|
|
|
+ padding: 2px 6px;
|
|
|
|
|
+ border-radius: 4px;
|
|
|
|
|
+ font-size: 11px;
|
|
|
|
|
+ font-weight: 600;
|
|
|
|
|
+ white-space: nowrap;
|
|
|
|
|
+ pointer-events: none;
|
|
|
|
|
+ z-index: 15;
|
|
|
|
|
+
|
|
|
|
|
+ &::before {
|
|
|
|
|
+ content: '';
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ bottom: 100%;
|
|
|
|
|
+ left: 50%;
|
|
|
|
|
+ transform: translateX(-50%);
|
|
|
|
|
+ border: 4px solid transparent;
|
|
|
|
|
+ border-bottom-color: #ef4444;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 圆形打点
|
|
// 圆形打点
|
|
@@ -2460,8 +2496,12 @@ onMounted(async () => {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
&.passed {
|
|
&.passed {
|
|
|
- background: #22c55e; // 巡航走过 - 绿色
|
|
|
|
|
- box-shadow: 0 0 8px rgba(34, 197, 94, 0.6);
|
|
|
|
|
|
|
+ background: #818cf8; // 巡航走过 - 主题色(紫蓝色)
|
|
|
|
|
+ box-shadow: 0 0 8px rgba(129, 140, 248, 0.6);
|
|
|
|
|
+
|
|
|
|
|
+ .point-number {
|
|
|
|
|
+ color: #fff;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
&.dragging {
|
|
&.dragging {
|