Compare commits

...

2 Commits

3 changed files with 57 additions and 4 deletions

View File

@ -4,5 +4,5 @@ ENV_WEBSOCKET_BASE=/ws
ENV_STORAGE_WEBSOCKET_BASE=/vwedWs
# 开发环境token配置 - 可以手动设置或从另一个项目获取后填入
ENV_DEV_TOKEN=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3NTgyMTA0NTIsInVzZXJuYW1lIjoiYWRtaW4ifQ.UTbugug5gJAxFvC92T_5wqt4JeI_SnF4PeayjAx5K4g
ENV_DEV_TOKEN=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3NjAxMDE2MTgsInVzZXJuYW1lIjoiYWRtaW4ifQ.e9kehve_MAqVPDRHRpMsJp2rEgyPW5pz_s0XDYUoxyk
ENV_DEV_TENANT_ID=1000

View File

@ -6,7 +6,8 @@
"scripts": {
"start": "vite",
"build": "vue-tsc -b && vite build",
"preview": "vite preview"
"preview": "vite preview",
"no-ts-build": "vite build"
},
"dependencies": {
"@ant-design/icons-vue": "^7.0.1",

View File

@ -1,6 +1,6 @@
<script setup lang="ts">
import { CaretRightOutlined, PauseOutlined } from '@ant-design/icons-vue';
import { computed, ref, watch } from 'vue';
import { computed, ref, watch, onUnmounted } from 'vue';
import { useTimelineTicks } from '../hooks/useTimelineTicks';
@ -35,14 +35,66 @@ const { ticks } = useTimelineTicks(viewStartTime, viewEndTime);
watch(
() => props.currentTime,
(newValue) => {
internalCurrentTime.value = newValue;
// Only update from prop if not playing
if (!props.isPlaying) {
internalCurrentTime.value = newValue;
}
const newHour = Math.floor(newValue / HOUR_IN_MS);
if (newHour !== selectedHour.value) {
selectedHour.value = newHour;
}
},
{ immediate: true },
);
// --- Animation Frame Timer for Playback ---
let animationFrameId: number | null = null;
let lastTimestamp: number | null = null;
const animationLoop = (timestamp: number) => {
if (!lastTimestamp) {
lastTimestamp = timestamp;
}
const deltaTime = timestamp - lastTimestamp;
lastTimestamp = timestamp;
// Ensure we don't jump too far ahead if the tab was inactive
const clampedDelta = Math.min(deltaTime, 1000); // Max 1-second jump
const newTime = internalCurrentTime.value + clampedDelta;
if (newTime < props.totalDuration) {
internalCurrentTime.value = newTime;
// No need to emit timeupdate as per user decision
// emit('timeupdate', newTime);
animationFrameId = requestAnimationFrame(animationLoop);
} else {
internalCurrentTime.value = props.totalDuration;
emit('pause'); // Auto-pause at the end
}
};
watch(
() => props.isPlaying,
(isPlaying) => {
if (isPlaying) {
lastTimestamp = null; // Reset timestamp on play
animationFrameId = requestAnimationFrame(animationLoop);
} else {
if (animationFrameId) {
cancelAnimationFrame(animationFrameId);
animationFrameId = null;
}
}
},
);
onUnmounted(() => {
if (animationFrameId) {
cancelAnimationFrame(animationFrameId);
}
});
// --- Computed properties for display and binding ---
const formatTime = (ms: number): string => {
if (isNaN(ms) || ms < 0) return '00:00:00';