Browse Source

信鸽服务

release_1.1.2
deartibers 3 years ago
parent
commit
5b9d2c746e
  1. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/createdSuccessfully.png
  2. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/icon_choose.png
  3. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/icon_four.png
  4. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/icon_four_choose.png
  5. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/icon_offLine.png
  6. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/icon_one.png
  7. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/icon_online.png
  8. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/icon_three.png
  9. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/icon_three_choose.png
  10. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/icon_timing.png
  11. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/icon_two.png
  12. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/icon_two_choose.png
  13. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/noteTopChoose.png
  14. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/triangle.png
  15. 10
      code/VideoAccess-VCMP/web/client/src/index.less
  16. 88
      code/VideoAccess-VCMP/web/client/src/sections/offline/actions/carrierpigeon.js
  17. 5
      code/VideoAccess-VCMP/web/client/src/sections/offline/actions/index.js
  18. 4
      code/VideoAccess-VCMP/web/client/src/sections/offline/actions/statuscode.js
  19. 754
      code/VideoAccess-VCMP/web/client/src/sections/offline/components/pushModal.jsx
  20. 44
      code/VideoAccess-VCMP/web/client/src/sections/offline/components/pushModal.less
  21. 77
      code/VideoAccess-VCMP/web/client/src/sections/offline/components/pushSideSheet.jsx
  22. 8
      code/VideoAccess-VCMP/web/client/src/sections/offline/components/pushSideSheet.less
  23. 328
      code/VideoAccess-VCMP/web/client/src/sections/offline/containers/carrierpigeon.jsx
  24. 7
      code/VideoAccess-VCMP/web/client/src/utils/webapi.js

BIN
code/VideoAccess-VCMP/web/client/assets/images/background/createdSuccessfully.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
code/VideoAccess-VCMP/web/client/assets/images/background/icon_choose.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
code/VideoAccess-VCMP/web/client/assets/images/background/icon_four.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
code/VideoAccess-VCMP/web/client/assets/images/background/icon_four_choose.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
code/VideoAccess-VCMP/web/client/assets/images/background/icon_offLine.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
code/VideoAccess-VCMP/web/client/assets/images/background/icon_one.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 983 B

BIN
code/VideoAccess-VCMP/web/client/assets/images/background/icon_online.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
code/VideoAccess-VCMP/web/client/assets/images/background/icon_three.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
code/VideoAccess-VCMP/web/client/assets/images/background/icon_three_choose.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
code/VideoAccess-VCMP/web/client/assets/images/background/icon_timing.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

BIN
code/VideoAccess-VCMP/web/client/assets/images/background/icon_two.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
code/VideoAccess-VCMP/web/client/assets/images/background/icon_two_choose.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
code/VideoAccess-VCMP/web/client/assets/images/background/noteTopChoose.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

BIN
code/VideoAccess-VCMP/web/client/assets/images/background/triangle.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 475 B

10
code/VideoAccess-VCMP/web/client/src/index.less

@ -19,6 +19,16 @@ body {
#App{
height: 100%;
}
.semi-timepicker-panel{//时间选择器不显示滚动栏
::-webkit-scrollbar {
display: none; /* Chrome Safari */
}
scrollbar-width: none; /* firefox */
-ms-overflow-style: none; /* IE 10+ */
overflow-x: hidden;
overflow-y: auto;
}
a:link {
text-decoration: none;
color: unset

88
code/VideoAccess-VCMP/web/client/src/sections/offline/actions/carrierpigeon.js

@ -0,0 +1,88 @@
"use strict";
import { basicAction } from "@peace/utils";
import { ApiTable } from "$utils";
export function getCameraListAll() {//获取摄像头能力列表
return (dispatch) =>
basicAction({
type: "get",
dispatch: dispatch,
actionType: "GET_CAMERA_LIST_ALL",
url: `${ApiTable.getCameraListAll}`,
msg: { option: "" },
reducer: { name: "" },
});
}
export function getStatusPush(query) {//获取推送配置
return (dispatch) =>
basicAction({
type: "get",
dispatch: dispatch,
actionType: "GET_STATUS_PUSH",
query: query,
url: `${ApiTable.getStatusPush}`,
msg: { option: "获取推送配置" },
reducer: { name: "StatusPushList" },
});
}
export function putSasdtatusPush(data) { //编辑推送配置
return (dispatch) =>
basicAction({
type: "put",
dispatch: dispatch,
actionType: "PUT_SASDTATUS_PUSH",
data,
url: `${ApiTable.putSasdtatusPush}`,
msg: { option: '编辑推送配置' },
reducer: {},
});
}
export function delPush(orgId) {//删除推送配置
return (dispatch) =>
basicAction({
type: "del",
dispatch: dispatch,
actionType: "DEL_PUSH",
url: `${ApiTable.delPush.replace("{configId}", orgId)}`,
msg: {
option:
"删除推送配置",
},
reducer: { name: "" },
});
}
export function putPushBanned(data, forbidden) {//禁用推送配置
return (dispatch) =>
basicAction({
type: "put",
dispatch: dispatch,
actionType: "PUT_PUSH_BANNED",
data,
url: `${ApiTable.putPushBanned}`,
msg: { option: forbidden ? "启用" : "禁用" },
reducer: {},
});
}
export function getPushCopy(orgId) {//复制推送配置
return (dispatch) =>
basicAction({
type: "get",
dispatch: dispatch,
actionType: "GET_PUSH_COPY",
url: `${ApiTable.getPushCopy.replace("{configId}", orgId)}`,
msg: { option: "复制推送配置" },
reducer: { name: "" },
});
}
export function getPushLog(orgId) {//获取推送记录
return (dispatch) =>
basicAction({
type: "get",
dispatch: dispatch,
actionType: "GET_PUSH_LOG",
url: `${ApiTable.getPushLog.replace("{configId}", orgId)}`,
msg: { option: "获取推送记录" },
reducer: { name: "" },
});
}

5
code/VideoAccess-VCMP/web/client/src/sections/offline/actions/index.js

@ -1,9 +1,8 @@
'use strict';
import * as statuscode from './statuscode'
// import * as camera from './camera'
import * as carrierpigeon from './carrierpigeon'
export default {
// ...statuscode,...camera
...statuscode
...statuscode,...carrierpigeon
}

4
code/VideoAccess-VCMP/web/client/src/sections/offline/actions/statuscode.js

@ -36,7 +36,7 @@ export function postStatusResolve(data) {
data,
actionType: "POST_STATUS_RESOLVE",
url: `${ApiTable.postStatusResolve}`,
msg: { option: "" }, //编辑解决方案
msg: { option: "编辑解决方案" }, //编辑解决方案
reducer: { name: "" },
});
}
@ -48,7 +48,7 @@ export function postStatusCustom(data) {
data,
actionType: "POST_STATUS_CUSTOM",
url: `${ApiTable.postStatusCustom}`,
msg: { option: "" }, //自定义状态码释义
msg: { option: "自定义状态码释义" }, //自定义状态码释义
reducer: { name: "" },
});
}

