diff --git a/src/api/media/playback.ts b/src/api/media/playback.ts new file mode 100644 index 00000000..10b88c55 --- /dev/null +++ b/src/api/media/playback.ts @@ -0,0 +1,49 @@ +import server from '@/utils/request'; +import { LocalStore } from '@/utils/comm'; +import { BASE_API_PATH, TOKEN_KEY } from '@/utils/variable'; +import { recordsItemType } from '@/views/media/Device/Playback/typings'; + +export default { + // 开始直播 + ptzStart: (deviceId: string, channelId: string, type: string) => + `${BASE_API_PATH}/media/device/${deviceId}/${channelId}/live.${type}?:X_Access_Token=${LocalStore.get(TOKEN_KEY)}`, + + // 查询设备通道详情 + queryDetail: (deviceId: string, data: any) => server.post(`/media/device/${deviceId}/channel/_query`, data), + + // 查询本地回放记录 + queryRecordLocal: (deviceId: string, channelId: string, data?: any) => + server.post(`/media/device/${deviceId}/${channelId}/records/in-local`, data), + + // 下载到云端 + downloadRecord: (deviceId: string, channelId: string, data: any) => + server.post(`/media/device/${deviceId}/${channelId}/_record`, data), + + // 播放本地回放 + playbackLocal: ( + deviceId: string, + channelId: string, + suffix: string, + startTime: string, + endTime: string, + speed: number = 1 + ) => + `${BASE_API_PATH}/media/device/${deviceId}/${channelId}/playback.${suffix}?:X_Access_Token=${LocalStore.get(TOKEN_KEY)}&startTime=${startTime}&endTime=${endTime}&speed=${speed}`, + + // 本地录像播放控制 + playbackControl: (deviceId: string, channelId: string) => + server.post(`/media/device/${deviceId}/${channelId}/stream-control`), + + // 查询云端回放记录 + recordsInServer: (deviceId: string, channelId: string, data: any) => + server.post(`/media/device/${deviceId}/${channelId}/records/in-server`, data), + + // 查询云端回放文件信息 + recordsInServerFiles: (deviceId: string, channelId: string, data: any) => + server.post(`/media/device/${deviceId}/${channelId}/records/in-server/files`, data), + + // 播放云端回放 + playbackStart: (recordId: string) => `${BASE_API_PATH}/record/${recordId}.mp4?:X_Access_Token=${LocalStore.get(TOKEN_KEY)}`, + + downLoadFile: (recordId: string) => `${BASE_API_PATH}/record/${recordId}.mp4?download=true&:X_Access_Token=${LocalStore.get(TOKEN_KEY)}` +} \ No newline at end of file diff --git a/src/components/AIcon/index.tsx b/src/components/AIcon/index.tsx index dd5e389f..7ff28560 100644 --- a/src/components/AIcon/index.tsx +++ b/src/components/AIcon/index.tsx @@ -73,7 +73,9 @@ const iconKeys = [ 'BellOutlined', 'UserOutlined', 'LogoutOutlined', - 'ReadIconOutlined' + 'ReadIconOutlined', + 'CloudDownloadOutlined', + 'PauseCircleOutlined', ] const Icon = (props: {type: string}) => { diff --git a/src/views/media/Device/Playback/iconNode.vue b/src/views/media/Device/Playback/iconNode.vue new file mode 100644 index 00000000..501c7861 --- /dev/null +++ b/src/views/media/Device/Playback/iconNode.vue @@ -0,0 +1,76 @@ + + + + + + diff --git a/src/views/media/Device/Playback/index.less b/src/views/media/Device/Playback/index.less new file mode 100644 index 00000000..dfa44d81 --- /dev/null +++ b/src/views/media/Device/Playback/index.less @@ -0,0 +1,120 @@ +@borderColor: #d9d9d9; + +.playback-warp { + display: flex; + padding: 24px; + background-color: #fff; + + .playback-left { + display: flex; + flex-direction: column; + flex-grow: 1; + width: 0; + + .playback-media { + width: 100%; + } + } + + .playback-right { + width: 300px; + margin-left: 24px; + + .playback-calendar { + margin-top: 16px; + border: 1px solid @borderColor; + border-radius: 2px; + + .ant-picker-calendar-header { + justify-content: space-between; + + > div:nth-child(3) { + display: none; + } + } + } + + .playback-list { + display: flex; + height: 300px; + margin-top: 16px; + overflow-y: auto; + border: 1px solid @borderColor; + + &.no-list { + align-items: center; + justify-content: center; + } + + .playback-list-items { + width: 100%; + + .ant-list-item { + padding-left: 12px; + } + } + } + } + + .time-line-warp { + padding: 10px 0; + + .time-line-clock { + display: flex; + align-items: stretch; + justify-content: space-between; + width: 100%; + + > div { + color: #666; + font-size: 12px; + } + } + + .time-line-content { + position: relative; + padding-bottom: 20px; + + .time-line-progress { + position: relative; + height: 16px; + overflow: hidden; + background-color: #d9d9d9; + border-radius: 2px; + + > div { + position: absolute; + top: 0; + left: 0; + height: 100%; + background-color: #52c41a; + cursor: pointer; + } + } + .time-line-btn { + position: absolute; + top: -2px; + left: 0; + width: 3px; + height: 19px; + background-color: @primary-color; + border-radius: 2px; + visibility: hidden; + } + + .time-line { + position: absolute; + bottom: -8px; + left: -30px; + width: 60px; + padding: 2px 0; + font-size: 12px; + text-align: center; + background-color: #d9d9d9; + border-radius: 2px; + box-shadow: 0 0 12px rgba(#000, 0.15); + visibility: hidden; + } + } + } +} diff --git a/src/views/media/Device/Playback/index.vue b/src/views/media/Device/Playback/index.vue index e0d2ef94..321a7127 100644 --- a/src/views/media/Device/Playback/index.vue +++ b/src/views/media/Device/Playback/index.vue @@ -1,7 +1,203 @@ + - + + + diff --git a/src/views/media/Device/Playback/timeLine.vue b/src/views/media/Device/Playback/timeLine.vue new file mode 100644 index 00000000..e77c014d --- /dev/null +++ b/src/views/media/Device/Playback/timeLine.vue @@ -0,0 +1,262 @@ + + + + + +