2025-09-29 17:40:12 +08:00
|
|
|
import { computed, type Ref } from 'vue';
|
|
|
|
|
|
|
|
|
|
export interface Tick {
|
|
|
|
|
position: string; // Percentage position within the view
|
|
|
|
|
label: string | null;
|
|
|
|
|
isMajor: boolean;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Formats time as hh:mm for labels
|
|
|
|
|
const formatLabelTime = (ms: number): string => {
|
|
|
|
|
const totalSeconds = Math.floor(ms / 1000);
|
|
|
|
|
const hours = Math.floor(totalSeconds / 3600);
|
|
|
|
|
const minutes = Math.floor((totalSeconds % 3600) / 60);
|
|
|
|
|
const pad = (num: number) => num.toString().padStart(2, '0');
|
|
|
|
|
return `${pad(hours)}:${pad(minutes)}`;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export function useTimelineTicks(viewStartTime: Ref<number>, viewEndTime: Ref<number>) {
|
|
|
|
|
const ticks = computed<Tick[]>(() => {
|
|
|
|
|
const startTime = viewStartTime.value;
|
|
|
|
|
const endTime = viewEndTime.value;
|
|
|
|
|
const viewDuration = endTime - startTime;
|
|
|
|
|
|
|
|
|
|
if (isNaN(startTime) || isNaN(endTime) || viewDuration <= 0) {
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const result: Tick[] = [];
|
|
|
|
|
|
|
|
|
|
// For a 1-hour view, we use fixed intervals
|
|
|
|
|
const majorTickInterval = 10 * 60 * 1000; // Every 10 minutes for labels
|
|
|
|
|
const minorTickInterval = 1 * 60 * 1000; // Every 1 minute for small ticks
|
|
|
|
|
|
|
|
|
|
for (let time = startTime; time <= endTime; time += minorTickInterval) {
|
|
|
|
|
// Ensure we only create ticks at exact minute marks relative to the start of the day
|
|
|
|
|
if (time % minorTickInterval !== 0) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const relativeTime = time - startTime;
|
|
|
|
|
const isMajor = time % majorTickInterval === 0;
|
|
|
|
|
|
|
|
|
|
result.push({
|
|
|
|
|
position: `${(relativeTime / viewDuration) * 100}%`,
|
2025-10-09 17:11:22 +08:00
|
|
|
// 使用相对视窗的时间展示,避免绝对时间导致的大数/负数
|
|
|
|
|
label: isMajor ? formatLabelTime(relativeTime) : null,
|
2025-09-29 17:40:12 +08:00
|
|
|
isMajor,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
ticks,
|
|
|
|
|
};
|
|
|
|
|
}
|