754
code/VideoAccess-VCMP/web/client/src/sections/offline/components/pushModal.jsx

@ -1,298 +1,582 @@
import React, { useState, useRef, useEffect, useImperativeHandle } from "react";
import React, { useState, useRef, useEffect } from "react";
import { connect } from "react-redux";
import { Modal, Form, Row, Col, Spin } from "@douyinfe/semi-ui";
import { IconTickCircle } from "@douyinfe/semi-icons";
import moment from "moment";
import { Modal, Form, Button,TimePicker,Transfer, Checkbox, Avatar } from "@douyinfe/semi-ui";
import { IconClose } from '@douyinfe/semi-icons';
import './pushModal.less'
function pushModal (props) {
const { modalName, pushRef } = props;
const { dispatch, actions, vender, close } = props;
const pushData = props.pushData || {}; //
const form = useRef();
const [visible, setVisible] = useState(false); //
const [isloading, setloading] = useState(false); //loading
const [loadingTip, setloadingTip] = useState("获取中...请稍后..."); //loading tip
const [step, setstep] = useState("none"); //
const [okText, setokText] = useState("测试校验"); //oktext
const [cancelText, setcancelText] = useState("取消"); //text
const [formObj, setformObj] = useState(); //
const {
close,
rowId,
dispatch,
actions,
title,//
pushData,//
cameraList,
} = props;
const { offline } = actions;//
const form = useRef();//
const [stepNum, setStepNum] = useState(0);//
const [okText, setOkText] = useState('下一步');//
const [cancelText, setCancelText] = useState('取消');//
const [finishSrc, setFinishSrc] = useState('/assets/images/background/icon_choose.png');//
const [stepList, setStepList] = useState([
{
chooseSrc: '/assets/images/background/icon_one.png',
unCheckedSrc: '/assets/images/background/icon_one.png',
title: '推送策略',
text: '基本信息配置'
}, {
chooseSrc: '/assets/images/background/icon_two_choose.png',
unCheckedSrc: '/assets/images/background/icon_two.png',
title: '通知策略',
text: '选择推送方式及周期'
}, {
chooseSrc: '/assets/images/background/icon_three_choose.png',
unCheckedSrc: '/assets/images/background/icon_three.png',
title: '监听范围',
text: '选择跟踪状态的设备'
}, {
chooseSrc: '/assets/images/background/icon_four_choose.png',
unCheckedSrc: '/assets/images/background/icon_four.png',
title: '创建完成',
text: '完成'
},
]);//
// const [pushWay, setPushWay] = useState('email');//
const pushWay = useRef('email');//
const emailList = useRef([]);//
const phoneList = useRef([]);//
function showDialog () {
//
setVisible(true);
}
function positionForm (val) {
let zz = /^(-?\d+)(\.\d+)?$/;
if (!val) {
return "请输入或拾取高德经纬度坐标";
} else if (val.split(",").length != 2) {
return "请输入格式为116.354169,39.835452的经纬度坐标";
} else if (!zz.test(val.split(",")[0])) {
return "只能填写数字";
} else if (!zz.test(val.split(",")[1])) {
return "只能填写数字";
} else {
return "";
const strategyList = [
//
{
id: 1,
img: "/assets/images/background/icon_offLine.png",
title: "离线即时通知",
value: "offline",
},
{
id: 2,
img: "/assets/images/background/icon_online.png",
title: "上线即时通知",
value: "online",
},
{
id: 3,
img: "/assets/images/background/icon_timing.png",
title: "定时统计",
value: "timing",
},
];
const [showList, setShowList] = useState([false, false, false]);//
const showstrategyListList = useRef(strategyList);//
const [timevalue, setTimevalue] = useState('18:00');//
const [noticeNum, setNoticeNum] = useState(0);//
const [policyList, setPolicyList] = useState([//
{
strategy: '系统监听到设备离线时,进行一次邮件推送,并将当前所 有离线的设备一同推送至信息邮箱,每次起始推送间隔不少于15分钟。',
example: '【superadmin】账号下的设备:【智慧小蓝排涝-乡山站排口】于【2022年22时00分】掉线,【智慧小蓝排涝-乡山站排口】于【2022年22时00分】掉线,【智慧小蓝排涝-乡山站排口】于【2022年22时00分】掉线,请及时处理!',
},
{
strategy: '系统监听到设备上线时,推送至信息邮箱,每次推送间隔 不少于15分钟。',
example: '【superadmin】账号下的设备:【智慧小蓝排涝-乡山站排口】于【2022年22时00分】掉线,【2022年22时00分】已恢复!',
},
{
strategy: '系统在设定时间前统计所有离线的设备信息,并推送至信 息邮箱。',
example: '【superadmin】账号下的设备,截止【2022年22时00分】,有15个设备掉线:【智慧小蓝排涝-乡山站排口】于【2022年22时00分】掉线,【智慧小蓝排涝-乡山站排口】于【2022年22时00分】掉线,【智慧小蓝排涝-乡山站排口】于【2022年22时00分】掉线,请及时处理!',
},
]);//
const [chooseCameraList, setChooseCameraList] = useState([]);//
const [mypushData, setMypushData] = useState({});//props
//
useEffect(() => {
let pushDataObj= JSON.parse(JSON.stringify(pushData))
let cameraIdList=[]
let receiverList=[]
if(pushDataObj.cameraStatusPushMonitors){//
for (let index = 0; index < pushDataObj.cameraStatusPushMonitors.length; index++) {
cameraIdList.push(String(pushDataObj.cameraStatusPushMonitors[index].cameraId))
}
}
if(pushDataObj.cameraStatusPushReceivers){//
for (let index = 0; index < pushDataObj.cameraStatusPushReceivers.length; index++) {
receiverList.push(pushDataObj.cameraStatusPushReceivers[index].receiver)
}
}
if(pushDataObj.pushWay){
pushWay.current=pushDataObj.pushWay
if(pushDataObj.pushWay=='email'){
emailList.current=receiverList
}
else{
phoneList.current=receiverList
}
}
if(pushDataObj.timing){//
setTimevalue(pushDataObj.timing)
}
setChooseCameraList(cameraIdList)
setMypushData({
...pushDataObj,
receiverList:receiverList,
})
if(pushDataObj.noticeWay){//
let arr = ['offline','online','timing']
let arr2 = [false,false,false]
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < pushDataObj.noticeWay.length; j++) {
if(arr[i]==pushDataObj.noticeWay[j]){
arr2[i]=true
}
}
}
setShowList(arr2)
}
}, []);
function handleOk () {
//
if (step == "none") {
let num = stepNum
if (num == 0) {
form.current
.validate()
.then((values) => {
//
console.log(values)
let valuesObj = JSON.parse(JSON.stringify(values));
valuesObj.longitude = values.position.split(",")[0];
valuesObj.latitude = values.position.split(",")[1];
delete valuesObj.position;
if (pushData.id) {
valuesObj.id = pushData.id;
}
var front = new moment(); //
setloading(true);
dispatch(
actions.equipmentWarehouse.getCheck({
serialNo: valuesObj.serialNo,
setStepNum(num + 1)
setOkText('下一步')
setCancelText('上一步')
if(showList.indexOf(true)>-1){
setRightDisabled(false)
}
else{
setRightDisabled(true)
}
})
}
else if (num == 1) {
setStepNum(num + 1)
setOkText('下一步')
setCancelText('上一步')
if(chooseCameraList.length>0){
setRightDisabled(false)
}
else{
setRightDisabled(true)
}
}
else if (num == 2) {
setStepNum(num + 1)
setOkText('确认并启用')
setCancelText('上一步')
}
else if (num == 3) {
//
let arr = ['offline','online','timing']
let noticeWay =[]
for (let index = 0; index < showList.length; index++) {
if(showList[index]){
noticeWay.push(arr[index])
}
}
let pushobj={}
if(showList[2]){
pushobj={
...form.current.getValues(),
noticeWay:noticeWay,
timing:timevalue,
cameraId:chooseCameraList,
}
}
else{
pushobj={
...form.current.getValues(),
noticeWay:noticeWay,
cameraId:chooseCameraList,
}
}
if(rowId){
pushobj.configId=rowId
}
dispatch(
offline.putSasdtatusPush(pushobj)
).then((res) => {
var after = new moment(); //
var duration = moment.duration(after.diff(front))._data.milliseconds;
if (res.success) {
setTimeout(
() => {
setloadingTip("已完成");
setTimeout(() => {
setstep("block");
setloading(false);
setokText("确认");
setcancelText("上一步");
setloadingTip("获取中...请稍后...");
}, 1000);
},
duration > 2000 ? 0 : 2000 - duration
close();
})
}
}
function handleCancel () {
//
let num = stepNum
if (num == 0) {
close();
}
else if (num == 1) {
setStepNum(num - 1)
setOkText('下一步')
setCancelText('取消')
setRightDisabled(false)
}
else if (num == 2) {
setStepNum(num - 1)
setOkText('下一步')
setCancelText('上一步')
setRightDisabled(false)
}
else if (num == 3) {
setStepNum(num - 1)
setOkText('下一步')
setCancelText('上一步')
setRightDisabled(false)
}
}
function handleClose () {
close();
}
function formChange (value, field) {//
if (Object.keys(field)[0] == 'receiver') {
form.current.validate(['receiver'])
}
if (value.pushWay !== pushWay.current) {
if (value.pushWay == 'phone') {
pushWay.current = value.pushWay
emailList.current = value.receiver
form.current.setValue('receiver', phoneList.current)
}
else {
pushWay.current = value.pushWay
phoneList.current = value.receiver
form.current.setValue('receiver', emailList.current)
}
}
}
const [rightDisabled, setRightDisabled] = useState(false);//
function twohandleChoose (value,index) {//
let chooselist = JSON.parse(JSON.stringify(showList))
chooselist[value - 1] = !chooselist[value - 1]
setShowList(chooselist)
let arrtrue =chooselist.indexOf(true)
if(arrtrue>-1){
setRightDisabled(false)
}else{
setRightDisabled(true)
}
}
function twohandleMouseOver (value,index){//
setNoticeNum(index)
}
function positionForm (val) {//
let myform = form.current.getValue()
if (!val||val.length<1) {
return "请输入接收信息";
}
else {
if (myform.pushWay == 'email') {
let zz = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,8})$/;
for (let index = 0; index < val.length; index++) {
if (!zz.test(val[index])) {
return "请输入正确的邮箱";
}
}
}
else {
let zz = /^[1][3,4,5,7,8][0-9]{9}$/;
for (let index = 0; index < val.length; index++) {
if (!zz.test(val[index])) {
return "请输入正确的手机号码";
}
}
}
}
}
function toTimePicker(e){//
e.stopPropagation()
}
function timeChange(value){//
let time = String(value).split(' ')
let timearr=time[4].split(':')
setTimevalue(timearr[0]+':'+timearr[1])
}
function renderSourceItem(item,index){//
return (
<div className="components-transfer-demo-source-item" key={item.key}>
<Checkbox
onChange={() => {
item.onChange();
}}
key={item.key}
checked={item.checked}
style={{ height: 52 }}
>
<Avatar style={{backgroundColor:item.color}} size="small">
{item.abbr}
</Avatar>
<div className="info">
<div className="name">{item.label}</div>
<div className="email">{item.value}</div>
</div>
</Checkbox>
</div>
);
} else {
setTimeout(
() => {
setloadingTip("校验失败");
setTimeout(() => {
setstep("none");
setloading(false);
setokText("测试校验");
setcancelText("取消");
setloadingTip("获取中...请稍后...");
}, 1000);
},
duration > 2000 ? 0 : 2000 - duration
}
function renderSelectedItem(item,index){//
return (
<div className="components-transfer-demo-selected-item" key={item.key}>
<Avatar style={{backgroundColor:item.color}} size="small">
{item.abbr}
</Avatar>
<div className="info">
<div className="name">{item.label}</div>
<div className="email">{item.value}</div>
</div>
<IconClose onClick={item.onRemove} />
</div>
);
}
});
setformObj(valuesObj);
})
.catch((errors) => {
//
console.log("errors", errors);
});
} else {
dispatch(actions.equipmentWarehouse.addchangepush(formObj)).then((res) => {
setVisible(false);
close();
});
function customFilter(sugInput, item){//, false
return item.value.includes(sugInput) || item.label.includes(sugInput);
}
function CameraChooseList(id, items){
if(id.length>0){
setRightDisabled(false)
}
function handleAfterClose () {
//
setstep("none");
setokText("测试校验");
setcancelText("取消");
else{
setRightDisabled(true)
}
setChooseCameraList(id)
}
function handleCancel () {
//
if (step == "none") {
setVisible(false);
} else {
setstep("none");
setokText("测试校验");
setcancelText("取消");
}
}
function handleLocation () {
//
window.open("https://lbs.amap.com/tools/picker", "_blank");
}
useImperativeHandle(pushRef, () => ({
//
//aa
pushNumber: () => formObj.serialNo
}));
return (
<>
<div onClick={showDialog}>{modalName == "add" ? "创建推送" : "修改"}</div>
<Modal
title={modalName == "add" ? "创建推送" : "修改"}
okText={okText}
cancelText={cancelText} //
visible={visible}
onOk={handleOk}
width={782}
height={720}
afterClose={handleAfterClose}
onCancel={handleCancel}
>
<Spin tip={loadingTip} spinning={isloading}>
<div
style={{
paddingLeft: 16,
display: step == "none" ? "block" : "none",
}}
title={title}
visible={true}
width={835}
onCancel={handleClose}
footer={
<div>
<Button type="primary" onClick={handleCancel}>
{cancelText}
</Button>
<Button theme='solid' disabled={rightDisabled} type="primary" onClick={handleOk}>
{okText}
</Button>
</div>
}
>
<div style={{ margin: '0px -24px', borderTop: '1px solid rgba(0,0,0,0.06)', borderBottom: '1px solid rgba(0,0,0,0.06)', display: 'flex' }}>
{stepList.map((item, index) => {
return (
<div key={index} style={{ width: '25%' }} className={stepNum == index ? 'myChoose' : ''}>
<div style={{ display: 'flex', margin: '12px 0px 8px 0px', justifyContent: 'center', alignItems: 'center' }}>
<img
src={index == stepNum ? item.chooseSrc : stepNum < index ? item.unCheckedSrc : finishSrc}
alt="设置"
style={{ width: 24, height: 24, marginRight: 21 }}
/>
<div>
<div style={{ fontSize: 14, color: '#1859C1' }}>
{item.title}
</div>
<div style={{ fontSize: 12, color: 'rgba(0,0,0,0.45)', marginTop: 7 }}>
{item.text}
</div>
</div>
</div>
<div className="myChooseButton"></div>
</div>
)
})}
</div>
{/* 第一步 */}
<div style={{ margin: '29px 32px 0px 32px', display: stepNum == "0" ? "block" : "none", }}>
<Form
allowEmpty
labelPosition="left"
labelAlign="left"
labelAlign="right"
labelWidth="90px"
onValueChange={(values) => console.log(values)}
onValueChange={(values, field) => formChange(values, field)}
getFormApi={(formApi) => (form.current = formApi)}
>
<Row>
<Col span={12}>
<Form.Input
maxLength="39"
field="serialNo"
label="设备编号:"
initValue={pushData.serialNo || ""}
placeholder="请输入设备编号"
style={{ width: 149 }}
rules={[{ required: true, message: "请输入设备编号" }]}
/>
</Col>
<Col span={12}>
<Form.InputNumber
formatter={(value) => `${value}`.replace(/\D/g, "")}
hideButtons={true}
maxLength="15"
field="regionCode"
label="行政区区码:"
initValue={pushData.regionCode || ""}
placeholder="请输入行政区区码"
style={{ width: 149 }}
/>
</Col>
<Col span={24}>
<div style={{ display: 'flex' }}>
<div>
<Form.Input
maxLength="36"
maxLength="16"
field="name"
label="设备名称:"
initValue={pushData.name || ""}
placeholder="请输入设备名称"
style={{ width: 421 }}
rules={[
{
required: true,
message: "请输入设备名称、常用项目或位置定义",
},
]}
label="策略名称:"
initValue={mypushData.name || ""}
placeholder="请输入策略名称,不超过16个字符"
style={{ width: 307 }}
rules={[{ required: true, message: "请输入策略名称,不超过16个字符" }]}
/>
</Col>
<Col span={24}>
</div>
<div style={{ marginLeft: 21 }}>
<Form.Select
label="设备厂家:"
field="venderId"
initValue={pushData.venderId || null}
placeholder="请选择设备厂家"
style={{ width: 421 }}
rules={[{ required: true, message: "请选择设备厂家" }]}
label="策略类型:"
field="pushWay"
initValue={mypushData.pushWay || 'email'}
placeholder="请选择策略类型"
style={{ width: 210 }}
>
{vender.map((item, index) => (
<Form.Select.Option key={index} value={item.id}>
{item.name}
<Form.Select.Option value='email'>
邮件推送
</Form.Select.Option>
<Form.Select.Option value='phone'>
短信推送
</Form.Select.Option>
))}
</Form.Select>
</Col>
<Col span={24} style={{ display: "flex" }}>
<Form.Input
maxLength="39"
field="position"
label="安装位置:"
initValue={
pushData.longitude && pushData.latitude
? pushData.longitude + "," + pushData.latitude
: ""
}
placeholder="请输入或拾取高德经纬度坐标"
style={{ width: 386 }}
</div>
</div>
<div>
<Form.TagInput
addOnBlur={true}
label='接收信息:'
field="receiver"
initValue={mypushData.receiverList||[]}
placeholder='请输入接收信息'
style={{ width: 630 }}
validate={positionForm}
rules={[
{
required: true,
message: "请输入或拾取高德经纬度坐标",
},
]}
/>
<div
style={{
width: 32,
height: 32,
background: "#1859C1",
marginLeft: 4,
display: "flex",
justifyContent: "center",
alignItems: "center",
cursor: "pointer",
marginTop: 12,
borderRadius: 3 + "px",
}}
onClick={handleLocation}
>
<img
src="../../../assets/images/background/location.png"
width={16}
height={20}
rules={[{ required: true, message: "请输入接收信息" }]}
/>
</div>
</Col>
</Row>
</Form>
<div style={{ color: 'rgba(0,0,0,0.45)', fontSize: 12, textAlign: 'right' }}>
敲击回车键后输入内容将成为标签
</div>
<div style={{ height: 224, display: step }}>
<div style={{ margin: '20px -56px 0px', borderTop: '1px solid rgba(0,0,0,0.06)' }}></div>
</div>
{/* 第二步 */}
<div style={{ margin: '29px 32px 0px 32px', display: stepNum == "1" ? "block" : "none", }}>
<div
style={{ display: "flex", alignItems: "center",justifyContent: 'space-between', height: 102 }}
>
{showstrategyListList.current.map((item, index) => (
<div
key={item.id}
style={{
paddingTop: 50,
width: 215,
height: 102,
border:
showList[index]
? "1px solid #1859C1"
: "1px solid #F9F9F9",
borderRadius: 3,
display: "flex",
justifyContent: "center",
boxShadow: '0px 2px 4px 0px rgba(231,231,231,0.5)',
cursor: "pointer",
position: "relative",
}}
onClick={() => twohandleChoose(item.id,index)}
onMouseOver={() => twohandleMouseOver(item.id,index)}
>
<IconTickCircle style={{ color: "#04B234", fontSize: 60 }} />
<img src={item.img} style={{width:56,height:56,margin:'23px 20px'}} alt="设置" />
{
item.id==3?(
<div>
<div style={{marginTop:22,color: '#34383E'}}>
{item.title}
</div>
<div style={{marginTop:10}}
onClick={(e)=>toTimePicker(e)}>
<TimePicker
showClear={false}
format={'HH:mm'}
placeholder="时间"
minuteStep={5}
defaultValue={'18:00'}
onChange={timeChange}
value={timevalue}
style={{ width: 108 }}/>
</div>
</div>
):(
<div style={{marginTop:48,color: '#34383E'}}>
{item.title}
</div>
)
}
{showList[index] ? (
<div
style={{
marginTop: 20,
display: "flex",
justifyContent: "center",
position: "absolute",
top: "-3px",
right: "-6px",
}}
>
是否确认创建推送
<img
src="/assets/images/background/noteTopChoose.png"
alt="1"
style={{width:49,height:34}}
/>
</div>
) : (
""
)}
</div>
))}
</div>
<div style={{ display: "flex", alignItems: "center",justifyContent: 'space-between'}}>
{showstrategyListList.current.map((item, index) => (
<div style={{width:215,height:15,textAlign: 'center'}} key={index}>
{
noticeNum==index?(
<img
src="/assets/images/background/triangle.png"
alt="1"
style={{width:14,height:12}}
/>
):''
}
</div>
))}
</div>
<div style={{background: 'rgba(231,240,251,0.8)',borderRadius: 3}}>
<div style={{margin:'0px 20px 0px'}}>
<div style={{paddingTop:13}}>
<span style={{color: '#1859C1'}}>策略</span>
<span style={{color: 'rgba(0,0,0,0.65)'}}>{policyList[noticeNum].strategy}</span>
</div>
<div style={{marginTop:12,paddingBottom:12}}>
<span style={{color: '#1859C1'}}>实例</span>
<span style={{color: 'rgba(0,0,0,0.65)'}}>{policyList[noticeNum].example}</span>
</div>
</div>
</div>
<div style={{ margin: '20px -56px 0px', borderTop: '1px solid rgba(0,0,0,0.06)' }}></div>
</div>
{/* 第三步 */}
<div style={{ margin: '29px 32px 0px 32px', display: stepNum == "2" ? "block" : "none", }}>
<Transfer
style={{ width: 683,height:220 }}
dataSource={cameraList}
filter={customFilter}
renderSelectedItem={renderSelectedItem}
renderSourceItem={renderSourceItem}
value={chooseCameraList}
inputProps={{ placeholder: '搜项目或设备名称或设备编号' }}
onChange={(id, items) => CameraChooseList(id, items)}
/>
<div style={{ margin: '20px -56px 0px', borderTop: '1px solid rgba(0,0,0,0.06)' }}></div>
</div>
{/* 第四步 */}
<div style={{ margin: '30px 32px 0px 32px',textAlign: 'center', display: stepNum == "3" ? "block" : "none", }}>
<img
src='/assets/images/background/createdSuccessfully.png'
alt="设置"
style={{ width: 97, height: 92}}
/>
<div style={{color: '#34383E',marginTop:4}}>创建完成</div>
<div style={{ margin: '25px -56px 0px', borderTop: '1px solid rgba(0,0,0,0.06)' }}></div>
</div>
</Spin>
</Modal>
</>
);
}
function mapStateToProps (state) {
const { auth, global, members, vender } = state;
const { auth, global, members, CameraKind, CameraAbility } = state;
return {
loading: members.isRequesting,
user: auth.user,
actions: global.actions,
members: members.data,
vender: vender.data || [], //
CameraKind: CameraKind.data || [],
CameraAbility: CameraAbility.data || [],
};
}

44
code/VideoAccess-VCMP/web/client/src/sections/offline/components/pushModal.less

@ -0,0 +1,44 @@
.myChoose{
background: #F9FBFF;
.myChooseButton{
height: 4px;
background: #0058C8;
}
}
.components-transfer-demo-selected-item {
.semi-icon-close {
visibility: hidden;
color: var(--semi-color-tertiary);
}
&:hover {
.semi-icon-close {
visibility: visible;
}
}
}
.components-transfer-demo-selected-item,
.components-transfer-demo-source-item {
height: 52px;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 12px;
&:hover {
background-color: var(--semi-color-fill-0);
}
.info {
margin-left: 8px;
flex-grow: 1;
}
.name {
font-size: 14px;
line-height: 20px;
}
.email {
font-size: 12px;
line-height: 16px;
color: var(--semi-color-text-2);
}
}

77
code/VideoAccess-VCMP/web/client/src/sections/offline/components/pushSideSheet.jsx

@ -0,0 +1,77 @@
import React, { useState, useRef, useEffect } from "react";
import { connect } from "react-redux";
import { Modal, Spin,Input,Collapse ,SideSheet,Tabs, TabPane} from "@douyinfe/semi-ui";
import moment from "moment";
import './pushSideSheet.less'
function pushSideSheet (props) {
const {
close,
actions,
pushData,//
journal//
} = props;
const { offline } = actions;
const [notesValue, setNotesValue] = useState('');//
//
useEffect(() => {
let timeList = []
for (let index = 0; index < journal.length; index++) {
timeList.push(
{
title:getTimeTitle(journal[index].time),
time:getTimeData(journal[index].time)
}
)
}
console.log('timeList',timeList);
}, []);
function getTimeTitle(date){
let year = moment(date).year()+'年'
let month = (moment(date).month()+1)>10?(moment(date).month()+1)+'月':'0'+(moment(date).month()+1)+'月'
return year+month
}
function getTimeData(date){
let day=moment(date).date()>10?moment(date).date()+'日':'0'+moment(date).date()+'日';
let hour=moment(date).hour()>10?moment(date).hour():'0'+moment(date).hour();
let minute=moment(date).minute()>10?moment(date).minute():'0'+moment(date).minute();
let second=moment(date).second()>10?moment(date).second():'0'+moment(date).second();
return day+' '+hour+':'+minute+':'+second
}
function sideSheetChange(){
close()
}
return (
<>
<SideSheet title={pushData.name} className='sideSheet' width={670} visible={true} onCancel={sideSheetChange}>
<Tabs type="line">
<TabPane tab="推送日志" itemKey="1">
<Collapse>
<Collapse.Panel header={<div style={{width:'100%',textAlign:'center'}}>11111111</div>} itemKey="1">
<p>Hi, bytedance dance dance. This is the docsite of Semi UI. </p>
</Collapse.Panel>
</Collapse>
</TabPane>
<TabPane tab="监听范围" itemKey="2">
22
</TabPane>
<TabPane tab="接收信息" itemKey="3">
33
</TabPane>
</Tabs>
</SideSheet>
</>
);
}
function mapStateToProps (state) {
const { auth, global, members, CameraKind, CameraAbility } = state;
return {
loading: members.isRequesting,
user: auth.user,
actions: global.actions,
CameraKind: CameraKind.data || [],
CameraAbility: CameraAbility.data || [],
};
}
export default connect(mapStateToProps)(pushSideSheet);

8
code/VideoAccess-VCMP/web/client/src/sections/offline/components/pushSideSheet.less

@ -0,0 +1,8 @@
.sideSheet{
.semi-tabs-tab{
font-size: 16px;
}
.semi-tabs-tab-active{
color: #1859C1;
}
}

328
code/VideoAccess-VCMP/web/client/src/sections/offline/containers/carrierpigeon.jsx

@ -1,14 +1,13 @@
import React, { useState, useEffect, useRef } from "react";
import { connect } from "react-redux";
import moment from "moment";
import { Button, Form, Table, Pagination, Skeleton, Popconfirm, Popover, Tag, } from "@douyinfe/semi-ui";
import { Button, Form, Table, Pagination, Skeleton, Popconfirm, SideSheet, Tag, } from "@douyinfe/semi-ui";
import "../style.less";
import { ApiTable } from "$utils";
import { Setup } from "$components";
import PushModal from "../components/pushModal";
import PushSideSheet from "../components/pushSideSheet";
// import SideSheets from "../components/sideSheet";
// import { skeletonScreen } from "../components/skeletonScreen";
// import { ReminderBox } from "../../../components/index";
export const accessType = [
{ name: "萤石云", key: "yingshi" },
@ -18,82 +17,86 @@ export const accessType = [
];
const Carrierpigeon = (props) => {
const { history, dispatch, actions, user, loading, equipmentWarehouseNvr } = props;
const { equipmentWarehouse } = actions;
const { history, dispatch, actions, user, loading, StatusPushList } = props;
const { offline } = actions;
const [setup, setSetup] = useState(false);
const [sideSheet, setSideSheet] = useState(false);
const [setupp, setSetupp] = useState([]);
const [venderList, setvenderList] = useState([]); //
const [query, setQuery] = useState({ limit: 10, page: 0 }); //
const [search, setearch] = useState({}); //
const [rowId, setRowId] = useState(); //id
const [reminder, setReminder] = useState(false); //
const [pigeonPush, setPigeonPush] = useState(false); //
const [pushTitle, setPushTitle] = useState(''); //
const api = useRef();
const searchData = useRef(search)
const limits = useRef(); //
const page = useRef(query.page);
const PIGEON = "pigeon";
const USER = "user" + props.user.id
const nvrRef = useRef(); //
const cameraList = useRef([]);//
const [sideSheetVisible, setSideSheetVisible] = useState(false);
const [pushData, setPushData] = useState({});
const [journal, setJournal] = useState([]);
const tableList = [//
{
title: '推送信息',
list: [
{ name: "策略类型", value: "PolicyType" },
{ name: "推送机制", value: "PushMechanism" },
{ name: "监听设备数量", value: "DevicesNumber" },
{ name: "累计推送次数", value: "PushNumber" },
{ name: "策略类型", value: "pushWay" },
{ name: "推送机制", value: "noticeWay" },
{ name: "监听设备数量", value: "logCount" },
{ name: "累计推送次数", value: "monitorCount" },
]
},
];
const noticeWayObj = {
'offline':'离线及时通知',
'online':'上线及时通知',
'timing':'定时统计',
}
useEffect(() => {
dispatch(actions.equipmentWarehouse.getVender()).then((res) => {
setvenderList(res.payload.data);
attribute(res.payload.data);
attribute();
dispatch(offline.getCameraListAll()).then((res) => {//
let mycameraList = res.payload.data
for (let index = 0; index < mycameraList.length; index++) {
mycameraList[index].label=mycameraList[index].name
mycameraList[index].key=index+1
mycameraList[index].value=String(mycameraList[index].id)
if(mycameraList[index].type=='cascade'){
mycameraList[index].color='#808FD3'
mycameraList[index].abbr='级联'
}
else if(mycameraList[index].type=='nvr'){
mycameraList[index].color='#F6D86F'
mycameraList[index].abbr='NVR'
}
else if(mycameraList[index].type=='ipc'){
mycameraList[index].color='#1859C1'
mycameraList[index].abbr='IPC'
}
else{
mycameraList[index].color='#57CBD3'
mycameraList[index].abbr='莹石'
}
}
cameraList.current=mycameraList
});
//
localStorage.getItem(PIGEON) == null
? localStorage.setItem(
PIGEON,
JSON.stringify(["PolicyType", "PushMechanism", "DevicesNumber", "PushNumber"])
JSON.stringify(['pushWay','noticeWay','logCount','monitorCount'])
)
: "";
}, []);
useEffect(() => {
equipmentGetNvr();
equipmentGetStatusPush();
}, [query, search]);
const equipmentGetNvr = () => {
const equipmentGetStatusPush = () => {
searchData.current = { ...query, ...search }
dispatch(equipmentWarehouse.getNvr(searchData.current)).then((res) => {
limits.current = res.payload.data.data.length
dispatch(offline.getStatusPush(searchData.current)).then((res) => {
limits.current = res.payload.data.length
});
}
function equipmentStatus (data) {
switch (data) {
case "email":
return "邮件通知"
case "note":
return "短信通知"
default:
return "未知"
}
}
function colorStatus (data) {
switch (data) {
case "ON":
return "#04B234"
case "ONLINE":
return "#04B234"
case "OFF":
return "rgba(0, 0, 0, 0.45)"
default:
return "#1859C1"
}
}
const columns = [
{
title: "序号",
@ -105,7 +108,6 @@ const Carrierpigeon = (props) => {
title: "策略名称",
dataIndex: "name",
render: (_, r, index) => {
console.log("r:" + r.name);
return r.name
},
},
@ -116,27 +118,67 @@ const Carrierpigeon = (props) => {
render: (_, row) => {
return (
<div style={{ display: "flex" }}>
<Button theme="borderless">
<PushModal
modalName="revise"
/>
</Button>
<Button
theme="borderless"
onClick={() => {
setSideSheet(true);
setPigeonPush(true);
// setTableNews(row);
setPushTitle('修改推送');
setPushData(row);
setRowId(row.id);
}}
>
禁用
修改
</Button>
{row.forbidden ? (
<Button
theme="borderless"
onClick={() => {
dispatch(
offline.putPushBanned(
{
configId: row.id,
forbidden: !row.forbidden,
},
row.forbidden
)
).then(() => {
equipmentGetStatusPush();
});
}}
>
启用
</Button>
) : (
<Popconfirm
title="禁用期间产生的通知将不会触达收信端"
arrowPointAtCenter={false}
showArrow={true}
position="topRight"
onConfirm={() => {
dispatch(
offline.putPushBanned(
{
configId: row.id,
forbidden: !row.forbidden,
},
row.forbidden
)
).then(() => {
equipmentGetStatusPush();
});
}}
>
<Button theme="borderless">禁用</Button>
</Popconfirm>
)}
<Popconfirm
title="是否确定删除?"
arrowPointAtCenter={false}
showArrow={true}
position="topRight"
onConfirm={() => {
dispatch(equipmentWarehouse.delNvr(row.id)).then(() => {
dispatch(offline.delPush(row.id)).then(() => {
if (page.current > 0 && limits.current < 2) {
setQuery({ limit: 10, page: page.current - 1 })
} else {
@ -147,10 +189,21 @@ const Carrierpigeon = (props) => {
>
<Button theme="borderless">删除</Button>
</Popconfirm>
<Button theme="borderless">
<Button onClick={()=>{
dispatch(offline.getPushCopy(row.id)).then(() => {
equipmentGetStatusPush();
});
}} theme="borderless">
复制
</Button>
<Button theme="borderless">
<Button onClick={()=>{
dispatch(offline.getPushLog(row.id)).then((res) => {
// equipmentGetStatusPush();
setJournal(res.payload.data);
setSideSheetVisible(true);
setPushData(row);
});
}} theme="borderless">
日志
</Button>
</div>
@ -160,7 +213,7 @@ const Carrierpigeon = (props) => {
];
//
function attribute (data) {
function attribute () {
const arr = localStorage.getItem(PIGEON)
? JSON.parse(localStorage.getItem(PIGEON))
: [];
@ -168,51 +221,41 @@ const Carrierpigeon = (props) => {
const column = [
{
title: "推送机制",
dataIndex: "venderId",
key: "PushMechanism",
dataIndex: "noticeWay",
key: "noticeWay",
render: (_, r, index) => {
let manufactorName = data.find((item) => item.id == r.venderId);
return manufactorName ? manufactorName.name : "";
let noticeWayValue=[]
for (let index = 0; index < r.noticeWay.length; index++) {
let val = r.noticeWay[index]
noticeWayValue.push(noticeWayObj[val])
}
let noticeWayString=noticeWayValue.join(';')
return noticeWayString;
},
},
{
title: "监听设备数量",
dataIndex: "DevicesNum",
key: "DevicesNumber",
dataIndex: "logCount",
key: "logCount",
render: (_, r, index) => {
return r.name
return r.logCount
},
},
{
title: "累计推送次数",
dataIndex: "PushNum",
key: "PushNumber",
dataIndex: "monitorCount",
key: "monitorCount",
render: (_, r, index) => {
return (r.name + '次')
return (r.monitorCount + '次')
},
},
{
title: "策略类型",
dataIndex: "size",
key: "PolicyType",
dataIndex: "pushWay",
key: "pushWay",
render: (_, r, index) => {
let status = r.gbNvr;
return (
<div>
<span
style={{
width: 8,
height: 8,
display: "inline-block",
borderRadius: "50%",
backgroundColor: status ? colorStatus(status.online) : "",
margin: "0 8px 0 0",
}}
/>
{status ? "邮件通知" : equipmentStatus(status.email)}
</div>
);
return r.pushWay=='email' ? '邮件通知' : '短信通知';
},
},
];
@ -224,32 +267,6 @@ const Carrierpigeon = (props) => {
}
setSetupp(columns);
}
//station
// function station (r, name, projects) {
// let data = []
// if (projects == "projects") {
// r.station.map((v) => {
// if (v.structure.projects.length > 0) {
// v.structure.projects.map((item) => data.push(item[name]))
// }
// })
// } else {
// r.station.map((v, index) => data.push(v.structure[name]))
// }
// let dataSet = [...(new Set(data))]
// return dataSet.length > 0 ? <Popover
// key="updateTime"
// position="top"
// content={
// dataSet.length > 1 ? <article style={{ padding: 12 }}>{dataSet.map((v, index) => <div key={index}>{v}</div>)}</article> : ""
// }
// >
// <Tag>{dataSet.length > 1 ? `${dataSet[0]}...` : dataSet.length > 0 ? dataSet[0] : ""}</Tag>
// </Popover> : ""
// }
//
const screen = {
width: 193,
@ -302,23 +319,12 @@ const Carrierpigeon = (props) => {
color: "#1859C1",
cursor: "pointer",
}}
>
<PushModal
modalName="add"
/>
{/* <NvrModal
modalName="add"
venderList={venderList}
nvrRef={nvrRef}
close={() => {
const remind = localStorage.getItem(USER);
console.log(remind)
if (!remind) {
setReminder(true)
}
equipmentGetNvr();
onClick={() => {
setPigeonPush(true);
setPushTitle('创建推送')
}}
/> */}
>
创建推送
</div>
</div>
</div>
@ -354,7 +360,7 @@ const Carrierpigeon = (props) => {
>
<Form.Input
label="策略名称:"
field="keyword"
field="name"
maxLength="36"
placeholder="请输入策略名称"
labelPosition="left"
@ -363,14 +369,14 @@ const Carrierpigeon = (props) => {
<Form.Select
label="策略类型:"
labelPosition="left"
field="PolicyType"
field="pushWay"
style={screen}
placeholder="全部"
showClear
>
<Form.Select.Option value="ALL">全部</Form.Select.Option>
<Form.Select.Option value="OFF">短信通知</Form.Select.Option>
<Form.Select.Option value="UNKONW">邮件通知</Form.Select.Option>
<Form.Select.Option value="">全部</Form.Select.Option>
<Form.Select.Option value="phone">短信通知</Form.Select.Option>
<Form.Select.Option value="email ">邮件通知</Form.Select.Option>
</Form.Select>
</Form>
<div
@ -469,12 +475,12 @@ const Carrierpigeon = (props) => {
</div>
<Skeleton
loading={loading}
// placeholder={skeletonScreen()}
active={true}
>
<Table
columns={setupp.filter((s) => s)}
dataSource={equipmentWarehouseNvr.data}
// dataSource={StatusPushList.data}
dataSource={StatusPushList}
bordered={false}
empty="暂无数据"
style={{
@ -492,10 +498,10 @@ const Carrierpigeon = (props) => {
}}
>
<span style={{ lineHeight: "30px" }}>
{equipmentWarehouseNvr.total}条策略
{StatusPushList.total}条策略
</span>
<Pagination
total={equipmentWarehouseNvr.total}
total={StatusPushList.total}
showSizeChanger
currentPage={query.page + 1}
pageSizeOpts={[10, 20, 30, 40]}
@ -512,54 +518,46 @@ const Carrierpigeon = (props) => {
tableList={tableList}
close={() => {
setSetup(false);
attribute(venderList);
attribute();
}}
/>
) : (
""
)}
{/* {sideSheet ? (
<SideSheets
visible={true}
{pigeonPush&&<PushModal
rowId={rowId}
accessType={accessType}
venderList={venderList}
title={pushTitle}
pushData={pushData}
cameraList={cameraList.current}
close={() => {
setSideSheet(false);
}}
/>
) : (
[]
)} */}
{/* <ReminderBox
title="是否继续添加NVR摄像头?"
wait="再等等"
toadd="去添加"
visible={reminder}
USER={USER}
onOk={() => {
history.push({ pathname: '/equipmentWarehouse/camera', query: { addNvr: true, serialNo: nvrRef.current.nvrNumber() } });
localStorage.setItem('vcmp_selected_sider', JSON.stringify("camera"))
setReminder(false)
setPigeonPush(false);
setRowId();
setPushData({})
equipmentGetStatusPush();
}}
/>}
{sideSheetVisible&&<PushSideSheet
pushData={pushData}
journal={journal}
close={() => {
setReminder(false)
setSideSheetVisible(false);
setPushData({})
}}
/> */}
/>}
</div>
</>
);
};
function mapStateToProps (state) {
const { auth, global, members, equipmentWarehouseNvr } = state;
const { auth, global, members, StatusPushList } = state;
return {
loading: equipmentWarehouseNvr.isRequesting && !equipmentWarehouseNvr.data,
loading: StatusPushList.isRequesting && !StatusPushList.data,
user: auth.user,
actions: global.actions,
members: members.data,
equipmentWarehouseNvr: equipmentWarehouseNvr.data || {},
StatusPushList: StatusPushList.data || [],
// StatusPushList: StatusPushList.data || {},
};
}

7
code/VideoAccess-VCMP/web/client/src/utils/webapi.js

@ -45,6 +45,13 @@ export const ApiTable = {
postStatusResolve:'status/resolve',//编辑解决方案
postStatusCustom:'status/custom',//自定义状态码释义
getStatusSimpleAll:'status/simple_all',//获取全部状态码简略信息
getCameraListAll:'camera/listAll',//获取所有摄像头信息
getStatusPush:'status/push',//获取推送配置
putSasdtatusPush:'sasdtatus/push',//编辑推送配置
delPush:'status/push/{configId}',//删除推送配置
putPushBanned:'status/push/banned',//禁用推送配置
getPushCopy:'status/push/{configId}/copy',//复制推送配置
getPushLog:'/status/push/{configId}/log',//获取推送记录
};
export const VideoServeApi = {

Loading…
Cancel
Save