parent
1559524338
commit
14bc8ffbf7
|
|
@ -1,9 +1,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { CaretRight, Location } from '@element-plus/icons-vue'
|
import { CaretRight, Location } from '@element-plus/icons-vue'
|
||||||
/**
|
import { ref, shallowRef, watch } from 'vue'
|
||||||
* 项目列表展示组件
|
|
||||||
* 接收两个参数:title(字符串)和data(字符串数组)
|
|
||||||
*/
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
title: {
|
title: {
|
||||||
type: String,
|
type: String,
|
||||||
|
|
@ -13,6 +11,10 @@ const props = defineProps({
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => [],
|
default: () => [],
|
||||||
},
|
},
|
||||||
|
currentTime: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['click', 'play'])
|
const emit = defineEmits(['click', 'play'])
|
||||||
|
|
@ -25,6 +27,49 @@ function handlePlayClick(e: Event, item: any[], index: number) {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
emit('play', item, index)
|
emit('play', item, index)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const dataCache = shallowRef<[number, string, string, string][]>([])
|
||||||
|
const indexMap = ref(new Map<number, number[]>())
|
||||||
|
const sortedTimes = ref<number[]>([])
|
||||||
|
|
||||||
|
watch(() => props.data, (newData) => {
|
||||||
|
const arr = newData as [number, string, string, string][]
|
||||||
|
dataCache.value = arr
|
||||||
|
const map = new Map<number, number[]>()
|
||||||
|
const times: number[] = []
|
||||||
|
for (let i = 0; i < arr.length; i++) {
|
||||||
|
const t = (arr[i][0] * 10) | 0
|
||||||
|
if (!map.has(t)) {
|
||||||
|
map.set(t, [])
|
||||||
|
times.push(t)
|
||||||
|
}
|
||||||
|
map.get(t)!.push(i)
|
||||||
|
}
|
||||||
|
times.sort((a, b) => a - b)
|
||||||
|
indexMap.value = map
|
||||||
|
sortedTimes.value = times
|
||||||
|
}, { immediate: true })
|
||||||
|
|
||||||
|
const currentHighlight = ref(-1)
|
||||||
|
|
||||||
|
watch(() => props.currentTime, (t) => {
|
||||||
|
const time = (t * 10) | 0
|
||||||
|
const indices = indexMap.value.get(time)
|
||||||
|
if (indices && indices.length > 0) {
|
||||||
|
currentHighlight.value = indices[0]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const times = sortedTimes.value
|
||||||
|
let prev = times[times.length - 1] || 0
|
||||||
|
for (let i = 0; i < times.length; i++) {
|
||||||
|
if (times[i] > time) {
|
||||||
|
prev = times[i - 1] ?? prev
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const prevIndices = indexMap.value.get(prev)
|
||||||
|
currentHighlight.value = prevIndices?.[0] ?? 0
|
||||||
|
}, { immediate: true })
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -40,7 +85,7 @@ function handlePlayClick(e: Event, item: any[], index: number) {
|
||||||
<!-- 滚动列表区域 -->
|
<!-- 滚动列表区域 -->
|
||||||
<el-row style="flex: 1; overflow-y: auto;">
|
<el-row style="flex: 1; overflow-y: auto;">
|
||||||
<el-col>
|
<el-col>
|
||||||
<el-row v-for="(item, index) in props.data" :key="index" class="message-item">
|
<el-row v-for="(item, index) in props.data" :key="index" class="message-item" :class="{ highlighted: currentHighlight === index }">
|
||||||
<div class="message-content" @click="handleItemClick(item as any[], index)">
|
<div class="message-content" @click="handleItemClick(item as any[], index)">
|
||||||
<div class="flex flex-col items-start">
|
<div class="flex flex-col items-start">
|
||||||
<div class="flex flex-row gap-2">
|
<div class="flex flex-row gap-2">
|
||||||
|
|
@ -97,6 +142,14 @@ function handlePlayClick(e: Event, item: any[], index: number) {
|
||||||
padding: 4px 0.75rem;
|
padding: 4px 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.message-item:hover {
|
||||||
|
background-color: var(--ep-bg-color-page);
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-item.highlighted {
|
||||||
|
background-color: var(--ep-color-primary-light-8) !important;
|
||||||
|
}
|
||||||
|
|
||||||
.message-content {
|
.message-content {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,10 @@ const data = ref<DataFormat>({
|
||||||
|
|
||||||
const selectedHazard = ref(-1)
|
const selectedHazard = ref(-1)
|
||||||
const currentFrame = ref(0)
|
const currentFrame = ref(0)
|
||||||
|
|
||||||
|
const videoCurrentTime = computed(() => {
|
||||||
|
return currentFrame.value / 30
|
||||||
|
})
|
||||||
const videoDuration = ref(0)
|
const videoDuration = ref(0)
|
||||||
const FPS = 30
|
const FPS = 30
|
||||||
const totalFrames = computed(() => {
|
const totalFrames = computed(() => {
|
||||||
|
|
@ -143,7 +147,8 @@ function updateCurrentFrame() {
|
||||||
const videoEl = videoRef.value
|
const videoEl = videoRef.value
|
||||||
if (!videoEl)
|
if (!videoEl)
|
||||||
return
|
return
|
||||||
currentFrame.value = Math.floor(videoEl.currentTime * 30)
|
const newFrame = Math.floor(videoEl.currentTime * 30)
|
||||||
|
currentFrame.value = newFrame
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleVideoLoadedMetadata() {
|
function handleVideoLoadedMetadata() {
|
||||||
|
|
@ -229,6 +234,7 @@ function handleJumpToTimePoint(seconds: number) {
|
||||||
|
|
||||||
// 直接设置 currentTime 实现跳转
|
// 直接设置 currentTime 实现跳转
|
||||||
videoEl.currentTime = seconds
|
videoEl.currentTime = seconds
|
||||||
|
currentFrame.value = Math.floor(seconds * 30)
|
||||||
|
|
||||||
// 跳转后自动暂停
|
// 跳转后自动暂停
|
||||||
videoEl.pause()
|
videoEl.pause()
|
||||||
|
|
@ -244,6 +250,7 @@ function handlePlayAndSeek(item: any[]) {
|
||||||
return
|
return
|
||||||
|
|
||||||
videoEl.currentTime = seconds
|
videoEl.currentTime = seconds
|
||||||
|
currentFrame.value = Math.floor(seconds * 30)
|
||||||
videoEl.play()
|
videoEl.play()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -461,6 +468,7 @@ onMounted(() => {
|
||||||
<SubtitleList
|
<SubtitleList
|
||||||
title="对话"
|
title="对话"
|
||||||
:data="data.对话列表"
|
:data="data.对话列表"
|
||||||
|
:current-time="videoCurrentTime"
|
||||||
@click="(item: any[]) => handleJumpToTimePoint(Number(item[0]))"
|
@click="(item: any[]) => handleJumpToTimePoint(Number(item[0]))"
|
||||||
@play="(item: any[]) => handlePlayAndSeek(item)"
|
@play="(item: any[]) => handlePlayAndSeek(item)"
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue