tplink摄像头语音对讲,TPLINK机构信息增、删、改同步

This commit is contained in:
曹磊 2025-03-18 18:06:20 +08:00
parent 7aa15bbbae
commit eea3145365
8 changed files with 196 additions and 95 deletions

View File

@ -17,7 +17,7 @@
</a-row> </a-row>
<a-row style="margin-top: 14px"> <a-row style="margin-top: 14px">
<a-col :span="4" class="labelText"> <a-col :span="4" class="labelText">
画面镜像 画面翻转
</a-col> </a-col>
<a-col :span="8"> <a-col :span="8">
<a-select v-model:value="formData.flip_type" @change="(value) => changeSwitch('flip_type', value)"> <a-select v-model:value="formData.flip_type" @change="(value) => changeSwitch('flip_type', value)">
@ -27,17 +27,6 @@
<a-select-option value="center">中心</a-select-option> <a-select-option value="center">中心</a-select-option>
</a-select> </a-select>
</a-col> </a-col>
<a-col :span="4" class="labelText">
画面翻转
</a-col>
<a-col :span="8">
<a-select v-model:value="formData.rotate_type" @change="(value) => changeSwitch('rotate_type', value)">
<a-select-option value="off">关闭</a-select-option>
<a-select-option value="anticlockwise_180">上下翻转</a-select-option>
<a-select-option value="anticlockwise_90">左翻转90°</a-select-option>
<a-select-option value="clockwise_90">右翻转90°</a-select-option>
</a-select>
</a-col>
</a-row> </a-row>
<a-row style="margin-top: 14px"> <a-row style="margin-top: 14px">
<a-col :span="1"></a-col> <a-col :span="1"></a-col>
@ -255,9 +244,8 @@ import {
smartwtl: "auto_wtl",//"auto_wtl_ae" //- "auto_wtl" //- "manual" // smartwtl: "auto_wtl",//"auto_wtl_ae" //- "auto_wtl" //- "manual" //
smartwtl_digital_level: "0",// smartwtl_digital_level: "0",//
flip_type: "center",// "off"// "left_and_right"// "up_and_down"// "center"// flip_type: "center",// "off"// "left_and_right"// "up_and_down"// "center"//
night_vision_mode: "md_night_vision",//"wtl_night_vision"// "inf_night_vision"// "md_night_vision"// night_vision_mode: "md_night_vision",//"wtl_night_vision"// "inf_night_vision"// "md_night_vision"//
rotate_type: "off",// "off"// "anticlockwise_180"//180 "clockwise_90"//90 "anticlockwise_90"//90
}); });
const player = ref(); const player = ref();
@ -268,6 +256,7 @@ import {
/** /**
* 恢复默认 * 恢复默认
*/
function restoreDefault(){ function restoreDefault(){
if(formData.deviceIndex==''){ if(formData.deviceIndex==''){
return return
@ -362,9 +351,8 @@ import {
"type": "switch" "type": "switch"
}).then(res=>{ }).then(res=>{
// console.log(res); // console.log(res);
formData.flip_type = res.flip_type; // formData.flip_type = res.flip_type; //
formData.night_vision_mode = res.night_vision_mode; // formData.night_vision_mode = res.night_vision_mode; //
formData.rotate_type = res.rotate_type; // 使
}); });
} }

View File

@ -52,6 +52,7 @@
const formData = reactive<Record<string, any>>({ const formData = reactive<Record<string, any>>({
// //
videoDevId: '',// videoDevId: '',//
storageDevId: '',//ID
multitrans: '',//IPCmultitrans multitrans: '',//IPCmultitrans
startTime: '',// startTime: '',//
endTime: '',// endTime: '',//
@ -97,52 +98,33 @@
}); });
// //
await getMultitransUrl({ await getMultitransUrl({
"deviceIndex":formData.videoDevId, "videoDevId":formData.videoDevId
"startTime":formData.startTime,
"endTime":formData.endTime,
"scale":formData.scale
}).then(res=>{ }).then(res=>{
confirmLoading.value=false; confirmLoading.value=false;
if(res.success == false){ let startTime = formData.startTime*1000;
createMessage.error(res.message) let endTime = formData.endTime*1000;
}else{
const list = res;
list.forEach(item => {
let startTime = item.startTime*1000;
let endTime = item.endTime*1000;
let duration = endTime - startTime; let duration = endTime - startTime;
// console.log(duration);
// console.log("url:"+item.url);
// console.log("socket:"+item.wssUrl);
// console.log("queryAddress:"+item.queryAddress);
// console.log("videoDevId:"+item.videoDevId);
// console.log("storageDevId:"+item.storageDevId);
// console.log("startTime:"+startTime);
// console.log("endTime:"+endTime);
// console.log("scale:"+item.scale);
player.value = new TumsPlayer('video-container-multitrans', { player.value = new TumsPlayer('video-container-multitrans', {
"autoplay": true, "autoplay": true,
"resolution": "HD", "resolution": "HD",
"streamType": "sdvod", // "streamType": "sdvod", //
"url": item.url, // url "url": res.url, // url
"socket": item.wssUrl, "socket": res.wssUrl,
"type": "rtsp", "type": "rtsp",
"decoderType": "wasm", // "decoderType": "wasm", //
"queryAddress": item.queryAddress, "queryAddress": res.queryAddress,
"videoSessionId": "", "videoSessionId": "",
"videoDevId": item.videoDevId, // id "videoDevId": res.videoDevId, // id
"useMultitrans": true, "useMultitrans": true,
"storageDevId": item.storageDevId, "storageDevId": formData.storageDevId,
"startTime": startTime, // 13 "startTime": startTime, // 13
"endTime": endTime, // 13 "endTime": endTime, // 13
"eventType": [1, 2], // "eventType": [1, 2], //
"scale": item.scale // "scale": 1 //
}); });
setTimeout(()=>{stop(player)}, duration); setTimeout(()=>{stop(player)}, duration);
}) })
} }
});
}
/** /**
* 切换回放倍 * 切换回放倍

View File

@ -55,6 +55,7 @@
const formData = reactive<Record<string, any>>({ const formData = reactive<Record<string, any>>({
// //
videoDevId: '',// videoDevId: '',//
storageDevId: '',//ID
startTime: '',// startTime: '',//
endTime: '',// endTime: '',//
videoType: '',// videoType: '',//
@ -101,11 +102,12 @@
}); });
// //
await getPlaybackUrlList({ await getPlaybackUrlList({
"deviceIndex":formData.videoDevId, "videoDevId":formData.videoDevId,
"storageDevId":formData.storageDevId,
"videoType":formData.videoType,
"scale":formData.scale,
"startTime":formData.startTime, "startTime":formData.startTime,
"endTime":formData.endTime, "endTime":formData.endTime,
"videoType":formData.videoType,
"scale":formData.scale
}).then(res=>{ }).then(res=>{
confirmLoading.value=false; confirmLoading.value=false;
// console.log(res); // console.log(res);
@ -153,6 +155,7 @@
* 切换回放倍 * 切换回放倍
*/ */
function changeScale(){ function changeScale(){
//
createMessage.info('切换回放倍速至'+formData.scale+'倍'); createMessage.info('切换回放倍速至'+formData.scale+'倍');
let scale = parseInt(formData.scale) ; let scale = parseInt(formData.scale) ;
player.value.setPlaybackConfig({"scale":scale}); player.value.setPlaybackConfig({"scale":scale});

View File

@ -17,8 +17,11 @@
<span style="margin-left: 5px;"> <span style="margin-left: 5px;">
<a-button preIcon="ant-design:phone-outlined" @click="screenshot">巡航*</a-button> <a-button preIcon="ant-design:phone-outlined" @click="screenshot">巡航*</a-button>
</span> </span>
<span style="margin-left: 5px;"> <span style="margin-left: 5px;" v-show="!izPhone">
<a-button preIcon="ant-design:phone-outlined" @click="screenshot">电话*</a-button> <a-button preIcon="ant-design:phone-outlined" @click="startPhone">电话</a-button>
</span>
<span style="margin-left: 5px;" v-show="izPhone">
<a-button type="primary" danger ghost preIcon="ant-design:phone-outlined" @click="stopPhone">电话</a-button>
</span> </span>
<span style="margin-left: 15px;">分屏 <span style="margin-left: 15px;">分屏
<a-select <a-select
@ -46,20 +49,14 @@
<span style="margin-left: 5px;" v-show="izRecording"> <span style="margin-left: 5px;" v-show="izRecording">
<a-button type="primary" danger ghost preIcon="ant-design:video-camera-outlined" @click="recordingEnd">录制</a-button> <a-button type="primary" danger ghost preIcon="ant-design:video-camera-outlined" @click="recordingEnd">录制</a-button>
</span> </span>
<!-- <span style="margin-left: 15px;">画面翻转 <span style="margin-left: 15px;">画面翻转
<a-select <a-select v-model:value="formData.flip_type" @change="(value) => changeSwitch('flip_type', value)">
ref="select" <a-select-option value="off">关闭</a-select-option>
v-model:value="rotateType" <a-select-option value="left_and_right">左右</a-select-option>
style="width: 120px" <a-select-option value="up_and_down">上下</a-select-option>
@focus="focus" <a-select-option value="center">中心</a-select-option>
@change="saveImageSwitch"
>
<a-select-option value="off">不翻转</a-select-option>
<a-select-option value="anticlockwise_180">上下翻转</a-select-option>
<a-select-option value="clockwise_90">右翻转90°</a-select-option>
<a-select-option value="anticlockwise_90">左翻转90°</a-select-option>
</a-select> </a-select>
</span>--> </span>
<span style="margin-left: 5px;"> <span style="margin-left: 5px;">
<a-button preIcon="ant-design:alert-outlined" @click="manualAlarm">报警</a-button> <a-button preIcon="ant-design:alert-outlined" @click="manualAlarm">报警</a-button>
</span> </span>
@ -74,7 +71,13 @@
import { useMessage } from '/@/hooks/web/useMessage'; import { useMessage } from '/@/hooks/web/useMessage';
import { getValueType } from '/@/utils'; import { getValueType } from '/@/utils';
import { Form } from 'ant-design-vue'; import { Form } from 'ant-design-vue';
import { getPreviewUrl, testAudio } from "@/views/iot/tplink/camera/camera.api"; import {
getImageCommon,
getMultitransUrl,
getPreviewUrl,
setImageCommon,
testAudio
} from "@/views/iot/tplink/camera/camera.api";
const props = defineProps({ const props = defineProps({
formDisabled: { type: Boolean, default: false }, formDisabled: { type: Boolean, default: false },
@ -87,8 +90,9 @@
const resolution = ref<string>('超清'); const resolution = ref<string>('超清');
const izPlaying = ref<boolean>(true); const izPlaying = ref<boolean>(true);
const izRecording = ref<boolean>(false); const izRecording = ref<boolean>(false);
const izPhone = ref<boolean>(false);
const fishEyeDisplayMode = ref<string>('ORIGIN'); const fishEyeDisplayMode = ref<string>('ORIGIN');
const rotateType = ref<string>('off'); const flipType = ref<string>('off');
const useForm = Form.useForm; const useForm = Form.useForm;
const emit = defineEmits(['register', 'ok']); const emit = defineEmits(['register', 'ok']);
const formData = reactive<Record<string, any>>({ const formData = reactive<Record<string, any>>({
@ -103,6 +107,8 @@
wsUrl: '',//ws wsUrl: '',//ws
wssUrl: '',//wss wssUrl: '',//wss
flip_type: '',// "off"// "left_and_right"// "up_and_down"// "center"//
}); });
const { createMessage } = useMessage(); const { createMessage } = useMessage();
const labelCol = ref<any>({ xs: { span: 24 }, sm: { span: 5 } }); const labelCol = ref<any>({ xs: { span: 24 }, sm: { span: 5 } });
@ -144,6 +150,7 @@
}); });
createPreview(); createPreview();
getSwitch();
/* await getIpcCapability({"deviceIndex":formData.deviceIndex}).then(res=>{ /* await getIpcCapability({"deviceIndex":formData.deviceIndex}).then(res=>{
console.log(res); console.log(res);
@ -172,6 +179,8 @@
// url: formData.backupUrl, // , getPreviewUrl // url: formData.backupUrl, // , getPreviewUrl
socket: formData.wssUrl, // websocket, getPreviewUrl socket: formData.wssUrl, // websocket, getPreviewUrl
pluginPath: '/static', // sdkpluginPath pluginPath: '/static', // sdkpluginPath
talkEnable: true,
useMultitrans: true,
}); });
let isPlaying = player.value.isPlaying(); let isPlaying = player.value.isPlaying();
@ -230,19 +239,32 @@
player.value.setFishEyeDisplayMode(fishEyeDisplayMode.value); player.value.setFishEyeDisplayMode(fishEyeDisplayMode.value);
} }
/**
* 获取画面翻转
*/
function getSwitch(){
if(formData.deviceIndex==null){
return
}
getImageCommon({
"deviceIndex": formData.deviceIndex,
"type": "switch"
}).then(res=>{
formData.flip_type = res.flip_type; //
});
}
/** /**
* 画面翻转 * 画面翻转
*/ */
function saveImageSwitch(){ function changeSwitch(attr,value){
player.value.saveImageSwitch({rotate_type:1}).then(() => { let param = {};
// 0.5-2s param[attr] = value;
createMessage.success('设置成功实际画面需要0.5-2s进行响应'); setImageCommon({
}).catch((errData) => { "deviceIndex": formData.deviceIndex,
// "type": "switch",
// errData.error_code "param": param
console.log(errData); }).then(res=>{ });
createMessage.error('设置错误,'+errData.msg);
});
} }
/** /**
@ -288,6 +310,31 @@
}); });
} }
/**
* 开始电话
*/
function startPhone(){
getMultitransUrl({
"videoDevId":formData.deviceIndex
}).then(res=>{
console.log(res);
player.value.startVoiceIntercom({
"url": res.url, // url
"wssUrl": res.wssUrl,
"mode": "half_duplex"
});
izPhone.value = true;
});
}
/**
* 结束电话
*/
function stopPhone(){
player.value.stopVoiceIntercom();
izPhone.value = false;
}
/** /**
* 销毁 * 销毁
*/ */

View File

@ -3,6 +3,9 @@ import { defHttp } from '/@/utils/http/axios';
enum Api { enum Api {
list = '/iot/projectInfo/list', list = '/iot/projectInfo/list',
sync = '/iot/projectInfo/sync', sync = '/iot/projectInfo/sync',
add = '/iot/projectInfo/add',
edit = '/iot/projectInfo/edit',
delete = '/iot/projectInfo/delete',
} }
/** /**
@ -16,3 +19,21 @@ export const list = (params) => defHttp.get({ url: Api.list, params });
* @param params * @param params
*/ */
export const sync = (params) => defHttp.get({ url: Api.sync, params }); export const sync = (params) => defHttp.get({ url: Api.sync, params });
/**
*
* @param params
*/
export const saveOrUpdatePrject = (params, isUpdate) => {
let url = isUpdate ? Api.edit : Api.add;
return defHttp.post({ url: url, params });
};
/**
*
*/
export const deletePrject = (params,handleSuccess) => {
return defHttp.post({ url: Api.delete, params }, { joinParamsToUrl: true }).then(() => {
handleSuccess();
});
};

View File

@ -81,6 +81,7 @@ export const formSchema: FormSchema[] = [
label: '项目序号', label: '项目序号',
field: 'projectId', field: 'projectId',
component: 'Input', component: 'Input',
dynamicDisabled: true
}, },
{ {
label: '项目名称', label: '项目名称',
@ -91,26 +92,31 @@ export const formSchema: FormSchema[] = [
label: '创建时间', label: '创建时间',
field: 'createTimeStr', field: 'createTimeStr',
component: 'Input', component: 'Input',
dynamicDisabled: true
}, },
{ {
label: '设备数量', label: '设备数量',
field: 'deviceNum', field: 'deviceNum',
component: 'Input', component: 'Input',
dynamicDisabled: true
}, },
{ {
label: '离线设备数', label: '离线设备数',
field: 'offlineNum', field: 'offlineNum',
component: 'Input', component: 'Input',
dynamicDisabled: true
}, },
{ {
label: '异常设备数', label: '异常设备数',
field: 'abnormalNum', field: 'abnormalNum',
component: 'Input', component: 'Input',
dynamicDisabled: true
}, },
{ {
label: '运行天数', label: '运行天数',
field: 'runningTimeStr', field: 'runningTimeStr',
component: 'Input', component: 'Input',
dynamicDisabled: true
}, },
{ {
label: '状态', label: '状态',
@ -125,6 +131,7 @@ export const formSchema: FormSchema[] = [
] ]
}; };
}, },
dynamicDisabled: true
}, },
]; ];

