3 changed files with 1309 additions and 24 deletions
@ -0,0 +1,138 @@ |
|||||
|
import React, { useState, useEffect } from "react"; |
||||
|
import { |
||||
|
Modal, |
||||
|
CheckboxGroup, |
||||
|
Checkbox, |
||||
|
} from "@douyinfe/semi-ui"; |
||||
|
|
||||
|
function Setup(props) { |
||||
|
const { |
||||
|
visible, |
||||
|
close, |
||||
|
CODE,//错误码 |
||||
|
PIGEON,//信鸽 |
||||
|
pigeonSetup, |
||||
|
} = props; |
||||
|
const [check, setCheck] = useState([]); |
||||
|
|
||||
|
const checkboxcss = { width: "25%", height: 16, margin: "0 0 20px 0" }; |
||||
|
|
||||
|
useEffect(() => { |
||||
|
//获取是否勾选信息 |
||||
|
const codeItem = localStorage.getItem(CODE); |
||||
|
const pigeonItem = localStorage.getItem(PIGEON); |
||||
|
if (pigeonSetup) { |
||||
|
setCheck(pigeonItem ? JSON.parse(pigeonItem) : []); |
||||
|
} else { |
||||
|
setCheck(codeItem ? JSON.parse(codeItem) : []); |
||||
|
} |
||||
|
ischeck(); |
||||
|
}, []); |
||||
|
|
||||
|
const equipmentCode = [//状态码管理 |
||||
|
{ name: "常规解决方案", value: "manufactor" }, |
||||
|
{ name: "状态频率", value: "accountNumber" }, |
||||
|
]; |
||||
|
const equipmentCarrierpigeon = [//信鸽服务 |
||||
|
{ name: "策略类型", value: "manufactor" }, |
||||
|
{ name: "推送机制", value: "type" }, |
||||
|
{ name: "监听设备数量", value: "state" }, |
||||
|
{ name: "累计推送次数", value: "support" }, |
||||
|
]; |
||||
|
|
||||
|
function ischeck(value) { |
||||
|
if (check.length >= 8) { |
||||
|
if (check.includes(value)) { |
||||
|
return false; |
||||
|
} else { |
||||
|
return true; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return ( |
||||
|
<Modal |
||||
|
title={ |
||||
|
<div> |
||||
|
表格属性设置 |
||||
|
<span |
||||
|
style={{ |
||||
|
width: 50, |
||||
|
lineHeight: "19px", |
||||
|
display: "inline-block", |
||||
|
|
||||
|
color: "white", |
||||
|
textAlign: "center", |
||||
|
marginLeft: 6, |
||||
|
background: |
||||
|
check.length == 8 |
||||
|
? "rgba(40, 123, 255, 1)" |
||||
|
: "rgba(176, 176, 176, 1)", |
||||
|
}} |
||||
|
> |
||||
|
{check.length}/8 |
||||
|
</span> |
||||
|
</div> |
||||
|
} |
||||
|
visible={visible} |
||||
|
style={{ width: 600 }} |
||||
|
onOk={() => { |
||||
|
pigeonSetup |
||||
|
? localStorage.setItem(PIGEON, JSON.stringify(check)) |
||||
|
: localStorage.setItem(CODE, JSON.stringify(check)); |
||||
|
close(); |
||||
|
}} |
||||
|
onCancel={() => { |
||||
|
close(); |
||||
|
}} |
||||
|
> |
||||
|
<CheckboxGroup |
||||
|
style={{ width: "100%", fontSize: 14 }} |
||||
|
key="primary1" |
||||
|
direction="horizontal" |
||||
|
defaultValue={check} |
||||
|
aria-label="表格属性设置" |
||||
|
onChange={(check) => { |
||||
|
setCheck(check); |
||||
|
ischeck(); |
||||
|
}} |
||||
|
> |
||||
|
<div |
||||
|
style={{ |
||||
|
width: 550, |
||||
|
border: "1px solid #EAEAEA", |
||||
|
padding: "0px 5px", |
||||
|
borderRadius: 4, |
||||
|
marginBottom: "20px", |
||||
|
}} |
||||
|
> |
||||
|
<div |
||||
|
style={{ |
||||
|
borderBottom: "1px solid #EAEAEA", |
||||
|
marginLeft: "10px", |
||||
|
padding: "8px 0px", |
||||
|
}} |
||||
|
> |
||||
|
{pigeonSetup?'推送信息':'状态码信息'} |
||||
|
</div> |
||||
|
<div style={{ padding: "15px 12px", width: 530 }}> |
||||
|
{(pigeonSetup ? equipmentCarrierpigeon : equipmentCode).map((item) => { |
||||
|
return ( |
||||
|
<Checkbox |
||||
|
key={item.value} |
||||
|
value={item.value} |
||||
|
style={checkboxcss} |
||||
|
disabled={ischeck(item.value)} |
||||
|
> |
||||
|
{item.name} |
||||
|
</Checkbox> |
||||
|
); |
||||
|
})} |
||||
|
</div> |
||||
|
</div> |
||||
|
</CheckboxGroup> |
||||
|
</Modal> |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
export default Setup; |
@ -1,20 +1,594 @@ |
|||||
import React, { useEffect } from 'react'; |
import React, { useState, useEffect, useRef } from "react"; |
||||
import { connect } from 'react-redux'; |
import { connect } from "react-redux"; |
||||
import { Coming } from '$components' |
import moment from "moment"; |
||||
import '../style.less' |
import { Button, Form, Table, Pagination, Skeleton, Popconfirm, Popover, Tag, } from "@douyinfe/semi-ui"; |
||||
|
import "../style.less"; |
||||
|
import { ApiTable } from "$utils"; |
||||
|
import Setup from "../components/setup"; |
||||
|
// import SideSheets from "../components/sideSheet"; |
||||
|
// import { skeletonScreen } from "../components/skeletonScreen"; |
||||
|
// import { ReminderBox } from "../../../components/index"; |
||||
|
|
||||
|
export const accessType = [ |
||||
|
{ name: "萤石云", key: "yingshi" }, |
||||
|
{ name: "NVR", key: "nvr" }, |
||||
|
{ name: "IPC", key: "ipc" }, |
||||
|
{ name: "级联", key: "cascade" }, |
||||
|
]; |
||||
|
|
||||
const Carrierpigeon = (props) => { |
const Carrierpigeon = (props) => { |
||||
|
const { history, dispatch, actions, user, loading, equipmentWarehouseNvr } = props; |
||||
|
const { equipmentWarehouse } = 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 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(); //获取子组件的设备编号 |
||||
|
|
||||
return ( |
useEffect(() => { |
||||
<Coming /> |
dispatch(actions.equipmentWarehouse.getVender()).then((res) => { |
||||
) |
setvenderList(res.payload.data); |
||||
} |
attribute(res.payload.data); |
||||
|
}); |
||||
|
//初始化表格显示设置 |
||||
|
localStorage.getItem(PIGEON) == null |
||||
|
? localStorage.setItem( |
||||
|
PIGEON, |
||||
|
JSON.stringify(["manufactor", "type","state","support"]) |
||||
|
) |
||||
|
: ""; |
||||
|
}, []); |
||||
|
|
||||
|
useEffect(() => { |
||||
|
equipmentGetNvr(); |
||||
|
}, [query, search]); |
||||
|
|
||||
|
const equipmentGetNvr = () => { |
||||
|
searchData.current = { ...query, ...search } |
||||
|
dispatch(equipmentWarehouse.getNvr(searchData.current)).then((res) => { |
||||
|
limits.current = res.payload.data.data.length |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function equipmentStatus (data) { |
||||
|
switch (data) { |
||||
|
case "ON": |
||||
|
return "在线" |
||||
|
case "ONLINE": |
||||
|
return "在线" |
||||
|
case "OFF": |
||||
|
return "离线" |
||||
|
default: |
||||
|
return "未知" |
||||
|
}F |
||||
|
} |
||||
|
|
||||
|
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: "序号", |
||||
|
render: (_, record, index) => { |
||||
|
return index + 1; |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: "设备名称", |
||||
|
dataIndex: "name", |
||||
|
render: (_, r, index) => { |
||||
|
console.log(r); |
||||
|
return r.name |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: "SIP地址", |
||||
|
dataIndex: "owner", |
||||
|
render: (_, r, index) => { |
||||
|
return r?.gbNvr?.sipip |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: "操作", |
||||
|
width: "20%", |
||||
|
dataIndex: "", |
||||
|
render: (_, row) => { |
||||
|
return ( |
||||
|
<div style={{ display: "flex" }}> |
||||
|
<Button theme="borderless"> |
||||
|
启用 |
||||
|
</Button> |
||||
|
<Button |
||||
|
theme="borderless" |
||||
|
onClick={() => { |
||||
|
setSideSheet(true); |
||||
|
setRowId(row.id); |
||||
|
}} |
||||
|
> |
||||
|
释义 |
||||
|
</Button> |
||||
|
<Popconfirm |
||||
|
title="删除NVR会删除端口下的所有摄像头,是否确定删除?" |
||||
|
arrowPointAtCenter={false} |
||||
|
showArrow={true} |
||||
|
position="topRight" |
||||
|
onConfirm={() => { |
||||
|
dispatch(equipmentWarehouse.delNvr(row.id)).then(() => { |
||||
|
if (page.current > 0 && limits.current < 2) { |
||||
|
setQuery({ limit: 10, page: page.current - 1 }) |
||||
|
} else { |
||||
|
setQuery({ limit: 10, page: page.current }) |
||||
|
} |
||||
|
}); |
||||
|
}} |
||||
|
> |
||||
|
<Button theme="borderless">方案</Button> |
||||
|
</Popconfirm> |
||||
|
</div> |
||||
|
); |
||||
|
}, |
||||
|
}, |
||||
|
]; |
||||
|
|
||||
|
//获取表格属性设置 |
||||
|
function attribute (data) { |
||||
|
const arr = localStorage.getItem(PIGEON) |
||||
|
? JSON.parse(localStorage.getItem(PIGEON)) |
||||
|
: []; |
||||
|
|
||||
|
const column = [ |
||||
|
{ |
||||
|
title: "设备厂家", |
||||
|
dataIndex: "venderId", |
||||
|
key: "manufactor", |
||||
|
render: (_, r, index) => { |
||||
|
let manufactorName = data.find((item) => item.id == r.venderId); |
||||
|
return manufactorName ? manufactorName.name : ""; |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: "添加账号", |
||||
|
dataIndex: "createUserId", |
||||
|
key: "accountNumber", |
||||
|
render: (_, r, index) => { |
||||
|
return r?.createUser?.name |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: "通道数", |
||||
|
dataIndex: "channelCount", |
||||
|
key: "passageway", |
||||
|
}, |
||||
|
{ |
||||
|
title: "端口", |
||||
|
dataIndex: "port", |
||||
|
key: "port", |
||||
|
}, |
||||
|
{ |
||||
|
title: "设备状态", |
||||
|
dataIndex: "size", |
||||
|
key: "state", |
||||
|
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.online) : ""} |
||||
|
</div> |
||||
|
); |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: "创建时间", |
||||
|
dataIndex: "createTime", |
||||
|
key: "time", |
||||
|
render: (_, r, index) => { |
||||
|
return moment(r.createTime).format("YYYY-MM-DD HH:MM:SS"); |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: "项目名称", |
||||
|
dataIndex: "", |
||||
|
key: "name", |
||||
|
render: (_, r, index) => { |
||||
|
return r.station.length == 0 |
||||
|
? "" |
||||
|
: station(r, "name", "projects") |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: "pcode", |
||||
|
dataIndex: "", |
||||
|
key: "pcode", |
||||
|
render: (_, r, index) => { |
||||
|
return r.station.length == 0 |
||||
|
? "" |
||||
|
: station(r, "url", "projects") |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: "结构物", |
||||
|
dataIndex: "", |
||||
|
key: "structure", |
||||
|
render: (_, r, index) => { |
||||
|
return r.station.length == 0 |
||||
|
? "" |
||||
|
: station(r, "name") |
||||
|
}, |
||||
|
}, |
||||
|
]; |
||||
|
for (let i = 0; i < arr.length; i++) { |
||||
|
let colum = column.filter((item) => { |
||||
|
return item.key === arr[i]; |
||||
|
}); |
||||
|
columns.splice(i + 2, 0, colum[0]); |
||||
|
} |
||||
|
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, |
||||
|
marginRight: 20, |
||||
|
marginBottom: 16, |
||||
|
color: "rgba(0, 0, 0, 0.65)", |
||||
|
}; |
||||
|
|
||||
|
return ( |
||||
|
<> |
||||
|
<div> |
||||
|
<video |
||||
|
id="nvrBanner" |
||||
|
autoPlay |
||||
|
loop |
||||
|
muted |
||||
|
style={{ width: "100%", objectFit: "cover", height: 171 }} |
||||
|
src="/assets/video/nvr_banner.mp4" |
||||
|
type="video/mp4" |
||||
|
/> |
||||
|
<div style={{ position: "absolute", top: 12 }}> |
||||
|
<div |
||||
|
style={{ |
||||
|
fontSize: 22, |
||||
|
paddingTop: 15, |
||||
|
marginLeft: 21, |
||||
|
}} |
||||
|
> |
||||
|
信鸽服务 |
||||
|
</div> |
||||
|
<div |
||||
|
style={{ |
||||
|
fontSize: 14, |
||||
|
paddingTop: 18, |
||||
|
marginLeft: 20, |
||||
|
}} |
||||
|
> |
||||
|
对设备状态变更进行监听,通过短信或邮件通知指定人员 |
||||
|
</div> |
||||
|
<div |
||||
|
style={{ |
||||
|
fontSize: 14, |
||||
|
marginTop: 28, |
||||
|
marginLeft: 21, |
||||
|
width: 89, |
||||
|
height: 32, |
||||
|
lineHeight: "32px", |
||||
|
textAlign: "center", |
||||
|
backgroundColor: "#D9EAFF", |
||||
|
color: "#1859C1", |
||||
|
cursor: "pointer", |
||||
|
}} |
||||
|
> |
||||
|
创建推送 |
||||
|
{/* <NvrModal |
||||
|
modalName="add" |
||||
|
venderList={venderList} |
||||
|
nvrRef={nvrRef} |
||||
|
close={() => { |
||||
|
const remind = localStorage.getItem(USER); |
||||
|
console.log(remind) |
||||
|
if (!remind) { |
||||
|
setReminder(true) |
||||
|
} |
||||
|
equipmentGetNvr(); |
||||
|
}} |
||||
|
/> */} |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div |
||||
|
style={{ |
||||
|
width: "100%", |
||||
|
background: "#FFFFFF", |
||||
|
borderRadius: 3, |
||||
|
padding: "8px 20px", |
||||
|
marginTop: 20, |
||||
|
}} |
||||
|
> |
||||
|
<div |
||||
|
style={{ |
||||
|
height: 22, |
||||
|
fontSize: 16, |
||||
|
fontFamily: "PingFangSC-Medium, PingFang SC", |
||||
|
fontWeight: "bold", |
||||
|
color: " rgba(0, 0, 0, 0.85)", |
||||
|
lineHeight: "22px", |
||||
|
marginBottom: 16, |
||||
|
}} |
||||
|
> |
||||
|
筛选条件 |
||||
|
</div> |
||||
|
<div style={{ display: "flex" }}> |
||||
|
<Form |
||||
|
onSubmit={(values) => console.log(values)} |
||||
|
// onValueChange={values=>console.log(values)} |
||||
|
getFormApi={(formApi) => (api.current = formApi)} |
||||
|
layout="horizontal" |
||||
|
style={{ position: "relative", width: "100%", flex: 1 }} |
||||
|
> |
||||
|
<Form.Input |
||||
|
label="策略名称:" |
||||
|
field="keyword" |
||||
|
maxLength="36" |
||||
|
placeholder="请输入策略名称" |
||||
|
labelPosition="left" |
||||
|
style={screen} |
||||
|
/> |
||||
|
<Form.Select |
||||
|
label="策略类型:" |
||||
|
labelPosition="left" |
||||
|
field="state" |
||||
|
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> |
||||
|
</Form> |
||||
|
<div |
||||
|
style={{ |
||||
|
width: 150, |
||||
|
display: "flex", |
||||
|
justifyContent: "flex-end", |
||||
|
alignItems: "flex-end", |
||||
|
}} |
||||
|
> |
||||
|
<Button |
||||
|
theme="solid" |
||||
|
type="primary" |
||||
|
style={{ |
||||
|
width: 65, |
||||
|
height: 30, |
||||
|
borderRadius: 3, |
||||
|
marginBottom: 20, |
||||
|
marginRight: 20, |
||||
|
}} |
||||
|
onClick={() => { |
||||
|
api.current.validate().then((v) => { |
||||
|
setearch(v); |
||||
|
setQuery({ limit: 10, page: 0 }) |
||||
|
}); |
||||
|
}} |
||||
|
> |
||||
|
搜素 |
||||
|
</Button> |
||||
|
<Button |
||||
|
theme="light" |
||||
|
type="primary" |
||||
|
style={{ |
||||
|
width: 65, |
||||
|
height: 30, |
||||
|
backGround: "#FFFFFF", |
||||
|
borderRadius: 3, |
||||
|
border: "1px solid #D9D9D9", |
||||
|
marginBottom: 20, |
||||
|
}} |
||||
|
onClick={() => { |
||||
|
api.current.reset(); |
||||
|
setearch({}); |
||||
|
setQuery({ limit: 10, page: 0 }) |
||||
|
}} |
||||
|
> |
||||
|
重置 |
||||
|
</Button> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div style={{ background: "#FFFFFF", marginTop: 5 }}> |
||||
|
<div |
||||
|
style={{ |
||||
|
width: "100%", |
||||
|
display: "flex", |
||||
|
justifyContent: "space-between", |
||||
|
padding: "13px 20px", |
||||
|
}} |
||||
|
> |
||||
|
<div |
||||
|
style={{ |
||||
|
width: 64, |
||||
|
height: 22, |
||||
|
fontSize: 16, |
||||
|
fontfAmily: "PingFangSC-Medium, PingFang SC", |
||||
|
fontWeight: "bold", |
||||
|
color: "rgba(0, 0, 0, 0.85)", |
||||
|
lineHeight: "22px", |
||||
|
}} |
||||
|
> |
||||
|
策略详情 |
||||
|
</div> |
||||
|
<div> |
||||
|
<Button |
||||
|
style={{ |
||||
|
width: 32, |
||||
|
height: 32, |
||||
|
background: "#D9D9D9", |
||||
|
borderadius: 3, |
||||
|
marginRight: 20, |
||||
|
}} |
||||
|
type="primary" |
||||
|
key="primary" |
||||
|
onClick={() => { |
||||
|
setSetup(true); |
||||
|
}} |
||||
|
> |
||||
|
<img |
||||
|
src="/assets/images/background/setup.png" |
||||
|
alt="设置" |
||||
|
style={{ width: 18, height: 18 }} |
||||
|
/> |
||||
|
</Button> |
||||
|
</div> |
||||
|
</div> |
||||
|
<Skeleton |
||||
|
loading={loading} |
||||
|
// placeholder={skeletonScreen()} |
||||
|
active={true} |
||||
|
> |
||||
|
<Table |
||||
|
columns={setupp.filter((s) => s)} |
||||
|
dataSource={equipmentWarehouseNvr.data} |
||||
|
bordered={false} |
||||
|
empty="暂无数据" |
||||
|
style={{ |
||||
|
padding: "0px 20px", |
||||
|
}} |
||||
|
pagination={false} |
||||
|
/> |
||||
|
</Skeleton> |
||||
|
|
||||
|
<div |
||||
|
style={{ |
||||
|
display: "flex", |
||||
|
justifyContent: "flex-end", |
||||
|
padding: "20px 20px", |
||||
|
}} |
||||
|
> |
||||
|
<span style={{ lineHeight: "30px" }}> |
||||
|
共{equipmentWarehouseNvr.total}个设备 |
||||
|
</span> |
||||
|
<Pagination |
||||
|
total={equipmentWarehouseNvr.total} |
||||
|
showSizeChanger |
||||
|
currentPage={query.page + 1} |
||||
|
pageSizeOpts={[10, 20, 30, 40]} |
||||
|
onChange={(currentPage, pageSize) => { |
||||
|
setQuery({ limit: pageSize, page: currentPage - 1 }); |
||||
|
page.current = currentPage - 1 |
||||
|
}} |
||||
|
/> |
||||
|
</div> |
||||
|
|
||||
|
{setup ? ( |
||||
|
<Setup |
||||
|
visible={true} |
||||
|
pigeonSetup={true} |
||||
|
PIGEON={PIGEON} |
||||
|
close={() => { |
||||
|
setSetup(false); |
||||
|
attribute(venderList); |
||||
|
}} |
||||
|
/> |
||||
|
) : ( |
||||
|
"" |
||||
|
)} |
||||
|
|
||||
|
{/* {sideSheet ? ( |
||||
|
<SideSheets |
||||
|
visible={true} |
||||
|
rowId={rowId} |
||||
|
accessType={accessType} |
||||
|
venderList={venderList} |
||||
|
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) |
||||
|
}} |
||||
|
close={() => { |
||||
|
setReminder(false) |
||||
|
}} |
||||
|
/> */} |
||||
|
</div> |
||||
|
</> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
function mapStateToProps (state) { |
function mapStateToProps (state) { |
||||
const { auth } = state; |
const { auth, global, members, equipmentWarehouseNvr } = state; |
||||
return { |
return { |
||||
user: auth.user, |
loading: equipmentWarehouseNvr.isRequesting && !equipmentWarehouseNvr.data, |
||||
}; |
user: auth.user, |
||||
|
actions: global.actions, |
||||
|
members: members.data, |
||||
|
equipmentWarehouseNvr: equipmentWarehouseNvr.data || {}, |
||||
|
}; |
||||
} |
} |
||||
|
|
||||
export default connect(mapStateToProps)(Carrierpigeon); |
export default connect(mapStateToProps)(Carrierpigeon); |
||||
|
@ -1,20 +1,593 @@ |
|||||
import React, { useEffect } from 'react'; |
import React, { useState, useEffect, useRef } from "react"; |
||||
import { connect } from 'react-redux'; |
import { connect } from "react-redux"; |
||||
import { Coming } from '$components' |
import moment from "moment"; |
||||
import '../style.less' |
import { Button, Form, Table, Pagination, Skeleton, Popconfirm, Popover, Tag, } from "@douyinfe/semi-ui"; |
||||
|
import "../style.less"; |
||||
|
import { ApiTable } from "$utils"; |
||||
|
import Setup from "../components/setup"; |
||||
|
// import SideSheets from "../components/sideSheet"; |
||||
|
// import { skeletonScreen } from "../components/skeletonScreen"; |
||||
|
// import { ReminderBox } from "../../../components/index"; |
||||
|
|
||||
|
export const accessType = [ |
||||
|
{ name: "萤石云", key: "yingshi" }, |
||||
|
{ name: "NVR", key: "nvr" }, |
||||
|
{ name: "IPC", key: "ipc" }, |
||||
|
{ name: "级联", key: "cascade" }, |
||||
|
]; |
||||
|
|
||||
const Statuscode = (props) => { |
const Statuscode = (props) => { |
||||
|
const { history, dispatch, actions, user, loading, equipmentWarehouseNvr } = props; |
||||
|
const { equipmentWarehouse } = 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 api = useRef(); |
||||
|
const searchData = useRef(search) |
||||
|
const limits = useRef(); //每页实际条数 |
||||
|
const page = useRef(query.page); |
||||
|
const CODE = "code"; |
||||
|
const USER = "user" + props.user.id |
||||
|
const nvrRef = useRef(); //获取子组件的设备编号 |
||||
|
|
||||
return ( |
useEffect(() => { |
||||
<Coming /> |
dispatch(actions.equipmentWarehouse.getVender()).then((res) => { |
||||
) |
setvenderList(res.payload.data); |
||||
} |
attribute(res.payload.data); |
||||
|
}); |
||||
|
//初始化表格显示设置 |
||||
|
localStorage.getItem(CODE) == null |
||||
|
? localStorage.setItem( |
||||
|
CODE, |
||||
|
JSON.stringify(["manufactor", "accountNumber"]) |
||||
|
) |
||||
|
: ""; |
||||
|
}, []); |
||||
|
|
||||
|
useEffect(() => { |
||||
|
equipmentGetNvr(); |
||||
|
}, [query, search]); |
||||
|
|
||||
|
const equipmentGetNvr = () => { |
||||
|
searchData.current = { ...query, ...search } |
||||
|
dispatch(equipmentWarehouse.getNvr(searchData.current)).then((res) => { |
||||
|
limits.current = res.payload.data.data.length |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function equipmentStatus (data) { |
||||
|
switch (data) { |
||||
|
case "ON": |
||||
|
return "在线" |
||||
|
case "ONLINE": |
||||
|
return "在线" |
||||
|
case "OFF": |
||||
|
return "离线" |
||||
|
default: |
||||
|
return "未知" |
||||
|
}F |
||||
|
} |
||||
|
|
||||
|
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: "序号", |
||||
|
render: (_, record, index) => { |
||||
|
return index + 1; |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: "设备名称", |
||||
|
dataIndex: "name", |
||||
|
render: (_, r, index) => { |
||||
|
console.log(r); |
||||
|
return r.name |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: "SIP地址", |
||||
|
dataIndex: "owner", |
||||
|
render: (_, r, index) => { |
||||
|
return r?.gbNvr?.sipip |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: "操作", |
||||
|
width: "20%", |
||||
|
dataIndex: "", |
||||
|
render: (_, row) => { |
||||
|
return ( |
||||
|
<div style={{ display: "flex" }}> |
||||
|
<Button theme="borderless"> |
||||
|
启用 |
||||
|
</Button> |
||||
|
<Button |
||||
|
theme="borderless" |
||||
|
onClick={() => { |
||||
|
setSideSheet(true); |
||||
|
setRowId(row.id); |
||||
|
}} |
||||
|
> |
||||
|
释义 |
||||
|
</Button> |
||||
|
<Popconfirm |
||||
|
title="删除NVR会删除端口下的所有摄像头,是否确定删除?" |
||||
|
arrowPointAtCenter={false} |
||||
|
showArrow={true} |
||||
|
position="topRight" |
||||
|
onConfirm={() => { |
||||
|
dispatch(equipmentWarehouse.delNvr(row.id)).then(() => { |
||||
|
if (page.current > 0 && limits.current < 2) { |
||||
|
setQuery({ limit: 10, page: page.current - 1 }) |
||||
|
} else { |
||||
|
setQuery({ limit: 10, page: page.current }) |
||||
|
} |
||||
|
}); |
||||
|
}} |
||||
|
> |
||||
|
<Button theme="borderless">方案</Button> |
||||
|
</Popconfirm> |
||||
|
</div> |
||||
|
); |
||||
|
}, |
||||
|
}, |
||||
|
]; |
||||
|
|
||||
|
//获取表格属性设置 |
||||
|
function attribute (data) { |
||||
|
const arr = localStorage.getItem(CODE) |
||||
|
? JSON.parse(localStorage.getItem(CODE)) |
||||
|
: []; |
||||
|
|
||||
|
const column = [ |
||||
|
{ |
||||
|
title: "设备厂家", |
||||
|
dataIndex: "venderId", |
||||
|
key: "manufactor", |
||||
|
render: (_, r, index) => { |
||||
|
let manufactorName = data.find((item) => item.id == r.venderId); |
||||
|
return manufactorName ? manufactorName.name : ""; |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: "添加账号", |
||||
|
dataIndex: "createUserId", |
||||
|
key: "accountNumber", |
||||
|
render: (_, r, index) => { |
||||
|
return r?.createUser?.name |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: "通道数", |
||||
|
dataIndex: "channelCount", |
||||
|
key: "passageway", |
||||
|
}, |
||||
|
{ |
||||
|
title: "端口", |
||||
|
dataIndex: "port", |
||||
|
key: "port", |
||||
|
}, |
||||
|
{ |
||||
|
title: "设备状态", |
||||
|
dataIndex: "size", |
||||
|
key: "state", |
||||
|
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.online) : ""} |
||||
|
</div> |
||||
|
); |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: "创建时间", |
||||
|
dataIndex: "createTime", |
||||
|
key: "time", |
||||
|
render: (_, r, index) => { |
||||
|
return moment(r.createTime).format("YYYY-MM-DD HH:MM:SS"); |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: "项目名称", |
||||
|
dataIndex: "", |
||||
|
key: "name", |
||||
|
render: (_, r, index) => { |
||||
|
return r.station.length == 0 |
||||
|
? "" |
||||
|
: station(r, "name", "projects") |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: "pcode", |
||||
|
dataIndex: "", |
||||
|
key: "pcode", |
||||
|
render: (_, r, index) => { |
||||
|
return r.station.length == 0 |
||||
|
? "" |
||||
|
: station(r, "url", "projects") |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: "结构物", |
||||
|
dataIndex: "", |
||||
|
key: "structure", |
||||
|
render: (_, r, index) => { |
||||
|
return r.station.length == 0 |
||||
|
? "" |
||||
|
: station(r, "name") |
||||
|
}, |
||||
|
}, |
||||
|
]; |
||||
|
for (let i = 0; i < arr.length; i++) { |
||||
|
let colum = column.filter((item) => { |
||||
|
return item.key === arr[i]; |
||||
|
}); |
||||
|
columns.splice(i + 2, 0, colum[0]); |
||||
|
} |
||||
|
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, |
||||
|
marginRight: 20, |
||||
|
marginBottom: 16, |
||||
|
color: "rgba(0, 0, 0, 0.65)", |
||||
|
}; |
||||
|
|
||||
|
return ( |
||||
|
<> |
||||
|
<div> |
||||
|
<video |
||||
|
id="nvrBanner" |
||||
|
autoPlay |
||||
|
loop |
||||
|
muted |
||||
|
style={{ width: "100%", objectFit: "cover", height: 171 }} |
||||
|
src="/assets/video/nvr_banner.mp4" |
||||
|
type="video/mp4" |
||||
|
/> |
||||
|
<div style={{ position: "absolute", top: 12 }}> |
||||
|
<div |
||||
|
style={{ |
||||
|
fontSize: 22, |
||||
|
paddingTop: 15, |
||||
|
marginLeft: 21, |
||||
|
}} |
||||
|
> |
||||
|
状态码管理 |
||||
|
</div> |
||||
|
<div |
||||
|
style={{ |
||||
|
fontSize: 14, |
||||
|
paddingTop: 18, |
||||
|
marginLeft: 20, |
||||
|
}} |
||||
|
> |
||||
|
系统支持状态码显示内容的释义修改,当设备异常时,会为您显示自定义释义内容。 |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div |
||||
|
style={{ |
||||
|
width: "100%", |
||||
|
background: "#FFFFFF", |
||||
|
borderRadius: 3, |
||||
|
padding: "8px 20px", |
||||
|
marginTop: 20, |
||||
|
}} |
||||
|
> |
||||
|
<div |
||||
|
style={{ |
||||
|
height: 22, |
||||
|
fontSize: 16, |
||||
|
fontFamily: "PingFangSC-Medium, PingFang SC", |
||||
|
fontWeight: "bold", |
||||
|
color: " rgba(0, 0, 0, 0.85)", |
||||
|
lineHeight: "22px", |
||||
|
marginBottom: 16, |
||||
|
}} |
||||
|
> |
||||
|
筛选条件 |
||||
|
</div> |
||||
|
<div style={{ display: "flex" }}> |
||||
|
<Form |
||||
|
onSubmit={(values) => console.log(values)} |
||||
|
// onValueChange={values=>console.log(values)} |
||||
|
getFormApi={(formApi) => (api.current = formApi)} |
||||
|
layout="horizontal" |
||||
|
style={{ position: "relative", width: "100%", flex: 1 }} |
||||
|
> |
||||
|
<Form.Input |
||||
|
label="释义搜索: " |
||||
|
field="keyword" |
||||
|
maxLength="36" |
||||
|
placeholder="请输入错误描述、释义或自定义释义" |
||||
|
labelPosition="left" |
||||
|
style={screen} |
||||
|
/> |
||||
|
<Form.Select |
||||
|
label="启用状态:" |
||||
|
labelPosition="left" |
||||
|
style={screen} |
||||
|
field="venderId" |
||||
|
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> |
||||
|
<Form.Select |
||||
|
label="状态查询:" |
||||
|
labelPosition="left" |
||||
|
field="state" |
||||
|
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> |
||||
|
</Form> |
||||
|
<div |
||||
|
style={{ |
||||
|
width: 150, |
||||
|
display: "flex", |
||||
|
justifyContent: "flex-end", |
||||
|
alignItems: "flex-end", |
||||
|
}} |
||||
|
> |
||||
|
<Button |
||||
|
theme="solid" |
||||
|
type="primary" |
||||
|
style={{ |
||||
|
width: 65, |
||||
|
height: 30, |
||||
|
borderRadius: 3, |
||||
|
marginBottom: 20, |
||||
|
marginRight: 20, |
||||
|
}} |
||||
|
onClick={() => { |
||||
|
api.current.validate().then((v) => { |
||||
|
setearch(v); |
||||
|
setQuery({ limit: 10, page: 0 }) |
||||
|
}); |
||||
|
}} |
||||
|
> |
||||
|
搜素 |
||||
|
</Button> |
||||
|
<Button |
||||
|
theme="light" |
||||
|
type="primary" |
||||
|
style={{ |
||||
|
width: 65, |
||||
|
height: 30, |
||||
|
backGround: "#FFFFFF", |
||||
|
borderRadius: 3, |
||||
|
border: "1px solid #D9D9D9", |
||||
|
marginBottom: 20, |
||||
|
}} |
||||
|
onClick={() => { |
||||
|
api.current.reset(); |
||||
|
setearch({}); |
||||
|
setQuery({ limit: 10, page: 0 }) |
||||
|
}} |
||||
|
> |
||||
|
重置 |
||||
|
</Button> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div style={{ background: "#FFFFFF", marginTop: 5 }}> |
||||
|
<div |
||||
|
style={{ |
||||
|
width: "100%", |
||||
|
display: "flex", |
||||
|
justifyContent: "space-between", |
||||
|
padding: "13px 20px", |
||||
|
}} |
||||
|
> |
||||
|
<div |
||||
|
style={{ |
||||
|
width: 64, |
||||
|
height: 22, |
||||
|
fontSize: 16, |
||||
|
fontfAmily: "PingFangSC-Medium, PingFang SC", |
||||
|
fontWeight: "bold", |
||||
|
color: "rgba(0, 0, 0, 0.85)", |
||||
|
lineHeight: "22px", |
||||
|
}} |
||||
|
> |
||||
|
状态码详情 |
||||
|
</div> |
||||
|
<div> |
||||
|
<Button |
||||
|
style={{ |
||||
|
width: 32, |
||||
|
height: 32, |
||||
|
background: "#D9D9D9", |
||||
|
borderadius: 3, |
||||
|
marginRight: 20, |
||||
|
}} |
||||
|
type="primary" |
||||
|
key="primary" |
||||
|
onClick={() => { |
||||
|
setSetup(true); |
||||
|
}} |
||||
|
> |
||||
|
<img |
||||
|
src="/assets/images/background/setup.png" |
||||
|
alt="设置" |
||||
|
style={{ width: 18, height: 18 }} |
||||
|
/> |
||||
|
</Button> |
||||
|
<Button |
||||
|
theme="solid" |
||||
|
type="primary" |
||||
|
style={{ |
||||
|
width: 65, |
||||
|
height: 32, |
||||
|
borderRadius: 3, |
||||
|
}} |
||||
|
onClick={() => { |
||||
|
// api.current.validate().then((v) => { |
||||
|
// setearch(v); |
||||
|
// setQuery({ limit: 10, page: 0 }) |
||||
|
// }); |
||||
|
}} |
||||
|
> |
||||
|
批量设置 |
||||
|
</Button> |
||||
|
</div> |
||||
|
</div> |
||||
|
<Skeleton |
||||
|
loading={loading} |
||||
|
// placeholder={skeletonScreen()} |
||||
|
active={true} |
||||
|
> |
||||
|
<Table |
||||
|
columns={setupp.filter((s) => s)} |
||||
|
dataSource={equipmentWarehouseNvr.data} |
||||
|
bordered={false} |
||||
|
empty="暂无数据" |
||||
|
style={{ |
||||
|
padding: "0px 20px", |
||||
|
}} |
||||
|
pagination={false} |
||||
|
/> |
||||
|
</Skeleton> |
||||
|
|
||||
|
<div |
||||
|
style={{ |
||||
|
display: "flex", |
||||
|
justifyContent: "flex-end", |
||||
|
padding: "20px 20px", |
||||
|
}} |
||||
|
> |
||||
|
<span style={{ lineHeight: "30px" }}> |
||||
|
共{equipmentWarehouseNvr.total}个设备 |
||||
|
</span> |
||||
|
<Pagination |
||||
|
total={equipmentWarehouseNvr.total} |
||||
|
showSizeChanger |
||||
|
currentPage={query.page + 1} |
||||
|
pageSizeOpts={[10, 20, 30, 40]} |
||||
|
onChange={(currentPage, pageSize) => { |
||||
|
setQuery({ limit: pageSize, page: currentPage - 1 }); |
||||
|
page.current = currentPage - 1 |
||||
|
}} |
||||
|
/> |
||||
|
</div> |
||||
|
|
||||
|
{setup ? ( |
||||
|
<Setup |
||||
|
visible={true} |
||||
|
CODE={CODE} |
||||
|
close={() => { |
||||
|
setSetup(false); |
||||
|
attribute(venderList); |
||||
|
}} |
||||
|
/> |
||||
|
) : ( |
||||
|
"" |
||||
|
)} |
||||
|
|
||||
|
{/* {sideSheet ? ( |
||||
|
<SideSheets |
||||
|
visible={true} |
||||
|
rowId={rowId} |
||||
|
accessType={accessType} |
||||
|
venderList={venderList} |
||||
|
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) |
||||
|
}} |
||||
|
close={() => { |
||||
|
setReminder(false) |
||||
|
}} |
||||
|
/> */} |
||||
|
</div> |
||||
|
</> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
function mapStateToProps (state) { |
function mapStateToProps (state) { |
||||
const { auth } = state; |
const { auth, global, members, equipmentWarehouseNvr } = state; |
||||
return { |
return { |
||||
user: auth.user, |
loading: equipmentWarehouseNvr.isRequesting && !equipmentWarehouseNvr.data, |
||||
}; |
user: auth.user, |
||||
|
actions: global.actions, |
||||
|
members: members.data, |
||||
|
equipmentWarehouseNvr: equipmentWarehouseNvr.data || {}, |
||||
|
}; |
||||
} |
} |
||||
|
|
||||
export default connect(mapStateToProps)(Statuscode); |
export default connect(mapStateToProps)(Statuscode); |
||||
|
Loading…
Reference in new issue