Commit 520ac95c37af5977eb1514747e7fc10a1862562a
Committed by
xp.Huang
1 parent
59683e06
feat: gbt28181(支持点播、云台控制)
Showing
11 changed files
with
317 additions
and
331 deletions
| @@ -19,6 +19,7 @@ enum CameraManagerApi { | @@ -19,6 +19,7 @@ enum CameraManagerApi { | ||
| 19 | STREAMING_POST_URL = '/video/platform', | 19 | STREAMING_POST_URL = '/video/platform', |
| 20 | STREAMING_DELETE_URL = '/video/platform', | 20 | STREAMING_DELETE_URL = '/video/platform', |
| 21 | STREAMING_PLAY_GET_URL = '/video/url', | 21 | STREAMING_PLAY_GET_URL = '/video/url', |
| 22 | + VIDEO_CONTROL_STOP = '/video/control/stop/', | ||
| 22 | } | 23 | } |
| 23 | 24 | ||
| 24 | export const cameraPage = (params: CameraQueryParam) => { | 25 | export const cameraPage = (params: CameraQueryParam) => { |
| @@ -127,3 +128,10 @@ export const controlling = (params: any) => { | @@ -127,3 +128,10 @@ export const controlling = (params: any) => { | ||
| 127 | params, | 128 | params, |
| 128 | }); | 129 | }); |
| 129 | }; | 130 | }; |
| 131 | + | ||
| 132 | +//云台控制 停止点播 | ||
| 133 | +export const stopOnDemandVideoApiGet = (deviceId: string, channelId: string) => { | ||
| 134 | + return defHttp.get({ | ||
| 135 | + url: `${CameraManagerApi.VIDEO_CONTROL_STOP}${deviceId}/${channelId}`, | ||
| 136 | + }); | ||
| 137 | +}; |
src/api/device/model/videoChannelModel.ts
0 → 100644
| 1 | +export interface VideoChannelQueryParamsType { | ||
| 2 | + page: number; | ||
| 3 | + pageSize: number; | ||
| 4 | + tbDeviceId?: string; | ||
| 5 | + name?: string; | ||
| 6 | + cameraCode?: string; | ||
| 7 | +} | ||
| 8 | + | ||
| 9 | +export interface VideoChannelItemType { | ||
| 10 | + id: string; | ||
| 11 | + createTime: string; | ||
| 12 | + updateTime: string; | ||
| 13 | + name: string; | ||
| 14 | + enabled: boolean; | ||
| 15 | + tenantId: string; | ||
| 16 | + channelId: string; | ||
| 17 | + cameraCode: string; | ||
| 18 | + deviceId: string; | ||
| 19 | + manufacturer: string; | ||
| 20 | + model: string; | ||
| 21 | + owner: string; | ||
| 22 | + civilCode: string; | ||
| 23 | + address: string; | ||
| 24 | + parental: number; | ||
| 25 | + safetyWay: number; | ||
| 26 | + registerWay: number; | ||
| 27 | + certifiable: number; | ||
| 28 | + errorCode: number; | ||
| 29 | + secrecy: number; | ||
| 30 | + status: string; | ||
| 31 | + longitude: number; | ||
| 32 | + latitude: number; | ||
| 33 | + longitudeGcj02: number; | ||
| 34 | + latitudeGcj02: number; | ||
| 35 | + longitudeWgs84: number; | ||
| 36 | + latitudeWgs84: number; | ||
| 37 | + subCount: number; | ||
| 38 | + hasAudio: boolean; | ||
| 39 | + channelType: number; | ||
| 40 | + ptztype: number; | ||
| 41 | + ifShowGBT?: boolean; | ||
| 42 | +} | ||
| 43 | + | ||
| 44 | +export interface VideoChannelPlayAddressType { | ||
| 45 | + code: number; | ||
| 46 | + message: string; | ||
| 47 | + data: Data; | ||
| 48 | +} | ||
| 49 | + | ||
| 50 | +export interface Data { | ||
| 51 | + app: string; | ||
| 52 | + stream: string; | ||
| 53 | + ip: any; | ||
| 54 | + flv: string; | ||
| 55 | + https_flv: string; | ||
| 56 | + ws_flv: string; | ||
| 57 | + wss_flv: string; | ||
| 58 | + fmp4: string; | ||
| 59 | + https_fmp4: string; | ||
| 60 | + ws_fmp4: string; | ||
| 61 | + wss_fmp4: string; | ||
| 62 | + hls: string; | ||
| 63 | + https_hls: string; | ||
| 64 | + ws_hls: string; | ||
| 65 | + wss_hls: string; | ||
| 66 | + ts: string; | ||
| 67 | + https_ts: string; | ||
| 68 | + ws_ts: string; | ||
| 69 | + wss_ts: any; | ||
| 70 | + rtmp: string; | ||
| 71 | + rtmps: string; | ||
| 72 | + rtsp: string; | ||
| 73 | + rtsps: string; | ||
| 74 | + rtc: string; | ||
| 75 | + rtcs: string; | ||
| 76 | + mediaServerId: string; | ||
| 77 | + tracks: Track[]; | ||
| 78 | + startTime: any; | ||
| 79 | + endTime: any; | ||
| 80 | + progress: number; | ||
| 81 | +} | ||
| 82 | + | ||
| 83 | +export interface Track { | ||
| 84 | + channels: number; | ||
| 85 | + codecId: number; | ||
| 86 | + codecIdName: any; | ||
| 87 | + codecType: number; | ||
| 88 | + ready: boolean; | ||
| 89 | + sampleBit: number; | ||
| 90 | + sampleRate: number; | ||
| 91 | + fps: number; | ||
| 92 | + height: number; | ||
| 93 | + width: number; | ||
| 94 | +} | ||
| 95 | + | ||
| 96 | +export interface VideoChanneControlType { | ||
| 97 | + command?: string | number | object; | ||
| 98 | + horizonSpeed?: string | number | object; | ||
| 99 | + verticalSpeed?: string | number | object; | ||
| 100 | + zoomSpeed?: string | number | object; | ||
| 101 | + tbDeviceId?: string | number | object; | ||
| 102 | + channelId?: string | number | object; | ||
| 103 | +} |
src/api/device/videoChannel.ts
0 → 100644
| 1 | +import { | ||
| 2 | + VideoChannelItemType, | ||
| 3 | + VideoChannelPlayAddressType, | ||
| 4 | + VideoChannelQueryParamsType, | ||
| 5 | + VideoChanneControlType, | ||
| 6 | +} from './model/videoChannelModel'; | ||
| 7 | +import { PaginationResult } from '/#/axios'; | ||
| 8 | +import { defHttp } from '/@/utils/http/axios'; | ||
| 9 | + | ||
| 10 | +enum Api { | ||
| 11 | + GET_VIDEO_CHANNEL_LIST = '/video/channel', | ||
| 12 | + GET_VIDEO_CONTROL_START = '/video/control/start', | ||
| 13 | + GET_VIDEO_CONTROL_STOP = '/video/control/stop', | ||
| 14 | + SET_VIDEO_CONTROL_CONTROL = '/video/control/control', | ||
| 15 | +} | ||
| 16 | + | ||
| 17 | +export const getVideoChannelList = (params: VideoChannelQueryParamsType) => { | ||
| 18 | + return defHttp.get<PaginationResult<VideoChannelItemType>>({ | ||
| 19 | + url: Api.GET_VIDEO_CHANNEL_LIST, | ||
| 20 | + params, | ||
| 21 | + }); | ||
| 22 | +}; | ||
| 23 | + | ||
| 24 | +export const getVideoControlStart = ({ | ||
| 25 | + deviceId, | ||
| 26 | + channelId, | ||
| 27 | +}: Record<'deviceId' | 'channelId', string>) => { | ||
| 28 | + return defHttp.get<VideoChannelPlayAddressType>( | ||
| 29 | + { | ||
| 30 | + url: `${Api.GET_VIDEO_CONTROL_START}/${deviceId}/${channelId}`, | ||
| 31 | + timeout: 30 * 1000, | ||
| 32 | + }, | ||
| 33 | + {} | ||
| 34 | + ); | ||
| 35 | +}; | ||
| 36 | + | ||
| 37 | +export const setVideoControl = (tbDeviceId, channelId, params: VideoChanneControlType) => { | ||
| 38 | + return defHttp.get<VideoChannelPlayAddressType>({ | ||
| 39 | + url: `${Api.SET_VIDEO_CONTROL_CONTROL}/${tbDeviceId}/${channelId}`, | ||
| 40 | + // timeout: 30 * 1000, | ||
| 41 | + params, | ||
| 42 | + }); | ||
| 43 | +}; |
| @@ -16,10 +16,10 @@ | @@ -16,10 +16,10 @@ | ||
| 16 | @open-gateway-device="handleOpenGatewayDevice" | 16 | @open-gateway-device="handleOpenGatewayDevice" |
| 17 | /> | 17 | /> |
| 18 | </Tabs.TabPane> | 18 | </Tabs.TabPane> |
| 19 | - <Tabs.TabPane key="modelOfMatter" tab="物模型数据"> | 19 | + <Tabs.TabPane v-if="!isGBTTransportType" key="modelOfMatter" tab="物模型数据"> |
| 20 | <ModelOfMatter :deviceDetail="deviceDetail" /> | 20 | <ModelOfMatter :deviceDetail="deviceDetail" /> |
| 21 | </Tabs.TabPane> | 21 | </Tabs.TabPane> |
| 22 | - <Tabs.TabPane key="3"> | 22 | + <Tabs.TabPane v-if="!isGBTTransportType" key="3"> |
| 23 | <template #tab> | 23 | <template #tab> |
| 24 | <Badge :offset="[2, -5]" style="color: inherit"> | 24 | <Badge :offset="[2, -5]" style="color: inherit"> |
| 25 | <span>告警</span> | 25 | <span>告警</span> |
| @@ -35,29 +35,32 @@ | @@ -35,29 +35,32 @@ | ||
| 35 | </template> | 35 | </template> |
| 36 | <AlarmLog :device-id="deviceDetail.id" class="bg-gray-100" /> | 36 | <AlarmLog :device-id="deviceDetail.id" class="bg-gray-100" /> |
| 37 | </Tabs.TabPane> | 37 | </Tabs.TabPane> |
| 38 | - <Tabs.TabPane key="4" tab="子设备" v-if="deviceDetail?.deviceType === 'GATEWAY'"> | 38 | + <Tabs.TabPane key="4" tab="子设备" v-if="deviceDetail?.deviceType === DeviceTypeEnum.GATEWAY"> |
| 39 | <ChildDevice | 39 | <ChildDevice |
| 40 | :fromId="deviceDetail?.tbDeviceId" | 40 | :fromId="deviceDetail?.tbDeviceId" |
| 41 | @openTbDeviceDetail="handleOpenTbDeviceDetail" | 41 | @openTbDeviceDetail="handleOpenTbDeviceDetail" |
| 42 | /> | 42 | /> |
| 43 | </Tabs.TabPane> | 43 | </Tabs.TabPane> |
| 44 | - <Tabs.TabPane key="7" tab="命令下发记录"> | 44 | + <Tabs.TabPane v-if="!isGBTTransportType" key="7" tab="命令下发记录"> |
| 45 | <CommandRecord :deviceDetail="deviceDetail" :fromId="deviceDetail?.tbDeviceId" /> | 45 | <CommandRecord :deviceDetail="deviceDetail" :fromId="deviceDetail?.tbDeviceId" /> |
| 46 | </Tabs.TabPane> | 46 | </Tabs.TabPane> |
| 47 | <!-- 网关设备并且场家是TBox --> | 47 | <!-- 网关设备并且场家是TBox --> |
| 48 | <Tabs.TabPane | 48 | <Tabs.TabPane |
| 49 | key="6" | 49 | key="6" |
| 50 | tab="TBox" | 50 | tab="TBox" |
| 51 | - v-if="deviceDetail?.deviceType === 'GATEWAY' && deviceDetail?.brand == 'TBox'" | 51 | + v-if="deviceDetail?.deviceType === DeviceTypeEnum.GATEWAY && deviceDetail?.brand == 'TBox'" |
| 52 | > | 52 | > |
| 53 | <TBoxDetail :deviceDetail="deviceDetail" /> | 53 | <TBoxDetail :deviceDetail="deviceDetail" /> |
| 54 | </Tabs.TabPane> | 54 | </Tabs.TabPane> |
| 55 | - <Tabs.TabPane key="eventManage" tab="事件管理"> | 55 | + <Tabs.TabPane v-if="!isGBTTransportType" key="eventManage" tab="事件管理"> |
| 56 | <EventManage :tbDeviceId="deviceDetail.tbDeviceId" /> | 56 | <EventManage :tbDeviceId="deviceDetail.tbDeviceId" /> |
| 57 | </Tabs.TabPane> | 57 | </Tabs.TabPane> |
| 58 | - <Tabs.TabPane key="task" tab="任务"> | 58 | + <Tabs.TabPane v-if="!isGBTTransportType" key="task" tab="任务"> |
| 59 | <Task :tbDeviceId="deviceDetail.tbDeviceId" /> | 59 | <Task :tbDeviceId="deviceDetail.tbDeviceId" /> |
| 60 | </Tabs.TabPane> | 60 | </Tabs.TabPane> |
| 61 | + <Tabs.TabPane v-if="isGBTTransportType" key="videoChanel" tab="视频通道"> | ||
| 62 | + <VideoChannel :deviceDetail="deviceDetail" /> | ||
| 63 | + </Tabs.TabPane> | ||
| 61 | </Tabs> | 64 | </Tabs> |
| 62 | </BasicDrawer> | 65 | </BasicDrawer> |
| 63 | </template> | 66 | </template> |
| @@ -72,10 +75,12 @@ | @@ -72,10 +75,12 @@ | ||
| 72 | import { getDeviceDetail } from '/@/api/device/deviceManager'; | 75 | import { getDeviceDetail } from '/@/api/device/deviceManager'; |
| 73 | import ModelOfMatter from '../tabs/ModelOfMatter.vue'; | 76 | import ModelOfMatter from '../tabs/ModelOfMatter.vue'; |
| 74 | import EventManage from '../tabs/EventManage/index.vue'; | 77 | import EventManage from '../tabs/EventManage/index.vue'; |
| 75 | - import { DeviceRecord } from '/@/api/device/model/deviceModel'; | 78 | + import { DeviceRecord, DeviceTypeEnum } from '/@/api/device/model/deviceModel'; |
| 76 | import Task from '../tabs/Task.vue'; | 79 | import Task from '../tabs/Task.vue'; |
| 77 | import AlarmLog from '/@/views/alarm/log/index.vue'; | 80 | import AlarmLog from '/@/views/alarm/log/index.vue'; |
| 78 | import { Icon } from '/@/components/Icon'; | 81 | import { Icon } from '/@/components/Icon'; |
| 82 | + import VideoChannel from '../tabs/VideoChannel/index.vue'; | ||
| 83 | + import { TransportTypeEnum } from '../../../profiles/components/TransportDescript/const'; | ||
| 79 | 84 | ||
| 80 | const emit = defineEmits(['reload', 'register', 'openTbDeviceDetail', 'openGatewayDeviceDetail']); | 85 | const emit = defineEmits(['reload', 'register', 'openTbDeviceDetail', 'openGatewayDeviceDetail']); |
| 81 | 86 | ||
| @@ -84,12 +89,14 @@ | @@ -84,12 +89,14 @@ | ||
| 84 | const deviceDetailRef = ref(); | 89 | const deviceDetailRef = ref(); |
| 85 | const deviceDetail = ref<DeviceRecord>({} as unknown as DeviceRecord); | 90 | const deviceDetail = ref<DeviceRecord>({} as unknown as DeviceRecord); |
| 86 | 91 | ||
| 87 | - const isTransportType = ref<Boolean>(false); //获取产品是不是GB/T 28181 | 92 | + const isGBTTransportType = ref<boolean>(false); //获取产品是不是GB/T 28181 |
| 88 | // 详情回显 | 93 | // 详情回显 |
| 89 | const [register] = useDrawerInner(async (data) => { | 94 | const [register] = useDrawerInner(async (data) => { |
| 90 | const { id, transportType, deviceType } = data || {}; | 95 | const { id, transportType, deviceType } = data || {}; |
| 91 | - isTransportType.value = | ||
| 92 | - transportType == 'GB/T28181' && deviceType == 'DIRECT_CONNECTION' ? true : false; | 96 | + isGBTTransportType.value = !!( |
| 97 | + transportType == TransportTypeEnum.GBT28181 && deviceType == DeviceTypeEnum.DIRECT_CONNECTION | ||
| 98 | + ); | ||
| 99 | + | ||
| 93 | // 设备详情 | 100 | // 设备详情 |
| 94 | const res = await getDeviceDetail(id); | 101 | const res = await getDeviceDetail(id); |
| 95 | deviceDetail.value = res; | 102 | deviceDetail.value = res; |
| @@ -2,43 +2,46 @@ import { h } from 'vue'; | @@ -2,43 +2,46 @@ import { h } from 'vue'; | ||
| 2 | import { BasicColumn, FormSchema } from '/@/components/Table'; | 2 | import { BasicColumn, FormSchema } from '/@/components/Table'; |
| 3 | import { Tag } from 'ant-design-vue'; | 3 | import { Tag } from 'ant-design-vue'; |
| 4 | import { withInstall } from '/@/utils/index'; | 4 | import { withInstall } from '/@/utils/index'; |
| 5 | -import { DeviceTypeEnum } from '/@/api/device/model/deviceModel'; | ||
| 6 | 5 | ||
| 7 | import VideoPlay from './video.vue'; | 6 | import VideoPlay from './video.vue'; |
| 8 | export const Video = withInstall(VideoPlay); | 7 | export const Video = withInstall(VideoPlay); |
| 9 | 8 | ||
| 9 | +enum ChannelStatusEnum { | ||
| 10 | + ONLINE = 'ONLINE', | ||
| 11 | +} | ||
| 12 | + | ||
| 10 | export const configColumns: BasicColumn[] = [ | 13 | export const configColumns: BasicColumn[] = [ |
| 11 | { | 14 | { |
| 12 | title: '通道编号', | 15 | title: '通道编号', |
| 13 | - dataIndex: 'channellNumber', | ||
| 14 | - }, | ||
| 15 | - { | ||
| 16 | - title: '设备名称', | ||
| 17 | - dataIndex: 'deviceName', | 16 | + dataIndex: 'cameraCode', |
| 18 | }, | 17 | }, |
| 19 | { | 18 | { |
| 20 | title: '通道名称', | 19 | title: '通道名称', |
| 21 | - dataIndex: 'channelName', | 20 | + dataIndex: 'name', |
| 22 | }, | 21 | }, |
| 23 | { | 22 | { |
| 24 | - title: '厂家', | ||
| 25 | - dataIndex: 'manufacturer', | 23 | + title: '型号', |
| 24 | + dataIndex: 'model', | ||
| 26 | }, | 25 | }, |
| 27 | { | 26 | { |
| 28 | - title: '开启音频', | ||
| 29 | - dataIndex: 'turnOnAudio', | ||
| 30 | - slots: { customRender: 'turnOnAudio' }, | 27 | + title: '厂商', |
| 28 | + dataIndex: 'manufacturer', | ||
| 31 | }, | 29 | }, |
| 30 | + // { | ||
| 31 | + // title: '开启音频', | ||
| 32 | + // dataIndex: 'hasAudio', | ||
| 33 | + // slots: { customRender: 'hasAudio' }, | ||
| 34 | + // }, | ||
| 32 | { | 35 | { |
| 33 | title: '状态', | 36 | title: '状态', |
| 34 | - dataIndex: 'state', | ||
| 35 | - format: (text) => { | 37 | + dataIndex: 'status', |
| 38 | + customRender: ({ text }: { text: ChannelStatusEnum }) => { | ||
| 36 | return h( | 39 | return h( |
| 37 | Tag, | 40 | Tag, |
| 38 | { | 41 | { |
| 39 | - color: Number(text) === 1 ? 'green' : 'blue', | 42 | + color: text === ChannelStatusEnum.ONLINE ? 'green' : 'blue', |
| 40 | }, | 43 | }, |
| 41 | - () => (Number(text) === 1 ? '在线' : '离线') | 44 | + () => (text === ChannelStatusEnum.ONLINE ? '在线' : '离线') |
| 42 | ); | 45 | ); |
| 43 | }, | 46 | }, |
| 44 | }, | 47 | }, |
| @@ -52,46 +55,21 @@ export const configColumns: BasicColumn[] = [ | @@ -52,46 +55,21 @@ export const configColumns: BasicColumn[] = [ | ||
| 52 | export const searchFormSchema: FormSchema[] | any = [ | 55 | export const searchFormSchema: FormSchema[] | any = [ |
| 53 | { | 56 | { |
| 54 | field: 'name', | 57 | field: 'name', |
| 55 | - label: '设备名称', | 58 | + label: '通道名称', |
| 56 | component: 'Input', | 59 | component: 'Input', |
| 57 | colProps: { span: 6 }, | 60 | colProps: { span: 6 }, |
| 58 | componentProps: { | 61 | componentProps: { |
| 59 | maxLength: 255, | 62 | maxLength: 255, |
| 60 | - placeholder: '请输入设备名称', | 63 | + placeholder: '请输入通道名称', |
| 61 | }, | 64 | }, |
| 62 | }, | 65 | }, |
| 63 | { | 66 | { |
| 64 | - field: 'deviceType', | ||
| 65 | - label: '设备类型', | ||
| 66 | - component: 'Select', | ||
| 67 | - colProps: { span: 6 }, | ||
| 68 | - componentProps: { | ||
| 69 | - options: [ | ||
| 70 | - { label: '网关设备', value: DeviceTypeEnum.GATEWAY }, | ||
| 71 | - { label: '直连设备', value: DeviceTypeEnum.DIRECT_CONNECTION }, | ||
| 72 | - { label: '网关子设备', value: DeviceTypeEnum.SENSOR }, | ||
| 73 | - ], | ||
| 74 | - placeholder: '请选择设备类型', | ||
| 75 | - }, | ||
| 76 | - }, | ||
| 77 | - // { | ||
| 78 | - // field: 'channelName', | ||
| 79 | - // label: '通道名称', | ||
| 80 | - // component: 'Input', | ||
| 81 | - // colProps: { span: 6 }, | ||
| 82 | - // componentProps: { | ||
| 83 | - // maxLength: 255, | ||
| 84 | - // placeholder: '请输入通道名称', | ||
| 85 | - // }, | ||
| 86 | - // }, | ||
| 87 | - { | ||
| 88 | - field: 'manufacturer', | ||
| 89 | - label: '厂家', | ||
| 90 | - component: 'Select', | 67 | + field: 'cameraCode', |
| 68 | + label: '国标编号', | ||
| 69 | + component: 'Input', | ||
| 91 | colProps: { span: 6 }, | 70 | colProps: { span: 6 }, |
| 92 | componentProps: { | 71 | componentProps: { |
| 93 | - options: [{}], | ||
| 94 | - placeholder: '请选择厂家', | 72 | + placeholder: '请输入国标编号', |
| 95 | }, | 73 | }, |
| 96 | }, | 74 | }, |
| 97 | ]; | 75 | ]; |
| @@ -3,13 +3,13 @@ | @@ -3,13 +3,13 @@ | ||
| 3 | class="bg-neutral-100 dark:text-gray-300 dark:bg-dark-700 p-4" | 3 | class="bg-neutral-100 dark:text-gray-300 dark:bg-dark-700 p-4" |
| 4 | @register="registerTable" | 4 | @register="registerTable" |
| 5 | > | 5 | > |
| 6 | - <template #turnOnAudio="{ record }"> | 6 | + <template #hasAudio="{ record }"> |
| 7 | <Switch | 7 | <Switch |
| 8 | :checked="record.status === 1" | 8 | :checked="record.status === 1" |
| 9 | :loading="record.pendingStatus" | 9 | :loading="record.pendingStatus" |
| 10 | checkedChildren="开启" | 10 | checkedChildren="开启" |
| 11 | unCheckedChildren="关闭" | 11 | unCheckedChildren="关闭" |
| 12 | - @change="(checked:boolean)=>handleTurnVideo(checked,record)" | 12 | + @change="(checked: boolean) => handleTurnVideo(checked, record)" |
| 13 | /> | 13 | /> |
| 14 | </template> | 14 | </template> |
| 15 | <template #action="{ record }"> | 15 | <template #action="{ record }"> |
| @@ -22,7 +22,8 @@ | @@ -22,7 +22,8 @@ | ||
| 22 | onClick: handlePlay.bind(null, record), | 22 | onClick: handlePlay.bind(null, record), |
| 23 | }, | 23 | }, |
| 24 | ]" | 24 | ]" |
| 25 | - /></template> | 25 | + /> |
| 26 | + </template> | ||
| 26 | </BasicTable> | 27 | </BasicTable> |
| 27 | <VideoModal @register="registerModal" /> | 28 | <VideoModal @register="registerModal" /> |
| 28 | </template> | 29 | </template> |
| @@ -34,28 +35,22 @@ | @@ -34,28 +35,22 @@ | ||
| 34 | import { DeviceRecord } from '/@/api/device/model/deviceModel'; | 35 | import { DeviceRecord } from '/@/api/device/model/deviceModel'; |
| 35 | import VideoModal from './videoModal.vue'; | 36 | import VideoModal from './videoModal.vue'; |
| 36 | import { useModal } from '/@/components/Modal'; | 37 | import { useModal } from '/@/components/Modal'; |
| 37 | - import { onMounted } from 'vue'; | ||
| 38 | import { useMessage } from '/@/hooks/web/useMessage'; | 38 | import { useMessage } from '/@/hooks/web/useMessage'; |
| 39 | + import { getVideoChannelList } from '/@/api/device/videoChannel'; | ||
| 39 | 40 | ||
| 40 | - defineProps({ | ||
| 41 | - fromId: { | ||
| 42 | - type: String, | ||
| 43 | - default: '', | ||
| 44 | - }, | ||
| 45 | - deviceDetail: { | ||
| 46 | - type: Object as PropType<DeviceRecord>, | ||
| 47 | - required: true, | ||
| 48 | - }, | ||
| 49 | - }); | 41 | + const props = defineProps<{ deviceDetail: DeviceRecord }>(); |
| 50 | 42 | ||
| 51 | const [registerModal, { openModal }] = useModal(); | 43 | const [registerModal, { openModal }] = useModal(); |
| 52 | 44 | ||
| 53 | - const [registerTable, { setTableData, setProps, setSelectedRowKeys, reload }] = useTable({ | ||
| 54 | - // api: deviceCommandRecordGetQuery, | 45 | + const [registerTable, { setProps, setSelectedRowKeys, reload }] = useTable({ |
| 46 | + api: getVideoChannelList, | ||
| 55 | columns: configColumns, | 47 | columns: configColumns, |
| 56 | showTableSetting: true, | 48 | showTableSetting: true, |
| 57 | bordered: true, | 49 | bordered: true, |
| 58 | showIndexColumn: false, | 50 | showIndexColumn: false, |
| 51 | + beforeFetch: (params: Recordable) => { | ||
| 52 | + return { ...params, tbDeviceId: props.deviceDetail.tbDeviceId }; | ||
| 53 | + }, | ||
| 59 | formConfig: { | 54 | formConfig: { |
| 60 | labelWidth: 120, | 55 | labelWidth: 120, |
| 61 | schemas: searchFormSchema, | 56 | schemas: searchFormSchema, |
| @@ -81,196 +76,10 @@ | @@ -81,196 +76,10 @@ | ||
| 81 | } | 76 | } |
| 82 | }; | 77 | }; |
| 83 | 78 | ||
| 84 | - const tableList = [ | ||
| 85 | - { | ||
| 86 | - id: '8b66f4fa-88e0-42b2-be33-60652cd2bda1', | ||
| 87 | - creator: '694a8f7f-f7ed-4a9c-af89-a3d18fc3663e', | ||
| 88 | - createTime: '2023-03-10 17:16:54', | ||
| 89 | - updater: '694a8f7f-f7ed-4a9c-af89-a3d18fc3663e', | ||
| 90 | - updateTime: '2023-04-11 10:25:49', | ||
| 91 | - name: 'dasd', | ||
| 92 | - enabled: false, | ||
| 93 | - tenantId: '0277ca80-693d-11ed-9e12-e5edad4f7148', | ||
| 94 | - videoUrl: 'ws://192.168.10.134:28080/rtp/62020000492000000002_34020000001320000001.live.flv', | ||
| 95 | - sn: 's', | ||
| 96 | - organizationId: '27ef2a83-6f1f-4e33-824b-80afac684699', | ||
| 97 | - organizationName: '车车组织', | ||
| 98 | - status: false, | ||
| 99 | - accessMode: 0, | ||
| 100 | - playProtocol: 0, | ||
| 101 | - channellNumber: 1, | ||
| 102 | - }, | ||
| 103 | - { | ||
| 104 | - id: '9ff408ab-980f-470c-a55c-e4e284ddd34d', | ||
| 105 | - creator: '694a8f7f-f7ed-4a9c-af89-a3d18fc3663e', | ||
| 106 | - createTime: '2023-02-22 14:50:13', | ||
| 107 | - updater: '694a8f7f-f7ed-4a9c-af89-a3d18fc3663e', | ||
| 108 | - updateTime: '2023-04-11 10:36:25', | ||
| 109 | - name: '2', | ||
| 110 | - enabled: false, | ||
| 111 | - tenantId: '0277ca80-693d-11ed-9e12-e5edad4f7148', | ||
| 112 | - videoUrl: | ||
| 113 | - 'https://vcsplay.scjtonline.cn:8099/live/HD_d80a740b-2672-4ad1-90e4-52eb71d8c2ef.m3u8?auth_key=1681180571-0-0-dfdb334e5f83838ade5f01f61f910107', | ||
| 114 | - sn: '212', | ||
| 115 | - organizationId: '27ef2a83-6f1f-4e33-824b-80afac684699', | ||
| 116 | - organizationName: '车车组织', | ||
| 117 | - status: false, | ||
| 118 | - accessMode: 0, | ||
| 119 | - playProtocol: 0, | ||
| 120 | - channellNumber: 1, | ||
| 121 | - }, | ||
| 122 | - { | ||
| 123 | - id: 'a6edd8fb-a91a-4a1b-8124-65959206dac4', | ||
| 124 | - creator: '694a8f7f-f7ed-4a9c-af89-a3d18fc3663e', | ||
| 125 | - createTime: '2023-02-21 16:39:51', | ||
| 126 | - updater: '694a8f7f-f7ed-4a9c-af89-a3d18fc3663e', | ||
| 127 | - updateTime: '2023-04-11 10:33:27', | ||
| 128 | - name: 'dasda', | ||
| 129 | - enabled: false, | ||
| 130 | - tenantId: '0277ca80-693d-11ed-9e12-e5edad4f7148', | ||
| 131 | - videoUrl: | ||
| 132 | - 'https://vcsplay.scjtonline.cn:8200/live/HD_1b361aa9-5230-48ba-b8be-d1e2c4e9b178.m3u8?auth_key=1681180365-0-0-e77f40e88550091053139f5562d8afa2', | ||
| 133 | - brand: 'dasdad', | ||
| 134 | - sn: 'adsad', | ||
| 135 | - organizationId: '27ef2a83-6f1f-4e33-824b-80afac684699', | ||
| 136 | - organizationName: '车车组织', | ||
| 137 | - status: false, | ||
| 138 | - accessMode: 0, | ||
| 139 | - playProtocol: 0, | ||
| 140 | - channellNumber: 1, | ||
| 141 | - }, | ||
| 142 | - { | ||
| 143 | - id: '51b4c0bc-8050-4b37-bdb3-9fe08b14cf86', | ||
| 144 | - creator: '694a8f7f-f7ed-4a9c-af89-a3d18fc3663e', | ||
| 145 | - createTime: '2023-02-21 16:37:44', | ||
| 146 | - updater: '694a8f7f-f7ed-4a9c-af89-a3d18fc3663e', | ||
| 147 | - updateTime: '2023-04-11 10:56:59', | ||
| 148 | - name: '视频', | ||
| 149 | - enabled: false, | ||
| 150 | - tenantId: '0277ca80-693d-11ed-9e12-e5edad4f7148', | ||
| 151 | - videoUrl: | ||
| 152 | - 'https://vcsplay.scjtonline.cn:8093/live/HD_c54034ca-4a6d-11eb-8edc-3cd2e55e088c.m3u8?auth_key=1681181808-0-0-d756d9b0426b71482e45b9377958e4dc', | ||
| 153 | - brand: '视频厂家', | ||
| 154 | - sn: 'DART2143SAD12RE', | ||
| 155 | - organizationId: '27ef2a83-6f1f-4e33-824b-80afac684699', | ||
| 156 | - organizationName: '车车组织', | ||
| 157 | - status: false, | ||
| 158 | - accessMode: 0, | ||
| 159 | - playProtocol: 0, | ||
| 160 | - channellNumber: 1, | ||
| 161 | - }, | ||
| 162 | - { | ||
| 163 | - id: '8c0e6ed0-3176-4e76-bd8e-92f722f61e79', | ||
| 164 | - creator: '694a8f7f-f7ed-4a9c-af89-a3d18fc3663e', | ||
| 165 | - createTime: '2022-12-01 15:55:54', | ||
| 166 | - updater: '694a8f7f-f7ed-4a9c-af89-a3d18fc3663e', | ||
| 167 | - updateTime: '2023-04-11 10:59:22', | ||
| 168 | - name: '视频', | ||
| 169 | - enabled: false, | ||
| 170 | - tenantId: '0277ca80-693d-11ed-9e12-e5edad4f7148', | ||
| 171 | - avatar: 'https://demo.thingskit.com:9000/yunteng/itbbqOBXIUzWvjq.jpeg', | ||
| 172 | - videoUrl: 'http://113.204.115.250:83/openUrl/iFzoWME/live.m3u8', | ||
| 173 | - brand: '厂家', | ||
| 174 | - sn: 'JDKSA11321', | ||
| 175 | - organizationId: '9196fd9a-624a-4891-a8b3-ce588baedf9f', | ||
| 176 | - organizationName: '丰田', | ||
| 177 | - status: false, | ||
| 178 | - channellNumber: 1, | ||
| 179 | - accessMode: 0, | ||
| 180 | - playProtocol: 0, | ||
| 181 | - }, | ||
| 182 | - { | ||
| 183 | - id: 'c30422a7-9498-49a5-96d5-e77f3a2823e3', | ||
| 184 | - creator: '694a8f7f-f7ed-4a9c-af89-a3d18fc3663e', | ||
| 185 | - createTime: '2022-12-01 14:42:52', | ||
| 186 | - updater: '694a8f7f-f7ed-4a9c-af89-a3d18fc3663e', | ||
| 187 | - updateTime: '2023-03-02 17:12:53', | ||
| 188 | - name: '湖南卫视', | ||
| 189 | - enabled: false, | ||
| 190 | - tenantId: '0277ca80-693d-11ed-9e12-e5edad4f7148', | ||
| 191 | - videoUrl: | ||
| 192 | - 'http://219.151.31.38/liveplay-kk.rtxapp.com/live/program/live/hnwshd/4000000/mnf.m3u8', | ||
| 193 | - brand: 'BUZHIDAO', | ||
| 194 | - sn: 'QKDK123456', | ||
| 195 | - organizationId: '27ef2a83-6f1f-4e33-824b-80afac684699', | ||
| 196 | - organizationName: '车车组织', | ||
| 197 | - status: false, | ||
| 198 | - channellNumber: 1, | ||
| 199 | - accessMode: 0, | ||
| 200 | - playProtocol: 0, | ||
| 201 | - }, | ||
| 202 | - { | ||
| 203 | - id: 'e3253015-b8df-4e8f-ad0c-f634d3fd927e', | ||
| 204 | - creator: '694a8f7f-f7ed-4a9c-af89-a3d18fc3663e', | ||
| 205 | - createTime: '2022-11-29 11:19:00', | ||
| 206 | - name: '玩具视频播放', | ||
| 207 | - enabled: false, | ||
| 208 | - tenantId: '0277ca80-693d-11ed-9e12-e5edad4f7148', | ||
| 209 | - avatar: 'http://nc.tianzow.com:29000/yunteng/tgygMQmYaaPDPdG.jpg', | ||
| 210 | - videoUrl: 'https://ask.dcloud.net.cn/topic.m3u8', | ||
| 211 | - brand: '成都厂家', | ||
| 212 | - sn: 'TCL1528GOP', | ||
| 213 | - organizationId: '27ef2a83-6f1f-4e33-824b-80afac684699', | ||
| 214 | - organizationName: '车车组织', | ||
| 215 | - status: false, | ||
| 216 | - accessMode: 0, | ||
| 217 | - channellNumber: 1, | ||
| 218 | - playProtocol: 0, | ||
| 219 | - }, | ||
| 220 | - { | ||
| 221 | - id: '9edc9f73-3a9a-4e4b-9b4c-b955329b99b3', | ||
| 222 | - creator: '694a8f7f-f7ed-4a9c-af89-a3d18fc3663e', | ||
| 223 | - createTime: '2022-11-29 11:13:44', | ||
| 224 | - updater: '694a8f7f-f7ed-4a9c-af89-a3d18fc3663e', | ||
| 225 | - updateTime: '2023-01-11 10:03:18', | ||
| 226 | - name: '视频', | ||
| 227 | - enabled: false, | ||
| 228 | - tenantId: '0277ca80-693d-11ed-9e12-e5edad4f7148', | ||
| 229 | - sn: '7aeb4061f3cf4ba384ed8e1a3027d2a8', | ||
| 230 | - organizationId: '27ef2a83-6f1f-4e33-824b-80afac684699', | ||
| 231 | - organizationName: '车车组织', | ||
| 232 | - status: false, | ||
| 233 | - accessMode: 1, | ||
| 234 | - videoPlatformId: '8cc7c20e-693b-48ea-9124-994e0908c83e', | ||
| 235 | - streamType: 0, | ||
| 236 | - playProtocol: 0, | ||
| 237 | - channellNumber: 1, | ||
| 238 | - videoPlatformDTO: { | ||
| 239 | - enabled: false, | ||
| 240 | - host: '113.204.115.250:7120', | ||
| 241 | - appKey: '28238690', | ||
| 242 | - appSecret: 'F3e3Ffvo9Wyg9jkl8BUS', | ||
| 243 | - ssl: 1, | ||
| 244 | - }, | ||
| 245 | - }, | ||
| 246 | - { | ||
| 247 | - id: '9d6675ad-07ed-45ae-bb4a-457000e164f8', | ||
| 248 | - creator: '694a8f7f-f7ed-4a9c-af89-a3d18fc3663e', | ||
| 249 | - createTime: '2022-11-21 11:49:59', | ||
| 250 | - updater: '694a8f7f-f7ed-4a9c-af89-a3d18fc3663e', | ||
| 251 | - updateTime: '2023-04-11 10:53:27', | ||
| 252 | - name: '新视频', | ||
| 253 | - enabled: false, | ||
| 254 | - tenantId: '0277ca80-693d-11ed-9e12-e5edad4f7148', | ||
| 255 | - videoUrl: 'http://www.w3school.com.cn/example/html5/mov_bbb.mp4', | ||
| 256 | - brand: '1111', | ||
| 257 | - sn: 'XYZ', | ||
| 258 | - organizationId: '27ef2a83-6f1f-4e33-824b-80afac684699', | ||
| 259 | - organizationName: '车车组织', | ||
| 260 | - status: false, | ||
| 261 | - accessMode: 0, | ||
| 262 | - channellNumber: 1, | ||
| 263 | - playProtocol: 0, | ||
| 264 | - }, | ||
| 265 | - ]; | ||
| 266 | - | ||
| 267 | - onMounted(() => { | ||
| 268 | - setTableData(tableList); | ||
| 269 | - }); | ||
| 270 | - | ||
| 271 | const handlePlay = (record: Recordable) => { | 79 | const handlePlay = (record: Recordable) => { |
| 272 | openModal(true, { | 80 | openModal(true, { |
| 273 | record, | 81 | record, |
| 82 | + ifShowGBT: true, | ||
| 274 | }); | 83 | }); |
| 275 | }; | 84 | }; |
| 276 | </script> | 85 | </script> |
| @@ -20,13 +20,20 @@ | @@ -20,13 +20,20 @@ | ||
| 20 | } from '@ant-design/icons-vue'; | 20 | } from '@ant-design/icons-vue'; |
| 21 | import { Button } from 'ant-design-vue'; | 21 | import { Button } from 'ant-design-vue'; |
| 22 | import { nextTick } from 'vue'; | 22 | import { nextTick } from 'vue'; |
| 23 | - import { controlling } from '/@/api/camera/cameraManager'; | 23 | + import { controlling, stopOnDemandVideoApiGet } from '/@/api/camera/cameraManager'; |
| 24 | + import { setVideoControl } from '/@/api/device/videoChannel'; | ||
| 24 | 25 | ||
| 25 | const { prefixCls } = useDesign('basic-video-play'); | 26 | const { prefixCls } = useDesign('basic-video-play'); |
| 27 | + interface IGbtOption { | ||
| 28 | + tbDeviceId: string; | ||
| 29 | + channelId: string; | ||
| 30 | + } | ||
| 26 | 31 | ||
| 27 | const props = defineProps<{ | 32 | const props = defineProps<{ |
| 28 | options?: VideoJsPlayerOptions; | 33 | options?: VideoJsPlayerOptions; |
| 29 | withToken?: boolean; | 34 | withToken?: boolean; |
| 35 | + isGBT?: boolean; | ||
| 36 | + GBTOption: IGbtOption; | ||
| 30 | }>(); | 37 | }>(); |
| 31 | 38 | ||
| 32 | const emit = defineEmits<{ | 39 | const emit = defineEmits<{ |
| @@ -38,6 +45,11 @@ | @@ -38,6 +45,11 @@ | ||
| 38 | 45 | ||
| 39 | const videoPlayInstance = ref<Nullable<VideoJsPlayer>>(); | 46 | const videoPlayInstance = ref<Nullable<VideoJsPlayer>>(); |
| 40 | 47 | ||
| 48 | + const getGBT = computed(() => { | ||
| 49 | + const { isGBT } = props; | ||
| 50 | + return isGBT; | ||
| 51 | + }); | ||
| 52 | + | ||
| 41 | const getOptions = computed(() => { | 53 | const getOptions = computed(() => { |
| 42 | const { options, withToken } = props; | 54 | const { options, withToken } = props; |
| 43 | 55 | ||
| @@ -85,8 +97,9 @@ | @@ -85,8 +97,9 @@ | ||
| 85 | 97 | ||
| 86 | //播放/暂停 | 98 | //播放/暂停 |
| 87 | const handleClick = () => { | 99 | const handleClick = () => { |
| 88 | - unref(isPlay) && unref(videoPlayInstance)?.pause(); | ||
| 89 | - !unref(isPlay) && unref(videoPlayInstance)?.play(); | 100 | + // unref(isPlay) ((true,停止),(false,开启)) |
| 101 | + if (unref(isPlay)) unref(videoPlayInstance)?.pause(); | ||
| 102 | + else unref(videoPlayInstance)?.play(); | ||
| 90 | }; | 103 | }; |
| 91 | 104 | ||
| 92 | const getId = () => { | 105 | const getId = () => { |
| @@ -100,6 +113,17 @@ | @@ -100,6 +113,17 @@ | ||
| 100 | controlling({ cameraIndexCode: organizationId, action, command: direction }); | 113 | controlling({ cameraIndexCode: organizationId, action, command: direction }); |
| 101 | }; | 114 | }; |
| 102 | 115 | ||
| 116 | + // 国标控制 | ||
| 117 | + const handleGBTControl = (command: string, action?: number | string) => { | ||
| 118 | + const { tbDeviceId, channelId } = props.GBTOption; | ||
| 119 | + setVideoControl(tbDeviceId, channelId, { | ||
| 120 | + command, | ||
| 121 | + horizonSpeed: action, | ||
| 122 | + verticalSpeed: action, | ||
| 123 | + zoomSpeed: action, | ||
| 124 | + }); | ||
| 125 | + }; | ||
| 126 | + | ||
| 103 | const isPlay = ref<Boolean | null | undefined>(false); | 127 | const isPlay = ref<Boolean | null | undefined>(false); |
| 104 | 128 | ||
| 105 | onMounted(async () => { | 129 | onMounted(async () => { |
| @@ -126,10 +150,19 @@ | @@ -126,10 +150,19 @@ | ||
| 126 | 150 | ||
| 127 | //长按开始 | 151 | //长按开始 |
| 128 | const moveStart = (action) => { | 152 | const moveStart = (action) => { |
| 153 | + if (unref(getGBT)) { | ||
| 154 | + handleGBTControl(action, '30'); | ||
| 155 | + return; | ||
| 156 | + } | ||
| 129 | handleControl(0, action); | 157 | handleControl(0, action); |
| 130 | }; | 158 | }; |
| 159 | + | ||
| 131 | // 长按结束 | 160 | // 长按结束 |
| 132 | const moveStop = (action) => { | 161 | const moveStop = (action) => { |
| 162 | + if (unref(getGBT)) { | ||
| 163 | + handleGBTControl('STOP', '30'); | ||
| 164 | + return; | ||
| 165 | + } | ||
| 133 | handleControl(1, action); | 166 | handleControl(1, action); |
| 134 | }; | 167 | }; |
| 135 | 168 | ||
| @@ -137,8 +170,15 @@ | @@ -137,8 +170,15 @@ | ||
| 137 | unref(videoPlayInstance)?.dispose(); | 170 | unref(videoPlayInstance)?.dispose(); |
| 138 | videoPlayInstance.value = null; | 171 | videoPlayInstance.value = null; |
| 139 | emit('onUnmounted'); | 172 | emit('onUnmounted'); |
| 173 | + stopOnDemandVideo(); | ||
| 140 | }); | 174 | }); |
| 141 | 175 | ||
| 176 | + // 停止点播视频 | ||
| 177 | + const stopOnDemandVideo = async () => { | ||
| 178 | + const { tbDeviceId, channelId } = props.GBTOption; | ||
| 179 | + await stopOnDemandVideoApiGet(tbDeviceId, channelId); | ||
| 180 | + }; | ||
| 181 | + | ||
| 142 | defineExpose({ | 182 | defineExpose({ |
| 143 | reloadPlayer: init, | 183 | reloadPlayer: init, |
| 144 | getInstance: () => unref(videoPlayInstance), | 184 | getInstance: () => unref(videoPlayInstance), |
| @@ -178,8 +218,8 @@ | @@ -178,8 +218,8 @@ | ||
| 178 | <div> | 218 | <div> |
| 179 | <Button | 219 | <Button |
| 180 | class="left-top in-block" | 220 | class="left-top in-block" |
| 181 | - @mousedown="moveStart('up')" | ||
| 182 | - @mouseup="moveStop('up')" | 221 | + @mousedown="moveStart('UP')" |
| 222 | + @mouseup="moveStop('UP')" | ||
| 183 | > | 223 | > |
| 184 | <CaretUpOutlined class="icon-rotate child-icon" /> | 224 | <CaretUpOutlined class="icon-rotate child-icon" /> |
| 185 | </Button> | 225 | </Button> |
| @@ -10,90 +10,73 @@ | @@ -10,90 +10,73 @@ | ||
| 10 | :showOkBtn="false" | 10 | :showOkBtn="false" |
| 11 | @cancel="handleCancel" | 11 | @cancel="handleCancel" |
| 12 | > | 12 | > |
| 13 | - <div class="flex items-center justify-center w-full h-full min-h-96 video-container"> | ||
| 14 | - <Video | 13 | + <div |
| 14 | + class="flex items-center justify-center w-full h-full min-h-96 video-container bg-dark-50" | ||
| 15 | + > | ||
| 16 | + <VideoPlayer | ||
| 17 | + ref="videoInstance" | ||
| 15 | v-if="showVideo" | 18 | v-if="showVideo" |
| 16 | - :options="(options as any)" | 19 | + :options="(options as VideoJsPlayerOptions)" |
| 17 | :withToken="withToken" | 20 | :withToken="withToken" |
| 18 | - @on-unmounted="handleCloseFlvPlayUrl" | 21 | + :isGBT="isGBT" |
| 22 | + :GBTOption="GBTOption" | ||
| 19 | /> | 23 | /> |
| 20 | </div> | 24 | </div> |
| 21 | </BasicModal> | 25 | </BasicModal> |
| 22 | </div> | 26 | </div> |
| 23 | </template> | 27 | </template> |
| 24 | <script setup lang="ts"> | 28 | <script setup lang="ts"> |
| 25 | - import { ref, reactive, unref } from 'vue'; | 29 | + import { ref, reactive } from 'vue'; |
| 26 | import { BasicModal, useModalInner } from '/@/components/Modal'; | 30 | import { BasicModal, useModalInner } from '/@/components/Modal'; |
| 27 | - import type { StreamingManageRecord, CameraModel } from '/@/api/camera/model/cameraModel'; | ||
| 28 | - import { getVideoTypeByUrl } from '/@/components/Video'; | ||
| 29 | - import { closeFlvPlay, getFlvPlayUrl, getStreamingPlayUrl } from '/@/api/camera/cameraManager'; | ||
| 30 | - import { isRtspProtocol } from '/@/components/Video/src/utils'; | ||
| 31 | import { VideoJsPlayerOptions } from 'video.js'; | 31 | import { VideoJsPlayerOptions } from 'video.js'; |
| 32 | - import { useFingerprint } from '/@/utils/useFingerprint'; | ||
| 33 | - import { GetResult } from '@fingerprintjs/fingerprintjs'; | ||
| 34 | - import { AccessMode } from '/@/views/camera/manage/config.data'; | ||
| 35 | - import { Video } from './config'; | 32 | + import VideoPlayer from './video.vue'; |
| 33 | + import { getVideoControlStart } from '/@/api/device/videoChannel'; | ||
| 34 | + import { VideoChannelItemType } from '/@/api/device/model/videoChannelModel'; | ||
| 35 | + import { getVideoTypeByUrl } from '/@/components/Video'; | ||
| 36 | 36 | ||
| 37 | const heightNum = ref(800); | 37 | const heightNum = ref(800); |
| 38 | const showVideo = ref(false); | 38 | const showVideo = ref(false); |
| 39 | 39 | ||
| 40 | - const playUrl = ref(''); | 40 | + const videoInstance = ref<InstanceType<typeof VideoPlayer>>(); |
| 41 | 41 | ||
| 42 | const videoId = ref<string>(); | 42 | const videoId = ref<string>(); |
| 43 | 43 | ||
| 44 | const withToken = ref(false); | 44 | const withToken = ref(false); |
| 45 | 45 | ||
| 46 | - const fingerprintResult = ref<Nullable<GetResult>>(null); | ||
| 47 | - | ||
| 48 | const options = reactive<VideoJsPlayerOptions>({ | 46 | const options = reactive<VideoJsPlayerOptions>({ |
| 49 | width: '100%' as unknown as number, | 47 | width: '100%' as unknown as number, |
| 50 | height: 384 as unknown as number, | 48 | height: 384 as unknown as number, |
| 51 | autoplay: true, | 49 | autoplay: true, |
| 52 | }); | 50 | }); |
| 51 | + const GBTOption = ref({ | ||
| 52 | + tbDeviceId: '', | ||
| 53 | + channelId: '', | ||
| 54 | + }); | ||
| 55 | + const isGBT = ref<boolean>(false); | ||
| 53 | 56 | ||
| 54 | - const setSources = (url: string, fingerprintResult: GetResult, id) => { | ||
| 55 | - const flag = isRtspProtocol(url); | ||
| 56 | - options.sources = [ | ||
| 57 | - { | ||
| 58 | - src: flag ? getFlvPlayUrl(url, fingerprintResult.visitorId) : url, | ||
| 59 | - type: getVideoTypeByUrl(url), | ||
| 60 | - id, | ||
| 61 | - }, | ||
| 62 | - ]; | ||
| 63 | - }; | ||
| 64 | - | ||
| 65 | - const { getResult } = useFingerprint(); | ||
| 66 | - const [register] = useModalInner( | ||
| 67 | - async (data: { record: CameraModel | StreamingManageRecord }) => { | ||
| 68 | - const { record } = data; | 57 | + const [register, { setModalProps }] = useModalInner( |
| 58 | + async (data: { record: VideoChannelItemType }) => { | ||
| 59 | + const { record, ifShowGBT = false } = data; | ||
| 69 | videoId.value = record.id || ''; | 60 | videoId.value = record.id || ''; |
| 70 | - const result = await getResult(); | ||
| 71 | - fingerprintResult.value = result; | ||
| 72 | - if (record.accessMode === AccessMode.ManuallyEnter) { | ||
| 73 | - if ((record as CameraModel).videoUrl) { | ||
| 74 | - if (isRtspProtocol((record as CameraModel).videoUrl)) { | ||
| 75 | - playUrl.value = (record as CameraModel).videoUrl; | ||
| 76 | - closeFlvPlay(unref(playUrl), result.visitorId); | ||
| 77 | - withToken.value = true; | ||
| 78 | - } | ||
| 79 | - setSources((record as CameraModel).videoUrl, result, record.id); | ||
| 80 | - } | ||
| 81 | - } else { | ||
| 82 | - try { | ||
| 83 | - const { data: { url } = { url: '' } } = await getStreamingPlayUrl(record.id!); | ||
| 84 | - setSources(url, result, record.id); | ||
| 85 | - } catch (error) {} | 61 | + isGBT.value = ifShowGBT; |
| 62 | + GBTOption.value.tbDeviceId = record.deviceId; | ||
| 63 | + GBTOption.value.channelId = record.channelId; | ||
| 64 | + try { | ||
| 65 | + setModalProps({ loading: true, loadingTip: '视频加载中...' }); | ||
| 66 | + | ||
| 67 | + const result = await getVideoControlStart({ | ||
| 68 | + deviceId: record.deviceId, | ||
| 69 | + channelId: record.channelId, | ||
| 70 | + }); | ||
| 71 | + options.sources = [{ src: result.data.flv, type: getVideoTypeByUrl(result.data.flv) }]; | ||
| 72 | + showVideo.value = true; | ||
| 73 | + } catch (error) { | ||
| 74 | + } finally { | ||
| 75 | + setModalProps({ loading: false }); | ||
| 86 | } | 76 | } |
| 87 | - showVideo.value = true; | ||
| 88 | } | 77 | } |
| 89 | ); | 78 | ); |
| 90 | 79 | ||
| 91 | - const handleCloseFlvPlayUrl = () => { | ||
| 92 | - if (isRtspProtocol(unref(playUrl))) { | ||
| 93 | - closeFlvPlay(unref(playUrl)!, unref(fingerprintResult)!.visitorId!); | ||
| 94 | - } | ||
| 95 | - }; | ||
| 96 | - | ||
| 97 | const handleCancel = () => { | 80 | const handleCancel = () => { |
| 98 | showVideo.value = false; | 81 | showVideo.value = false; |
| 99 | withToken.value = false; | 82 | withToken.value = false; |
| @@ -148,12 +148,12 @@ | @@ -148,12 +148,12 @@ | ||
| 148 | } | 148 | } |
| 149 | }; | 149 | }; |
| 150 | const handleStepNext = (e, data) => { | 150 | const handleStepNext = (e, data) => { |
| 151 | - // const { deviceType } = unref(DevConStRef)?.getFieldsValue() || {}; | 151 | + const { deviceType } = unref(DevConStRef)?.getFieldsValue() || {}; |
| 152 | if (e) { | 152 | if (e) { |
| 153 | current.value++; | 153 | current.value++; |
| 154 | unref(isUpdate) | 154 | unref(isUpdate) |
| 155 | - ? unref(TransConStRef)?.editOrAddTransportTypeStatus(true) | ||
| 156 | - : unref(TransConStRef)?.editOrAddTransportTypeStatus(false); | 155 | + ? unref(TransConStRef)?.editOrAddTransportTypeStatus(true, deviceType) |
| 156 | + : unref(TransConStRef)?.editOrAddTransportTypeStatus(false, deviceType); | ||
| 157 | } else { | 157 | } else { |
| 158 | setTransConfEditFormData(data); | 158 | setTransConfEditFormData(data); |
| 159 | } | 159 | } |
| 1 | +export enum TransportTypeEnum { | ||
| 2 | + DEFAULT = 'DEFAULT', | ||
| 3 | + MQTT = 'MQTT', | ||
| 4 | + COAP = 'COAP', | ||
| 5 | + LWM2M = 'LWM2M', | ||
| 6 | + SNMP = 'SNMP', | ||
| 7 | + TCP = 'TCP', | ||
| 8 | + GBT28181 = 'GBT28181', | ||
| 9 | +} | ||
| 10 | + | ||
| 1 | export enum TransportPayloadTypeEnum { | 11 | export enum TransportPayloadTypeEnum { |
| 2 | PROTOBUF = 'PROTOBUF', | 12 | PROTOBUF = 'PROTOBUF', |
| 3 | JSON = 'JSON', | 13 | JSON = 'JSON', |
| @@ -2,7 +2,7 @@ | @@ -2,7 +2,7 @@ | ||
| 2 | <div | 2 | <div |
| 3 | class="step2-style" | 3 | class="step2-style" |
| 4 | :style="[ | 4 | :style="[ |
| 5 | - isMqttType == 'DEFAULT' || isMqttType == 'GB/T28181' | 5 | + isMqttType == 'DEFAULT' || isMqttType == 'GBT28181' |
| 6 | ? { minHeight: 0 + 'px' } | 6 | ? { minHeight: 0 + 'px' } |
| 7 | : { minHeight: 800 + 'px' }, | 7 | : { minHeight: 800 + 'px' }, |
| 8 | ]" | 8 | ]" |
| @@ -58,6 +58,7 @@ | @@ -58,6 +58,7 @@ | ||
| 58 | import Lwm2mCpns from './cpns/lwm2m/index.vue'; | 58 | import Lwm2mCpns from './cpns/lwm2m/index.vue'; |
| 59 | import SnmpCpns from './cpns/snmp/index.vue'; | 59 | import SnmpCpns from './cpns/snmp/index.vue'; |
| 60 | import TcpCpns from './cpns/tcp/index.vue'; | 60 | import TcpCpns from './cpns/tcp/index.vue'; |
| 61 | + import { DeviceTypeEnum } from '/@/api/device/model/deviceModel'; | ||
| 61 | 62 | ||
| 62 | const emits = defineEmits(['prev']); | 63 | const emits = defineEmits(['prev']); |
| 63 | const props = defineProps({ | 64 | const props = defineProps({ |
| @@ -150,10 +151,14 @@ | @@ -150,10 +151,14 @@ | ||
| 150 | ...getTcpVal, | 151 | ...getTcpVal, |
| 151 | ...val, | 152 | ...val, |
| 152 | }; | 153 | }; |
| 154 | + | ||
| 155 | + if (val?.transportType === 'GBT28181') { | ||
| 156 | + step2Data.transportConfiguration = { type: val?.transportType }; | ||
| 157 | + } | ||
| 153 | return step2Data; | 158 | return step2Data; |
| 154 | }; | 159 | }; |
| 155 | 160 | ||
| 156 | - const editOrAddTransportTypeStatus = (status: boolean) => { | 161 | + const editOrAddTransportTypeStatus = (status: boolean, deviceType: DeviceTypeEnum) => { |
| 157 | const options = [ | 162 | const options = [ |
| 158 | { label: '默认', value: 'DEFAULT' }, | 163 | { label: '默认', value: 'DEFAULT' }, |
| 159 | { label: 'MQTT', value: 'MQTT' }, | 164 | { label: 'MQTT', value: 'MQTT' }, |
| @@ -162,12 +167,12 @@ | @@ -162,12 +167,12 @@ | ||
| 162 | // { label: 'SNMP', value: 'SNMP' }, | 167 | // { label: 'SNMP', value: 'SNMP' }, |
| 163 | { label: 'TCP/UDP', value: 'TCP' }, | 168 | { label: 'TCP/UDP', value: 'TCP' }, |
| 164 | ]; | 169 | ]; |
| 165 | - // if (deviceType == 'DIRECT_CONNECTION') { | ||
| 166 | - // options.push({ label: 'GB/T 28181', value: 'GB/T28181' });//暂时隐藏 GBT 28181写完放出来 | ||
| 167 | - // } | ||
| 168 | - // if (deviceType != 'DIRECT_CONNECTION' && isMqttType.value == 'GB/T28181') { | ||
| 169 | - // setFieldsValue({ transportType: null }); | ||
| 170 | - // } | 170 | + if (deviceType == DeviceTypeEnum.DIRECT_CONNECTION) { |
| 171 | + options.push({ label: 'GBT28181', value: 'GBT28181' }); //暂时隐藏 GBT 28181写完放出来 | ||
| 172 | + } | ||
| 173 | + if (deviceType != 'DIRECT_CONNECTION' && isMqttType.value == 'GBT28181') { | ||
| 174 | + setFieldsValue({ transportType: null }); | ||
| 175 | + } | ||
| 171 | updateSchema({ | 176 | updateSchema({ |
| 172 | field: 'transportType', | 177 | field: 'transportType', |
| 173 | componentProps: { | 178 | componentProps: { |