|
|
|
@ -1,12 +1,260 @@
|
|
|
|
|
<template>
|
|
|
|
|
<div class="historyVideoModal-wrap">
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<el-dialog class="historyVideoModal-wrap" v-model="show" @close="handleClose">
|
|
|
|
|
<!-- 自定义标题栏 -->
|
|
|
|
|
<template #header="{ close, titleId, titleClass }">
|
|
|
|
|
<div class="flex items-center justify-between video-dialog-header">
|
|
|
|
|
<div class="flex items-center justify-center header-left">
|
|
|
|
|
<div class="header-icon mr-[12px]"></div>
|
|
|
|
|
<p class="overflow-hidden whitespace-nowrap text-ellipsis max-w-[650px]">{{
|
|
|
|
|
info.device_name }}</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
<div class="flex main-content">
|
|
|
|
|
<!-- 播放器 -->
|
|
|
|
|
<Player :src="currentVideo.video_url" :is-playing="isPlaying" @update:progress="handleProgress"
|
|
|
|
|
@update:duration="handleDuration" @play="isPlaying = true" @pause="isPlaying = false" />
|
|
|
|
|
<div class="flex video-record-list">
|
|
|
|
|
<!-- 日期筛选 -->
|
|
|
|
|
<div class="flex pl-[16px] pr-[24px] items-center">
|
|
|
|
|
<span>时间:</span>
|
|
|
|
|
<el-select v-model="selectedDate" placeholder="请选择" class="custom-select record_date_select"
|
|
|
|
|
clearable @change="handleDateChange" @clear="handleClear">
|
|
|
|
|
<el-option v-for="(item, index) in dateList" :key="item" :label="item"
|
|
|
|
|
:value="item"></el-option>
|
|
|
|
|
</el-select>
|
|
|
|
|
<!-- <el-date-picker v-model="selectedDate" type="date" placeholder="选择日期"
|
|
|
|
|
@change="handleDateChange"></el-date-picker> -->
|
|
|
|
|
</div>
|
|
|
|
|
<!-- 记录列表 -->
|
|
|
|
|
<el-scrollbar style="height: calc(100% - 80px)">
|
|
|
|
|
<ul class="record-list-box">
|
|
|
|
|
<li v-for="(item, index) in recordList" :key="item.id"
|
|
|
|
|
:class="{ active: currentVideo?.id === item.id }" @click="handleItemClick(item)"
|
|
|
|
|
class="flex items-center justify-between">
|
|
|
|
|
<span class="time">{{ item.created_at }}</span>
|
|
|
|
|
<div :class="{ 'play-btn': true, 'playing': isPlaying && currentVideo?.id === item.id }">
|
|
|
|
|
</div>
|
|
|
|
|
</li>
|
|
|
|
|
</ul>
|
|
|
|
|
</el-scrollbar>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</el-dialog>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script lang="ts" setup>
|
|
|
|
|
import Player from '@/components/videoPlayer/Player.vue'
|
|
|
|
|
import { ElMessage } from 'element-plus';
|
|
|
|
|
import { extractUniqueDatesWithMoment, filterDataByDate } from '@/utils/array';
|
|
|
|
|
interface Props {
|
|
|
|
|
/** 弹窗显隐 */
|
|
|
|
|
value: boolean;
|
|
|
|
|
info: Record<string, any>;
|
|
|
|
|
historyVideos: Record<string, any>[];
|
|
|
|
|
}
|
|
|
|
|
interface Emits {
|
|
|
|
|
(e: "update:value", val: boolean): void;
|
|
|
|
|
}
|
|
|
|
|
const props = withDefaults(defineProps<Props>(), {
|
|
|
|
|
value: false,
|
|
|
|
|
info: {},
|
|
|
|
|
historyVideos: []
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const emit = defineEmits<Emits>();
|
|
|
|
|
|
|
|
|
|
// 组件状态
|
|
|
|
|
const dateList = ref<string[]>([]);
|
|
|
|
|
const selectedDate = ref(); // 默认今天
|
|
|
|
|
const recordList = ref([]);
|
|
|
|
|
const currentVideo = ref<Record<string, any>>({})
|
|
|
|
|
const isPlaying = ref(false);
|
|
|
|
|
|
|
|
|
|
const togglePlay = () => {
|
|
|
|
|
isPlaying.value = !isPlaying.value;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// TODO 监听进度更新 暂未使用
|
|
|
|
|
const handleProgress = (data: { currentTime: number, duration: number }) => {
|
|
|
|
|
console.log((data.currentTime / data.duration) * 100, "handleProgress")
|
|
|
|
|
const progressVal = (data.currentTime / data.duration) * 100
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO 处理时长更新 暂未使用
|
|
|
|
|
const handleDuration = (newDuration: number) => {
|
|
|
|
|
// duration.value = newDuration
|
|
|
|
|
}
|
|
|
|
|
// 加载数据
|
|
|
|
|
const loadData = () => {
|
|
|
|
|
recordList.value = props.historyVideos
|
|
|
|
|
dateList.value = extractUniqueDatesWithMoment(recordList.value);
|
|
|
|
|
currentVideo.value = props.historyVideos[0]; // 切换日期时重置选中
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 日期选择变化
|
|
|
|
|
const handleDateChange = (date) => {
|
|
|
|
|
console.log(date, "handleDateChange_date");
|
|
|
|
|
if (date) {
|
|
|
|
|
selectedDate.value = date;
|
|
|
|
|
recordList.value = filterDataByDate(toRaw(props.historyVideos), date);
|
|
|
|
|
currentVideo.value = recordList.value[0]; // 切换日期时重置选中
|
|
|
|
|
} else {
|
|
|
|
|
loadData()
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
// 点击列表项
|
|
|
|
|
const handleItemClick = (item) => {
|
|
|
|
|
if (currentVideo.value?.id === item.id) {
|
|
|
|
|
togglePlay() // 播放 暂停
|
|
|
|
|
} else {
|
|
|
|
|
currentVideo.value = item;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 视频播放结束
|
|
|
|
|
const handleVideoEnd = () => {
|
|
|
|
|
// currentIndex.value = -1;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 时间格式化
|
|
|
|
|
const formatTime = (timeStr) => {
|
|
|
|
|
return timeStr.split(' ')[1].substring(0, 5); // 只显示时分
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 处理对话框关闭事件
|
|
|
|
|
const handleClose = () => {
|
|
|
|
|
emits('close');
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const show = computed({
|
|
|
|
|
get() {
|
|
|
|
|
return props.value;
|
|
|
|
|
},
|
|
|
|
|
set(val: boolean) {
|
|
|
|
|
emit("update:value", val);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
// TODO 后续再做自动播放
|
|
|
|
|
defineExpose({ loadData })
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style lang="scss">
|
|
|
|
|
.historyVideoModal-wrap.el-dialog {
|
|
|
|
|
border: none;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
box-shadow: none;
|
|
|
|
|
background-color: transparent;
|
|
|
|
|
background-image: url("@/assets/common/bg_player_dialog.png");
|
|
|
|
|
background-size: contain;
|
|
|
|
|
background-position: center;
|
|
|
|
|
background-repeat: no-repeat;
|
|
|
|
|
width: 1100px;
|
|
|
|
|
height: 612px;
|
|
|
|
|
padding: 0;
|
|
|
|
|
margin-top: calc(50vh - 316px);
|
|
|
|
|
|
|
|
|
|
.el-dialog__header.show-close {
|
|
|
|
|
padding: 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.el-dialog__close {
|
|
|
|
|
width: 56px;
|
|
|
|
|
height: 56px;
|
|
|
|
|
color: white;
|
|
|
|
|
font-size: 18px;
|
|
|
|
|
padding-top: 4px;
|
|
|
|
|
padding-right: 20px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.video-dialog-header {
|
|
|
|
|
color: white;
|
|
|
|
|
padding: 0;
|
|
|
|
|
padding-top: 4px;
|
|
|
|
|
|
|
|
|
|
.header-left {
|
|
|
|
|
padding: 0 18px;
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
font-size: 18px;
|
|
|
|
|
|
|
|
|
|
.header-icon {
|
|
|
|
|
margin-top: 8px;
|
|
|
|
|
width: 48px;
|
|
|
|
|
height: 48px;
|
|
|
|
|
background-image: url("@/assets/common/dialog_title_icon.png");
|
|
|
|
|
background-size: contain;
|
|
|
|
|
background-position: center;
|
|
|
|
|
background-repeat: no-repeat;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.main-content {
|
|
|
|
|
padding-left: 24px;
|
|
|
|
|
padding-top: 24px;
|
|
|
|
|
|
|
|
|
|
// background: red;
|
|
|
|
|
.video-player-box {
|
|
|
|
|
border-radius: 0px 0px 4px 4px;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
width: 752px;
|
|
|
|
|
height: 502px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.video-record-list {
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
flex: 1;
|
|
|
|
|
color: white;
|
|
|
|
|
|
|
|
|
|
.record_date_select {
|
|
|
|
|
width: 100%;
|
|
|
|
|
display: flex;
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
|
|
|
|
.el-select__wrapper {
|
|
|
|
|
width: 100%;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
.record-list-box {
|
|
|
|
|
margin-top: 5px;
|
|
|
|
|
|
|
|
|
|
li {
|
|
|
|
|
color: white;
|
|
|
|
|
height: 32px;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
padding-left: 16px;
|
|
|
|
|
padding-right: 24px;
|
|
|
|
|
|
|
|
|
|
&.active,
|
|
|
|
|
&:hover {
|
|
|
|
|
background: linear-gradient(90deg, rgba(30, 54, 88, 0) 0%, #0C4FAD 53%, rgba(65, 117, 190, 0) 100%);
|
|
|
|
|
color: #37DBFF;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.time {
|
|
|
|
|
flex: 1;
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.play-btn {
|
|
|
|
|
width: 18px;
|
|
|
|
|
height: 18px;
|
|
|
|
|
background: url("@/assets/common/player_icon.png") no-repeat center center;
|
|
|
|
|
background-size: contain;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.playing {
|
|
|
|
|
background: url("@/assets/common/pause_icon.png") no-repeat center center;
|
|
|
|
|
background-size: contain;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</style>
|