View File

@ -5,7 +5,8 @@
<BasicTable @register="registerTable"> <BasicTable @register="registerTable">
<!--插槽:table标题--> <!--插槽:table标题-->
<template #tableTitle> <template #tableTitle>
<a-button type="primary" preIcon="ant-design:sync-outlined" @click="handleSync"> 同步</a-button> <a-button type="primary" preIcon="ant-design:plus-outlined" @click="handleCreate"> 新增</a-button>
<a-button preIcon="ant-design:sync-outlined" @click="handleSync"> 同步</a-button>
</template> </template>
<!--操作栏--> <!--操作栏-->
<template #action="{ record }"> <template #action="{ record }">
@ -30,6 +31,10 @@
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { useDrawer } from "@/components/Drawer"; import { useDrawer } from "@/components/Drawer";
import ProjectInfoDrawer from './components/ProjectInfoDrawer.vue'; import ProjectInfoDrawer from './components/ProjectInfoDrawer.vue';
import { deletePrject } from "@/views/iot/tplink/project/ProjectInfo.api";
import {Modal} from "ant-design-vue";
import {ExclamationCircleOutlined} from "@ant-design/icons-vue";
import {rebootDevice} from "@/views/iot/tplink/camera/camera.api";
//drawer //drawer
const [registerDrawer, { openDrawer }] = useDrawer(); const [registerDrawer, { openDrawer }] = useDrawer();
let router = useRouter(); let router = useRouter();
@ -70,29 +75,71 @@
}); });
/** /**
* 详情 * 新增
*/ */
function handleDetail(record: Recordable) { function handleCreate() {
openDrawer(true, {
isUpdate: false,
showFooter: true,
tenantSaas: false,
});
}
/**
* 编辑
*/
function handleEdit(record: Recordable) {
openDrawer(true, { openDrawer(true, {
record, record,
isUpdate: true, isUpdate: true,
showFooter: false, showFooter: true,
tenantSaas: false, tenantSaas: false,
}); });
} }
/**
* 删除
*/
function handleDelete(record: Recordable) {
Modal.confirm({
title: '删除项目',
width: '500px',
icon: createVNode(ExclamationCircleOutlined),
content: createVNode('div', { style: 'color:red;' }, '项目删除后,与之相关信息将失效,确定要删除该项目吗?'),
okText: '确定',
onOk() {
deletePrject(record, reload);
},
onCancel() {
// console.log('Cancel');
},
class: 'test',
});
}
/** /**
* 操作栏 * 操作栏
*/ */
function getTableAction(record) { function getTableAction(record) {
return [ return [
{ {
label: '详情', label: '编辑',
onClick: handleDetail.bind(null, record), onClick: handleEdit.bind(null, record),
},
{
label: '删除',
onClick: handleDelete.bind(null, record),
}, },
]; ];
} }
/**
* 成功回调
*/
function handleSuccess() {
reload();
}
/** /**
* 查询 * 查询
*/ */

View File

@ -19,6 +19,7 @@ import { formSchema } from "@/views/iot/tplink/project/ProjectInfo.data";
import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
import { useDrawerAdaptiveWidth } from '/@/hooks/jeecg/useAdaptiveWidth'; import { useDrawerAdaptiveWidth } from '/@/hooks/jeecg/useAdaptiveWidth';
import { getTenantId } from "/@/utils/auth"; import { getTenantId } from "/@/utils/auth";
import { saveOrUpdatePrject } from "@/views/iot/tplink/project/ProjectInfo.api";
// Emits // Emits
const emit = defineEmits(['success', 'register']); const emit = defineEmits(['success', 'register']);
@ -62,6 +63,11 @@ const { adaptiveWidth } = useDrawerAdaptiveWidth();
// //
async function handleSubmit() { async function handleSubmit() {
try { try {
let values = await validate();
setDrawerProps({ confirmLoading: true });
let params = values;
let isUpdateVal = unref(isUpdate);
await saveOrUpdatePrject(params,isUpdateVal);
// //
closeDrawer(); closeDrawer();
// //