After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 983 B |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 475 B |
@ -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: "" }, |
||||
|
}); |
||||
|
} |
@ -1,9 +1,8 @@ |
|||||
'use strict'; |
'use strict'; |
||||
|
|
||||
import * as statuscode from './statuscode' |
import * as statuscode from './statuscode' |
||||
// import * as camera from './camera'
|
import * as carrierpigeon from './carrierpigeon' |
||||
|
|
||||
export default { |
export default { |
||||
// ...statuscode,...camera
|
...statuscode,...carrierpigeon |
||||
...statuscode |
|
||||
} |
} |
@ -1,299 +1,583 @@ |
|||||
import React, { useState, useRef, useEffect, useImperativeHandle } from "react"; |
import React, { useState, useRef, useEffect } from "react"; |
||||
import { connect } from "react-redux"; |
import { connect } from "react-redux"; |
||||
import { Modal, Form, Row, Col, Spin } from "@douyinfe/semi-ui"; |
import { Modal, Form, Button,TimePicker,Transfer, Checkbox, Avatar } from "@douyinfe/semi-ui"; |
||||
import { IconTickCircle } from "@douyinfe/semi-icons"; |
import { IconClose } from '@douyinfe/semi-icons'; |
||||
|
import './pushModal.less' |
||||
import moment from "moment"; |
|
||||
|
|
||||
function pushModal (props) { |
function pushModal (props) { |
||||
const { modalName, pushRef } = props; |
const { |
||||
const { dispatch, actions, vender, close } = props; |
close, |
||||
const pushData = props.pushData || {}; //修改时传来的值 |
rowId, |
||||
const form = useRef(); |
dispatch, |
||||
const [visible, setVisible] = useState(false); //是否显示弹框 |
actions, |
||||
const [isloading, setloading] = useState(false); //是否显示loading |
title,//是编辑还是修改 |
||||
const [loadingTip, setloadingTip] = useState("获取中...请稍后..."); //loading tip的值 |
pushData,//数据值 |
||||
const [step, setstep] = useState("none"); //第几步 |
cameraList, |
||||
const [okText, setokText] = useState("测试校验"); //ok弹框text 右边 |
} = props; |
||||
const [cancelText, setcancelText] = useState("取消"); //取消弹框text 左边 |
const { offline } = actions;//接口 |
||||
const [formObj, setformObj] = useState(); //接口入参 |
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');//策略类型 |
||||
|
|
||||
function showDialog () { |
const pushWay = useRef('email');//策略类型 |
||||
//打开弹框 |
const emailList = useRef([]);//邮箱列表 |
||||
setVisible(true); |
const phoneList = useRef([]);//电话列表 |
||||
} |
|
||||
function positionForm (val) { |
const strategyList = [ |
||||
let zz = /^(-?\d+)(\.\d+)?$/; |
//循环摄像头列表 |
||||
if (!val) { |
{ |
||||
return "请输入或拾取高德经纬度坐标"; |
id: 1, |
||||
} else if (val.split(",").length != 2) { |
img: "/assets/images/background/icon_offLine.png", |
||||
return "请输入格式为116.354169,39.835452的经纬度坐标"; |
title: "离线即时通知", |
||||
} else if (!zz.test(val.split(",")[0])) { |
value: "offline", |
||||
return "只能填写数字"; |
}, |
||||
} else if (!zz.test(val.split(",")[1])) { |
{ |
||||
return "只能填写数字"; |
id: 2, |
||||
} else { |
img: "/assets/images/background/icon_online.png", |
||||
return ""; |
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 () { |
function handleOk () { |
||||
//点击弹框确定 右边按钮 |
let num = stepNum |
||||
if (step == "none") { |
if (num == 0) { |
||||
form.current |
form.current |
||||
.validate() |
.validate() |
||||
.then((values) => { |
.then((values) => { |
||||
//表单校验 |
setStepNum(num + 1) |
||||
console.log(values) |
setOkText('下一步') |
||||
let valuesObj = JSON.parse(JSON.stringify(values)); |
setCancelText('上一步') |
||||
valuesObj.longitude = values.position.split(",")[0]; |
if(showList.indexOf(true)>-1){ |
||||
valuesObj.latitude = values.position.split(",")[1]; |
setRightDisabled(false) |
||||
delete valuesObj.position; |
} |
||||
if (pushData.id) { |
else{ |
||||
valuesObj.id = pushData.id; |
setRightDisabled(true) |
||||
} |
} |
||||
var front = new moment(); //验证前时间 |
|
||||
setloading(true); |
|
||||
dispatch( |
|
||||
actions.equipmentWarehouse.getCheck({ |
|
||||
serialNo: valuesObj.serialNo, |
|
||||
}) |
|
||||
).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 |
|
||||
); |
|
||||
} else { |
|
||||
setTimeout( |
|
||||
() => { |
|
||||
setloadingTip("校验失败"); |
|
||||
setTimeout(() => { |
|
||||
setstep("none"); |
|
||||
setloading(false); |
|
||||
setokText("测试校验"); |
|
||||
setcancelText("取消"); |
|
||||
setloadingTip("获取中...请稍后..."); |
|
||||
}, 1000); |
|
||||
}, |
|
||||
duration > 2000 ? 0 : 2000 - duration |
|
||||
); |
|
||||
} |
|
||||
}); |
|
||||
setformObj(valuesObj); |
|
||||
}) |
}) |
||||
.catch((errors) => { |
} |
||||
//表单校验失败 |
else if (num == 1) { |
||||
console.log("errors", errors); |
setStepNum(num + 1) |
||||
}); |
setOkText('下一步') |
||||
} else { |
setCancelText('上一步') |
||||
dispatch(actions.equipmentWarehouse.addchangepush(formObj)).then((res) => { |
if(chooseCameraList.length>0){ |
||||
setVisible(false); |
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) => { |
||||
close(); |
close(); |
||||
}); |
}) |
||||
} |
} |
||||
} |
} |
||||
function handleAfterClose () { |
|
||||
//在关闭之后 |
|
||||
setstep("none"); |
|
||||
setokText("测试校验"); |
|
||||
setcancelText("取消"); |
|
||||
} |
|
||||
function handleCancel () { |
function handleCancel () { |
||||
//点击弹框取消 左边按钮 |
//点击弹框取消 左边按钮 |
||||
if (step == "none") { |
let num = stepNum |
||||
setVisible(false); |
if (num == 0) { |
||||
} else { |
close(); |
||||
setstep("none"); |
} |
||||
setokText("测试校验"); |
else if (num == 1) { |
||||
setcancelText("取消"); |
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 handleLocation () { |
function toTimePicker(e){//阻止定时事件冒泡 |
||||
//高德经纬度 |
e.stopPropagation() |
||||
window.open("https://lbs.amap.com/tools/picker", "_blank"); |
} |
||||
|
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> |
||||
|
); |
||||
|
} |
||||
|
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> |
||||
|
); |
||||
|
} |
||||
|
function customFilter(sugInput, item){//自定义筛选逻辑, 当为 false 时,不展示搜索框 |
||||
|
return item.value.includes(sugInput) || item.label.includes(sugInput); |
||||
|
} |
||||
|
function CameraChooseList(id, items){ |
||||
|
if(id.length>0){ |
||||
|
setRightDisabled(false) |
||||
|
} |
||||
|
else{ |
||||
|
setRightDisabled(true) |
||||
|
} |
||||
|
setChooseCameraList(id) |
||||
} |
} |
||||
useImperativeHandle(pushRef, () => ({ |
|
||||
//传给父组件方法 |
|
||||
//aa即为子组件暴露给父组件的方法 |
|
||||
pushNumber: () => formObj.serialNo |
|
||||
})); |
|
||||
return ( |
return ( |
||||
<> |
<> |
||||
<div onClick={showDialog}>{modalName == "add" ? "创建推送" : "修改"}</div> |
|
||||
<Modal |
<Modal |
||||
title={modalName == "add" ? "创建推送" : "修改"} |
title={title} |
||||
okText={okText} |
visible={true} |
||||
cancelText={cancelText} //取消按钮 |
width={835} |
||||
visible={visible} |
onCancel={handleClose} |
||||
onOk={handleOk} |
footer={ |
||||
width={782} |
<div> |
||||
height={720} |
<Button type="primary" onClick={handleCancel}> |
||||
afterClose={handleAfterClose} |
{cancelText} |
||||
onCancel={handleCancel} |
</Button> |
||||
|
<Button theme='solid' disabled={rightDisabled} type="primary" onClick={handleOk}> |
||||
|
{okText} |
||||
|
</Button> |
||||
|
</div> |
||||
|
} |
||||
> |
> |
||||
<Spin tip={loadingTip} spinning={isloading}> |
<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="right" |
||||
|
labelWidth="90px" |
||||
|
onValueChange={(values, field) => formChange(values, field)} |
||||
|
getFormApi={(formApi) => (form.current = formApi)} |
||||
|
> |
||||
|
<div style={{ display: 'flex' }}> |
||||
|
<div> |
||||
|
<Form.Input |
||||
|
maxLength="16" |
||||
|
field="name" |
||||
|
label="策略名称:" |
||||
|
initValue={mypushData.name || ""} |
||||
|
placeholder="请输入策略名称,不超过16个字符" |
||||
|
style={{ width: 307 }} |
||||
|
rules={[{ required: true, message: "请输入策略名称,不超过16个字符" }]} |
||||
|
/> |
||||
|
</div> |
||||
|
<div style={{ marginLeft: 21 }}> |
||||
|
<Form.Select |
||||
|
label="策略类型:" |
||||
|
field="pushWay" |
||||
|
initValue={mypushData.pushWay || 'email'} |
||||
|
placeholder="请选择策略类型" |
||||
|
style={{ width: 210 }} |
||||
|
> |
||||
|
<Form.Select.Option value='email'> |
||||
|
邮件推送 |
||||
|
</Form.Select.Option> |
||||
|
<Form.Select.Option value='phone'> |
||||
|
短信推送 |
||||
|
</Form.Select.Option> |
||||
|
</Form.Select> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div> |
||||
|
<Form.TagInput |
||||
|
addOnBlur={true} |
||||
|
label='接收信息:' |
||||
|
field="receiver" |
||||
|
initValue={mypushData.receiverList||[]} |
||||
|
placeholder='请输入接收信息' |
||||
|
style={{ width: 630 }} |
||||
|
validate={positionForm} |
||||
|
rules={[{ required: true, message: "请输入接收信息" }]} |
||||
|
/> |
||||
|
</div> |
||||
|
</Form> |
||||
|
<div style={{ color: 'rgba(0,0,0,0.45)', fontSize: 12, textAlign: 'right' }}> |
||||
|
敲击回车键后,输入内容将成为标签 |
||||
|
</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 == "1" ? "block" : "none", }}> |
||||
<div |
<div |
||||
style={{ |
style={{ display: "flex", alignItems: "center",justifyContent: 'space-between', height: 102 }} |
||||
paddingLeft: 16, |
|
||||
display: step == "none" ? "block" : "none", |
|
||||
}} |
|
||||
> |
> |
||||
<Form |
{showstrategyListList.current.map((item, index) => ( |
||||
allowEmpty |
<div |
||||
labelPosition="left" |
key={item.id} |
||||
labelAlign="left" |
style={{ |
||||
labelWidth="90px" |
width: 215, |
||||
onValueChange={(values) => console.log(values)} |
height: 102, |
||||
getFormApi={(formApi) => (form.current = formApi)} |
border: |
||||
> |
showList[index] |
||||
<Row> |
? "1px solid #1859C1" |
||||
<Col span={12}> |
: "1px solid #F9F9F9", |
||||
<Form.Input |
borderRadius: 3, |
||||
maxLength="39" |
display: "flex", |
||||
field="serialNo" |
boxShadow: '0px 2px 4px 0px rgba(231,231,231,0.5)', |
||||
label="设备编号:" |
cursor: "pointer", |
||||
initValue={pushData.serialNo || ""} |
position: "relative", |
||||
placeholder="请输入设备编号" |
}} |
||||
style={{ width: 149 }} |
onClick={() => twohandleChoose(item.id,index)} |
||||
rules={[{ required: true, message: "请输入设备编号" }]} |
onMouseOver={() => twohandleMouseOver(item.id,index)} |
||||
/> |
> |
||||
</Col> |
<img src={item.img} style={{width:56,height:56,margin:'23px 20px'}} alt="设置" /> |
||||
<Col span={12}> |
{ |
||||
<Form.InputNumber |
item.id==3?( |
||||
formatter={(value) => `${value}`.replace(/\D/g, "")} |
<div> |
||||
hideButtons={true} |
<div style={{marginTop:22,color: '#34383E'}}> |
||||
maxLength="15" |
{item.title} |
||||
field="regionCode" |
</div> |
||||
label="行政区区码:" |
<div style={{marginTop:10}} |
||||
initValue={pushData.regionCode || ""} |
onClick={(e)=>toTimePicker(e)}> |
||||
placeholder="请输入行政区区码" |
<TimePicker |
||||
style={{ width: 149 }} |
showClear={false} |
||||
/> |
format={'HH:mm'} |
||||
</Col> |
placeholder="时间" |
||||
<Col span={24}> |
minuteStep={5} |
||||
<Form.Input |
defaultValue={'18:00'} |
||||
maxLength="36" |
onChange={timeChange} |
||||
field="name" |
value={timevalue} |
||||
label="设备名称:" |
style={{ width: 108 }}/> |
||||
initValue={pushData.name || ""} |
</div> |
||||
placeholder="请输入设备名称" |
</div> |
||||
style={{ width: 421 }} |
):( |
||||
rules={[ |
<div style={{marginTop:48,color: '#34383E'}}> |
||||
{ |
{item.title} |
||||
required: true, |
</div> |
||||
message: "请输入设备名称、常用项目或位置定义", |
) |
||||
}, |
} |
||||
]} |
{showList[index] ? ( |
||||
/> |
|
||||
</Col> |
|
||||
<Col span={24}> |
|
||||
<Form.Select |
|
||||
label="设备厂家:" |
|
||||
field="venderId" |
|
||||
initValue={pushData.venderId || null} |
|
||||
placeholder="请选择设备厂家" |
|
||||
style={{ width: 421 }} |
|
||||
rules={[{ required: true, message: "请选择设备厂家" }]} |
|
||||
> |
|
||||
{vender.map((item, index) => ( |
|
||||
<Form.Select.Option key={index} value={item.id}> |
|
||||
{item.name} |
|
||||
</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 }} |
|
||||
validate={positionForm} |
|
||||
rules={[ |
|
||||
{ |
|
||||
required: true, |
|
||||
message: "请输入或拾取高德经纬度坐标", |
|
||||
}, |
|
||||
]} |
|
||||
/> |
|
||||
<div |
<div |
||||
style={{ |
style={{ |
||||
width: 32, |
position: "absolute", |
||||
height: 32, |
top: "-3px", |
||||
background: "#1859C1", |
right: "-6px", |
||||
marginLeft: 4, |
|
||||
display: "flex", |
|
||||
justifyContent: "center", |
|
||||
alignItems: "center", |
|
||||
cursor: "pointer", |
|
||||
marginTop: 12, |
|
||||
borderRadius: 3 + "px", |
|
||||
}} |
}} |
||||
onClick={handleLocation} |
|
||||
> |
> |
||||
<img |
<img |
||||
src="../../../assets/images/background/location.png" |
src="/assets/images/background/noteTopChoose.png" |
||||
width={16} |
alt="1" |
||||
height={20} |
style={{width:49,height:34}} |
||||
/> |
/> |
||||
</div> |
</div> |
||||
</Col> |
) : ( |
||||
</Row> |
"" |
||||
</Form> |
)} |
||||
|
</div> |
||||
|
))} |
||||
</div> |
</div> |
||||
|
<div style={{ display: "flex", alignItems: "center",justifyContent: 'space-between'}}> |
||||
<div style={{ height: 224, display: step }}> |
{showstrategyListList.current.map((item, index) => ( |
||||
<div |
<div style={{width:215,height:15,textAlign: 'center'}} key={index}> |
||||
style={{ |
{ |
||||
paddingTop: 50, |
noticeNum==index?( |
||||
display: "flex", |
<img |
||||
justifyContent: "center", |
src="/assets/images/background/triangle.png" |
||||
}} |
alt="1" |
||||
> |
style={{width:14,height:12}} |
||||
<IconTickCircle style={{ color: "#04B234", fontSize: 60 }} /> |
/> |
||||
</div> |
):'' |
||||
<div |
} |
||||
style={{ |
</div> |
||||
marginTop: 20, |
))} |
||||
display: "flex", |
</div> |
||||
justifyContent: "center", |
<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> |
</div> |
||||
</Spin> |
<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> |
||||
</Modal> |
</Modal> |
||||
</> |
</> |
||||
); |
); |
||||
} |
} |
||||
|
|
||||
function mapStateToProps (state) { |
function mapStateToProps (state) { |
||||
const { auth, global, members, vender } = state; |
const { auth, global, members, CameraKind, CameraAbility } = state; |
||||
return { |
return { |
||||
loading: members.isRequesting, |
loading: members.isRequesting, |
||||
user: auth.user, |
user: auth.user, |
||||
actions: global.actions, |
actions: global.actions, |
||||
members: members.data, |
CameraKind: CameraKind.data || [], |
||||
vender: vender.data || [], //设备厂家 |
CameraAbility: CameraAbility.data || [], |
||||
}; |
}; |
||||
} |
} |
||||
|
|
||||
export default connect(mapStateToProps)(pushModal); |
export default connect(mapStateToProps)(pushModal); |
@ -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); |
||||
|
} |
||||
|
} |
@ -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); |
@ -0,0 +1,8 @@ |
|||||
|
.sideSheet{ |
||||
|
.semi-tabs-tab{ |
||||
|
font-size: 16px; |
||||
|
} |
||||
|
.semi-tabs-tab-active{ |
||||
|
color: #1859C1; |
||||
|
} |
||||
|
} |