Browse Source

Merge branch 'dev_trial' of https://gitea.anxinyun.cn/free-sun/FS-IOT into dev_trial

release_1.1.2
巴林闲侠 2 years ago
parent
commit
9d55d70bc2
  1. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/icon_camera.png
  2. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/icon_email.png
  3. BIN
      code/VideoAccess-VCMP/web/client/assets/images/background/icon_phone.png
  4. 4
      code/VideoAccess-VCMP/web/client/src/components/index.js
  5. 2
      code/VideoAccess-VCMP/web/client/src/components/skeletonScreen.jsx
  6. 80
      code/VideoAccess-VCMP/web/client/src/sections/application/components/applyModal.jsx
  7. 358
      code/VideoAccess-VCMP/web/client/src/sections/application/containers/applicationCenter.jsx
  8. 42
      code/VideoAccess-VCMP/web/client/src/sections/equipmentWarehouse/components/fluoriteCamera.jsx
  9. 43
      code/VideoAccess-VCMP/web/client/src/sections/equipmentWarehouse/components/ipcCamera.jsx
  10. 21
      code/VideoAccess-VCMP/web/client/src/sections/equipmentWarehouse/components/nvrCamera.jsx
  11. 6
      code/VideoAccess-VCMP/web/client/src/sections/equipmentWarehouse/containers/camera.jsx
  12. 5
      code/VideoAccess-VCMP/web/client/src/sections/equipmentWarehouse/containers/nvr.jsx
  13. 102
      code/VideoAccess-VCMP/web/client/src/sections/offline/components/pushSideSheet.jsx
  14. 44
      code/VideoAccess-VCMP/web/client/src/sections/offline/components/pushSideSheet.less
  15. 15
      code/VideoAccess-VCMP/web/client/src/sections/offline/containers/carrierpigeon.jsx
  16. 2
      code/VideoAccess-VCMP/web/client/src/utils/webapi.js
  17. 2
      code/VideoAccess-VCMP/web/package.json

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 561 B

4
code/VideoAccess-VCMP/web/client/src/components/index.js

@ -5,6 +5,7 @@ import ReminderBox from './reminderBox'
import VideoPlay from './videoPlayer/videoPlay' import VideoPlay from './videoPlayer/videoPlay'
import VideoPlayModal from './videoPlayer/videoPlayModal' import VideoPlayModal from './videoPlayer/videoPlayModal'
import Setup from './setup' import Setup from './setup'
import {SkeletonScreen} from './skeletonScreen'
export { export {
SimpleFileDownButton, SimpleFileDownButton,
@ -12,5 +13,6 @@ export {
ReminderBox, ReminderBox,
VideoPlay, VideoPlay,
VideoPlayModal, VideoPlayModal,
Setup Setup,
SkeletonScreen,
}; };

2
code/VideoAccess-VCMP/web/client/src/sections/equipmentWarehouse/components/skeletonScreen.jsx → code/VideoAccess-VCMP/web/client/src/components/skeletonScreen.jsx

@ -2,7 +2,7 @@ import React, { useState, useEffect } from "react";
import { Skeleton } from "@douyinfe/semi-ui"; import { Skeleton } from "@douyinfe/semi-ui";
export function skeletonScreen() { export function SkeletonScreen() {
return <> return <>
<Skeleton.Title style={{width: "95%",height:24,margin:"8px 20px"}} /> <Skeleton.Title style={{width: "95%",height:24,margin:"8px 20px"}} />
<Skeleton.Title style={{width: "80%",height:28,margin:"16px 20px"}} /> <Skeleton.Title style={{width: "80%",height:28,margin:"16px 20px"}} />

80
code/VideoAccess-VCMP/web/client/src/sections/application/components/applyModal.jsx

@ -0,0 +1,80 @@
import React, { useState, useEffect, useRef } from "react";
import { connect } from "react-redux";
import { Button, Form, Modal, } from "@douyinfe/semi-ui";
const ApplyModal = ({ close, modalName, visible }) => {
const form = useRef();
const handleOk = () => {
form.current
.validate()
.then((values) => {
console.log(values);
// close()
})
}
return <Modal
title={modalName ? "修改应用" : "创建应用"}
visible={visible}
width={610}
onCancel={() => close()}
onOk={handleOk}
>
<Form
allowEmpty
labelPosition="left"
labelAlign="left"
labelWidth="90px"
onValueChange={(values) => console.log(values)}
getFormApi={(formApi) => (form.current = formApi)}
>
<Form.Input
maxLength="36"
field="name"
label="应用名称:"
allowEmpty={false}
initValue={'' || ""}
placeholder="建议命名方式: [应用名 + 应用场景] 如:智慧昌南-消防,不超过15个字符"
style={{ width: 466 }}
rules={[
{
required: true,
message: "建议命名方式: [应用名 + 应用场景] 如:智慧昌南-消防,不超过15个字符",
},
]}
/>
<Form.Select
label="设备厂家:"
field="venderId"
initValue={'' || null}
placeholder="请选择应用类型"
allowEmpty={false}
style={{ width: 150 }}
rules={[{ required: true, message: "请选择应用类型" }]}
>
{[{ name: 'web', id: 'web' }, { name: 'app', id: 'app' }, { name: '小程序', id: '小程序' }, { name: '其他', id: '其他' }].map((item, index) => (
<Form.Select.Option key={index} value={item.id}>
{item.name}
</Form.Select.Option>
))}
</Form.Select>
</Form>
</Modal>
}
function mapStateToProps (state) {
const { auth, global, members } = state;
return {
loading: members.isRequesting,
user: auth.user,
actions: global.actions,
global: global,
members: members.data,
};
}
export default connect(mapStateToProps)(ApplyModal);

358
code/VideoAccess-VCMP/web/client/src/sections/application/containers/applicationCenter.jsx

@ -1,12 +1,362 @@
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 qs from "qs";
import {
Button,
Form,
Table,
Pagination,
Popover,
Tag,
Skeleton,
Popconfirm,
Row,
} from "@douyinfe/semi-ui";
import { SimpleFileDownButton, VideoPlayModal, SkeletonScreen, Setup } from "$components";
// import "../style.less";
import ApplyModal from "../components/applyModal";
// import RemarksModal from "../components/remarksModal";
// import SideSheets from "../components/sideSheet";
// import { accessType } from "./nvr";
import '../style.less' import '../style.less'
const ApplicationCenter = (props) => { const ApplicationCenter = (props) => {
const { dispatch, actions, user, loading, equipmentWarehouseCamera } = props;
// const { equipmentWarehouse } = actions;
const [cameraModal, setCameraModal] = useState(false);
const [remarksModal, setRemarksModal] = useState(false);
const [videoPlay, setVideoPlay] = useState(false);
const [modalName, setModalName] = useState(false); //
const [setup, setSetup] = useState(false); //
const [applyModal, setApplyModal] = useState(false);
const [cameraSetup, setcameraSetup] = useState(false);
const [setupp, setSetupp] = useState([]);
const [venderList, setvenderList] = useState([]); //
const [query, setQuery] = useState({ limit: 10, page: 0 }); //
const [search, setSearch] = useState({}); //
const [rowId, setRowId] = useState(); //id
const [cameraData, setCameraData] = useState({}); //
const [modify, setModify] = useState(false); //
const [parentCamera, setParentCamera] = useState(""); //
const [addNvr, setAddNvr] = useState(false); //nvrNVR
const [nvrNumber, setNvrNumber] = useState();
const [videoObj, setVideoObj] = useState(); //
const [axyData, setAxyData] = useState();
const [cameraRemarks, setCameraRemarks] = useState([]);//
const api = useRef();
const searchData = useRef({})
const limits = useRef(); //
const page = useRef(query.page);
const deviceClickb = useRef(true)
const APPLICATION = "application";
const columns = [
{
title: "序号",
dataIndex: "",
render: (text, r, index) => {
return index + 1;
},
},
{
title: "应用名称",
dataIndex: "name",
key: "name",
},
{
title: "APPID",
dataIndex: "appId",
key: "appId",
},
{
title: "Secret Key",
dataIndex: "secretKey",
key: "secretKey",
},
{
title: "操作",
width: "20%",
dataIndex: "",
render: (_, row) => {
return ( return (
<Coming /> <div style={{ display: "flex" }}>
<Button
theme="borderless"
onClick={() => {
setApplyModal(true)
setModalName(true)
}}
>
修改
</Button>
{row.forbidden ? (
<Button
theme="borderless"
onClick={() => {
}}
>
启用
</Button>
) : (
<Popconfirm
title="禁用后,应用系统引入的页面及能力将会暂时失效,请谨慎操作。"
arrowPointAtCenter={false}
showArrow={true}
position="topRight"
onConfirm={() => {
}}
>
<Button theme="borderless">禁用</Button>
</Popconfirm>
)}
<Popconfirm
title="删除后,应用系统引入的页面及能力将会永久失效,请谨慎操作。"
arrowPointAtCenter={false}
showArrow={true}
position="topRight"
onConfirm={() => {
}}
>
<Button theme="borderless">删除</Button>
</Popconfirm>
</div>
);
},
}
];
//
function attribute () {
const arr = localStorage.getItem(APPLICATION)
? JSON.parse(localStorage.getItem(APPLICATION))
: [];
const column = [
{
title: "创建时间",
dataIndex: "createTime",
key: "createTime",
},
{
title: "创建账号",
dataIndex: "account",
key: "account",
},
{
title: "应用类型",
dataIndex: "applicationType",
key: "applicationType",
},
];
for (let i = 0; i < arr.length; i++) {
let colum = column.filter((item) => {
return item.key === arr[i];
});
columns.splice(i + 4, 0, colum[0]);
}
setSetupp(columns);
}
const tableList = [//
{
title: '详情信息',
list: [
{ name: "创建时间", value: "createTime" },
{ name: "创建账号", value: "account" },
{ name: "应用类型", value: "applicationType" },
]
},
];
useEffect(() => {
//
localStorage.getItem(APPLICATION) == null
? localStorage.setItem(
APPLICATION,
JSON.stringify(["createTime",])
)
: "";
attribute();
}, [])
return (
<>
<div style={{ position: "" }}>
<video
id="cameraBanner"
autoPlay
loop
muted
style={{ width: "100%", objectFit: "cover", height: 171 }}
src="/assets/video/camera_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,
}}
>
创建接口对应子系统的APPID及能力调用时所需的秘钥
</div>
<div
style={{
fontSize: 14,
marginTop: 28,
marginLeft: 21,
width: 89,
height: 32,
lineHeight: 32 + "px",
textAlign: "center",
backgroundColor: "#D9EAFF",
color: "#1859C1",
cursor: "pointer",
}}
onClick={() => {
setApplyModal(true)
}}
>
创建应用
</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);
// setcameraSetup(true);
}}
>
<img
src="/assets/images/background/setup.png"
alt="设置"
style={{ width: 18, height: 18 }}
/>
</Button>
{/* <SimpleFileDownButton src="camera/export" /> */}
</div>
</div>
<Skeleton
loading={false}
active={true}
placeholder={SkeletonScreen()}
>
<Table
columns={setupp.filter((s) => s)}
dataSource={[{ name: 'csadca', }]}
bordered={false}
empty="暂无数据"
style={{
padding: "0px 20px",
}}
pagination={false}
/>
</Skeleton>
<div
style={{
display: "flex",
justifyContent: "flex-end",
padding: "20px 20px",
}}
>
<span style={{ lineHeight: "30px" }}>
{100}个设备
</span>
<Pagination
className="22"
total={100}
showSizeChanger
currentPage={query.page + 1}
pageSizeOpts={[10, 20, 30, 40]}
onChange={(currentPage, pageSize) => {
setQuery({ limit: pageSize, page: currentPage - 1 });
page.current = currentPage - 1
}}
/>
</div>
</div>
{/*表格设置*/}
{setup ? (
<Setup
tableType={APPLICATION}
tableList={tableList}
close={() => {
setSetup(false);
attribute();
}}
/>
) : (
""
)}
{applyModal ? (
<ApplyModal
visible={true}
modalName={modalName}
close={() => {
setApplyModal(false)
setModalName(false)
}}
/>
) : (
""
)}
</>
) )
} }

42
code/VideoAccess-VCMP/web/client/src/sections/equipmentWarehouse/components/fluoriteCamera.jsx

@ -83,7 +83,8 @@ function fluoriteCamera ({ cRef, CameraKind, CameraAbility, cameraData, ashTrue,
labelWidth="115px" labelWidth="115px"
onValueChange={(values) => { onValueChange={(values) => {
console.log(values); console.log(values);
let setting = ["abilityId", "cloudControl", "highDefinition", "kindId", "name", "position", "rtmp", "serialNo",] // let setting = ["abilityId", "cloudControl", "highDefinition", "kindId", "name", "position", "rtmp", "serialNo",]
let setting = ["abilityId", "cloudControl", "highDefinition", "kindId", "name", "position", "serialNo",]
let b = {} let b = {}
setting.map((item) => { setting.map((item) => {
if (values.hasOwnProperty(item)) { if (values.hasOwnProperty(item)) {
@ -109,7 +110,8 @@ function fluoriteCamera ({ cRef, CameraKind, CameraAbility, cameraData, ashTrue,
cloudControl: cameraData.cloudControl || "", cloudControl: cameraData.cloudControl || "",
voice: cameraData.voice || "", voice: cameraData.voice || "",
serialNo: cameraData.serialNo || "", serialNo: cameraData.serialNo || "",
rtmp: cameraData.rtmp || "", // rtmp: cameraData.rtmp || "",
rtmp: '此处无效 自动生成',
}} }}
getFormApi={(formApi) => (form.current = formApi)} getFormApi={(formApi) => (form.current = formApi)}
> >
@ -264,7 +266,7 @@ function fluoriteCamera ({ cRef, CameraKind, CameraAbility, cameraData, ashTrue,
label="设备类型:" label="设备类型:"
field="kindId" field="kindId"
placeholder="请选择摄像头类型" placeholder="请选择摄像头类型"
style={{ width: 180 }} style={{ width: 307 }}
rules={[{ required: true, message: "请选择摄像头类型" }]} rules={[{ required: true, message: "请选择摄像头类型" }]}
> >
{CameraKind.map((item, index) => ( {CameraKind.map((item, index) => (
@ -274,21 +276,6 @@ function fluoriteCamera ({ cRef, CameraKind, CameraAbility, cameraData, ashTrue,
))} ))}
</Form.Select> </Form.Select>
<Form.Select
label="设备能力:"
multiple
maxTagCount={1}
field="abilityId"
placeholder="请选择能力"
style={{ width: 180 }}
rules={[{ required: true, message: "请选择能力" }]}
>
{CameraAbility.map((item, index) => (
<Form.Select.Option key={index} value={item.id}>
{item.ability}
</Form.Select.Option>
))}
</Form.Select>
</Col> </Col>
<Col span={12}> <Col span={12}>
{/* 云台支持 */} {/* 云台支持 */}
@ -473,7 +460,7 @@ function fluoriteCamera ({ cRef, CameraKind, CameraAbility, cameraData, ashTrue,
rules={[{ required: true, message: "请输入设备序列号" }]} rules={[{ required: true, message: "请输入设备序列号" }]}
/> />
{/* RTMP地址接入 */} {/* RTMP地址接入 */}
<TextArea {/* <TextArea
style={{ width: 320, height: 90 }} style={{ width: 320, height: 90 }}
field="rtmp" field="rtmp"
label="RTMP地址接入:" label="RTMP地址接入:"
@ -481,7 +468,22 @@ function fluoriteCamera ({ cRef, CameraKind, CameraAbility, cameraData, ashTrue,
disabled={cameraData.id ? true : false} disabled={cameraData.id ? true : false}
placeholder="请输入RTMP地址接入" placeholder="请输入RTMP地址接入"
rules={[{ required: true, message: "请输入RTMP地址接入" }]} rules={[{ required: true, message: "请输入RTMP地址接入" }]}
/> /> */}
<Form.Select
label="设备能力:"
multiple
maxTagCount={1}
field="abilityId"
placeholder="请选择能力"
style={{ width: 307 }}
rules={[{ required: true, message: "请选择能力" }]}
>
{CameraAbility.map((item, index) => (
<Form.Select.Option key={index} value={item.id}>
{item.ability}
</Form.Select.Option>
))}
</Form.Select>
</Col> </Col>
</Row> </Row>
</Form> </Form>

43
code/VideoAccess-VCMP/web/client/src/sections/equipmentWarehouse/components/ipcCamera.jsx

@ -88,7 +88,8 @@ function ipcCamera ({
labelWidth="115px" labelWidth="115px"
onValueChange={(values) => { onValueChange={(values) => {
console.log(values); console.log(values);
let setting = ["abilityId", "cloudControl", "kindId", "name", "position", "rtmp", "serialNo"] let setting = ["abilityId", "cloudControl", "kindId", "name", "position", "serialNo"]
// let setting = ["abilityId", "cloudControl", "kindId", "name", "position", "rtmp", "serialNo"]
let b = {} let b = {}
setting.map((item) => { setting.map((item) => {
if (values.hasOwnProperty(item)) { if (values.hasOwnProperty(item)) {
@ -113,7 +114,8 @@ function ipcCamera ({
cloudControl: cameraData.cloudControl || "", cloudControl: cameraData.cloudControl || "",
voice: cameraData.voice || "", voice: cameraData.voice || "",
serialNo: cameraData.serialNo || "", serialNo: cameraData.serialNo || "",
rtmp: cameraData.rtmp || "", rtmp: "此处无效 自动生成",
// rtmp: cameraData.rtmp || "",
}} }}
getFormApi={(formApi) => (form.current = formApi)} getFormApi={(formApi) => (form.current = formApi)}
> >
@ -190,7 +192,7 @@ function ipcCamera ({
label="设备类型:" label="设备类型:"
field="kindId" field="kindId"
placeholder="请选择摄像头类型" placeholder="请选择摄像头类型"
style={{ width: 180 }} style={{ width: 307 }}
rules={[{ required: true, message: "请选择摄像头类型" }]} rules={[{ required: true, message: "请选择摄像头类型" }]}
> >
{CameraKind.map((item, index) => ( {CameraKind.map((item, index) => (
@ -199,22 +201,6 @@ function ipcCamera ({
</Form.Select.Option> </Form.Select.Option>
))} ))}
</Form.Select> </Form.Select>
<Form.Select
label="设备能力:"
multiple
maxTagCount={1}
field="abilityId"
placeholder="请选择能力"
style={{ width: 180 }}
rules={[{ required: true, message: "请选择能力" }]}
>
{CameraAbility.map((item, index) => (
<Form.Select.Option key={index} value={item.id}>
{item.ability}
</Form.Select.Option>
))}
</Form.Select>
</Col> </Col>
<Col span={12}> <Col span={12}>
<Form.RadioGroup <Form.RadioGroup
@ -398,14 +384,29 @@ function ipcCamera ({
rules={[{ required: true, message: "请输入设备编号" }]} rules={[{ required: true, message: "请输入设备编号" }]}
/> />
</div> </div>
<TextArea <Form.Select
label="设备能力:"
multiple
maxTagCount={1}
field="abilityId"
placeholder="请选择能力"
style={{ width: 307 }}
rules={[{ required: true, message: "请选择能力" }]}
>
{CameraAbility.map((item, index) => (
<Form.Select.Option key={index} value={item.id}>
{item.ability}
</Form.Select.Option>
))}
</Form.Select>
{/* <TextArea
style={{ width: 320, height: 90 }} style={{ width: 320, height: 90 }}
field="rtmp" field="rtmp"
label="RTMP地址接入:" label="RTMP地址接入:"
disabled={cameraData.id ? true : false} disabled={cameraData.id ? true : false}
placeholder="请输入RTMP地址接入" placeholder="请输入RTMP地址接入"
rules={[{ required: true, message: "请输入RTMP地址" }]} rules={[{ required: true, message: "请输入RTMP地址" }]}
/> /> */}
</Col> </Col>
{/* <Col span={18}> {/* <Col span={18}>

21
code/VideoAccess-VCMP/web/client/src/sections/equipmentWarehouse/components/nvrCamera.jsx

@ -54,6 +54,13 @@ function nvrCamera ({ dispatch, actions, nvrRef, cameraData, addNvr, nvrNumber,
streamId: cameraDataNvr.serialNo, streamId: cameraDataNvr.serialNo,
}) })
).then((res) => { ).then((res) => {
if(res.success==false){
setstep("none");
setloading(false);
setstepp("none");
setloadingTip("获取中...");
return
}
let oneData = res.payload.data[0]; let oneData = res.payload.data[0];
let modifyData = res.payload.data.find( let modifyData = res.payload.data.find(
(item) => item.id == cameraData.gbId); (item) => item.id == cameraData.gbId);
@ -92,6 +99,13 @@ function nvrCamera ({ dispatch, actions, nvrRef, cameraData, addNvr, nvrNumber,
setloading(true); setloading(true);
setstep("block"); setstep("block");
dispatch(equipmentWarehouse.getVideoStreaming({ streamId: nvrNumber })).then((res) => { dispatch(equipmentWarehouse.getVideoStreaming({ streamId: nvrNumber })).then((res) => {
if(res.success==false){
setstep("none");
setloading(false);
setstepp("none");
setloadingTip("获取中...");
return
}
let chooseList = []; let chooseList = [];
let data = res.payload.data.map((item) => { let data = res.payload.data.map((item) => {
item.change = false; item.change = false;
@ -159,6 +173,13 @@ function nvrCamera ({ dispatch, actions, nvrRef, cameraData, addNvr, nvrNumber,
setloading(true); setloading(true);
setstep("block"); setstep("block");
dispatch(equipmentWarehouse.getVideoStreaming(valuess)).then((res) => { dispatch(equipmentWarehouse.getVideoStreaming(valuess)).then((res) => {
if(res.success==false){
setstep("none");
setloading(false);
setstepp("none");
setloadingTip("获取中...");
return
}
let data = res.payload.data.map((item) => { let data = res.payload.data.map((item) => {
item.change = false; item.change = false;
item.support = false; item.support = false;

6
code/VideoAccess-VCMP/web/client/src/sections/equipmentWarehouse/containers/camera.jsx

@ -13,13 +13,13 @@ import {
Popconfirm, Popconfirm,
Row, Row,
} from "@douyinfe/semi-ui"; } from "@douyinfe/semi-ui";
import { SimpleFileDownButton, VideoPlayModal } from "$components"; import { SimpleFileDownButton, VideoPlayModal,SkeletonScreen } from "$components";
import "../style.less"; import "../style.less";
import CameraModal from "../components/cameraModal"; import CameraModal from "../components/cameraModal";
import RemarksModal from "../components/remarksModal"; import RemarksModal from "../components/remarksModal";
import {Setup} from "$components"; import {Setup} from "$components";
import SideSheets from "../components/sideSheet"; import SideSheets from "../components/sideSheet";
import { skeletonScreen } from "../components/skeletonScreen"; import { skeletonScreen } from "../../../components/skeletonScreen";
import { accessType } from "./nvr"; import { accessType } from "./nvr";
const CameraHeader = (props) => { const CameraHeader = (props) => {
@ -756,7 +756,7 @@ const CameraHeader = (props) => {
<Skeleton <Skeleton
loading={loading} loading={loading}
active={true} active={true}
placeholder={skeletonScreen()} placeholder={SkeletonScreen()}
> >
<Table <Table
columns={setupp.filter((s) => s)} columns={setupp.filter((s) => s)}

5
code/VideoAccess-VCMP/web/client/src/sections/equipmentWarehouse/containers/nvr.jsx

@ -7,9 +7,8 @@ import { ApiTable } from "$utils";
import NvrModal from "../components/nvrModal"; import NvrModal from "../components/nvrModal";
import {Setup} from "$components"; import {Setup} from "$components";
import SideSheets from "../components/sideSheet"; import SideSheets from "../components/sideSheet";
import { skeletonScreen } from "../components/skeletonScreen";
import { ReminderBox } from "../../../components/index"; import { ReminderBox } from "../../../components/index";
import { SimpleFileDownButton } from "$components"; import { SimpleFileDownButton,SkeletonScreen } from "$components";
export const accessType = [ export const accessType = [
{ name: "萤石云", key: "yingshi" }, { name: "萤石云", key: "yingshi" },
@ -556,7 +555,7 @@ const NvrHeader = (props) => {
</div> </div>
<Skeleton <Skeleton
loading={loading} loading={loading}
placeholder={skeletonScreen()} placeholder={SkeletonScreen()}
active={true} active={true}
> >
<Table <Table

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

@ -1,8 +1,9 @@
import React, { useState, useRef, useEffect } from "react"; import React, { useState, useRef, useEffect } from "react";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { Modal, Spin,Input,Collapse ,SideSheet,Tabs, TabPane} from "@douyinfe/semi-ui"; import { Modal, Spin,Input,Collapse ,SideSheet,Tabs, TabPane,Popover} from "@douyinfe/semi-ui";
import moment from "moment"; import moment from "moment";
import './pushSideSheet.less' import './pushSideSheet.less'
import { push } from "react-router-redux";
function pushSideSheet (props) { function pushSideSheet (props) {
const { const {
close, close,
@ -11,20 +12,67 @@ function pushSideSheet (props) {
journal// journal//
} = props; } = props;
const { offline } = actions; const { offline } = actions;
const [notesValue, setNotesValue] = useState('');// const [logList, setLogList] = useState([]);//
const [noticeTest, setNoticeTest] = useState('');//
const [equipmentTest, setEquipmentTest] = useState();//
// //
useEffect(() => { useEffect(() => {
let timeList = [] let timeList = []
for (let index = 0; index < journal.length; index++) { for (let index = 0; index < journal.length; index++) {
let receiverTest=journal[index].receiver.join(';');
let camerTest=''
for (let j = 0; j < journal[index].camera.length; j++) {
camerTest=camerTest+journal[index].camera[j].name+';'
}
timeList.push( timeList.push(
{ {
title:getTimeTitle(journal[index].time), title:getTimeTitle(journal[index].time),
time:getTimeData(journal[index].time) time:getTimeData(journal[index].time),
cameraList:camerTest,
receiverList:receiverTest
}
)
}
let yearList=[]
for (let index = 0; index < journal.length; index++) {
yearList.push(
{
title:getTimeTitle(journal[index].time),
} }
) )
} }
console.log('timeList',timeList); let showList=[]
let obj = {};
for (let i = 0; i < yearList.length; i++) {
if (!obj[yearList[i].title]) {
showList.push(yearList[i]);
obj[yearList[i].title] = true;
}
}
for (let index = 0; index < showList.length; index++) {
showList[index].timeList=[]
}
for (let j = 0; j < showList.length; j++) {
for (let i = 0; i < timeList.length; i++) {
if(timeList[i].title==showList[j].title){
showList[j].timeList.push({time:timeList[i].time,cameraList:timeList[i].cameraList,receiverList:timeList[i].receiverList})
}
}
}
setLogList(showList)
let noticeList =''
for (let i = 0; i < pushData.cameraStatusPushReceivers.length; i++) {
noticeList=noticeList+pushData.cameraStatusPushReceivers[i].receiver+';'
}
setNoticeTest(noticeList)
let equipmentList=''
for (let i = 0; i < pushData.cameraStatusPushMonitors.length; i++) {
noticeList=noticeList+pushData.cameraStatusPushMonitors[i].camera.name+';'
}
setEquipmentTest(equipmentList)
console.log('pushData',pushData);
}, []); }, []);
function getTimeTitle(date){ function getTimeTitle(date){
let year = moment(date).year()+'年' let year = moment(date).year()+'年'
@ -47,16 +95,54 @@ function pushSideSheet (props) {
<Tabs type="line"> <Tabs type="line">
<TabPane tab="推送日志" itemKey="1"> <TabPane tab="推送日志" itemKey="1">
<Collapse> <Collapse>
<Collapse.Panel header={<div style={{width:'100%',textAlign:'center'}}>11111111</div>} itemKey="1"> {logList.map((item, index) => {
<p>Hi, bytedance dance dance. This is the docsite of Semi UI. </p> return (
<Collapse.Panel header={<div style={{width:'100%',textAlign:'center'}}>{item.title}</div>} itemKey={String(index)} key={index} >
{item.timeList.map((itm,idx)=>{
return(
<div style={{display:'flex',alignItems:'center',height:46,borderBottom: '1px solid #E8E8E8',fontSize:12,color:'rgba(0,0,0,0.6500)'}} key={idx}>
<div style={{margin:'0px 24px',width:74}}>{itm.time}</div>
<Popover content={
<div style={{ padding: 12,width:300,wordBreak:'break-all' }}>
{itm.receiverList}
</div>
}>
<div style={{marginRight:24,width:262,textOverflow:'ellipsis',whiteSpace:'nowrap',overflow:'hidden'}}>{itm.receiverList}</div>
</Popover>
<Popover content={
<div style={{ padding: 12,width:200,wordBreak:'break-all' }}>
{itm.cameraList}
</div>
}>
<div style={{marginRight:24,width:133,textOverflow:'ellipsis',whiteSpace:'nowrap',overflow:'hidden'}}>{itm.cameraList}</div>
</Popover>
<div style={{marginRight:25,width:83}} className='online' >上线及时通知</div>
</div>
)
})}
</Collapse.Panel> </Collapse.Panel>
)})}
</Collapse> </Collapse>
</TabPane> </TabPane>
<TabPane tab="监听范围" itemKey="2"> <TabPane tab="监听范围" itemKey="2">
22 <div style={{margin:'12px 36px',fontSize:12,color:'rgba(0,0,0,0.6500)'}}>
<img
src="/assets/images/background/icon_camera.png"
alt="设置"
style={{ width: 24, height: 24 }}
/>
<div>{equipmentTest}</div>
</div>
</TabPane> </TabPane>
<TabPane tab="接收信息" itemKey="3"> <TabPane tab="接收信息" itemKey="3">
33 <div style={{margin:'12px 36px',fontSize:12,color:'rgba(0,0,0,0.6500)'}}>
<img
src={pushData.pushWay=='email'?"/assets/images/background/icon_email.png":"/assets/images/background/icon_phone.png"}
alt="设置"
style={{ width: 24, height: 24 }}
/>
<div>{noticeTest}</div>
</div>
</TabPane> </TabPane>
</Tabs> </Tabs>
</SideSheet> </SideSheet>

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

@ -5,4 +5,48 @@
.semi-tabs-tab-active{ .semi-tabs-tab-active{
color: #1859C1; color: #1859C1;
} }
.semi-sidesheet-body{
padding:0px;
}
.semi-tabs-bar{
margin: 0px 24px;
border-bottom:none;
}
.semi-collapse-header{
background: #F7F8FA;
margin:0px;
}
.semi-tabs-content{
padding:0px;
}
.semi-collapse-content{
padding: 0px;
}
.online{
background: #E7F6EB;
color: #007B22;
display: flex;
align-items: center;
height: 22px;
justify-content: center;
border-radius: 3px;
}
.offline{
background:#FFF6D8;
color: #E8B500;
display: flex;
align-items: center;
height: 22px;
justify-content: center;
border-radius: 3px;
}
.timing{
background: #F0F6FF;
color: #1859C1;
display: flex;
align-items: center;
height: 22px;
justify-content: center;
border-radius: 3px;
}
} }

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

@ -198,13 +198,12 @@ const Carrierpigeon = (props) => {
</Button> </Button>
<Button onClick={()=>{ <Button onClick={()=>{
dispatch(offline.getPushLog(row.id)).then((res) => { dispatch(offline.getPushLog(row.id)).then((res) => {
// equipmentGetStatusPush();
setJournal(res.payload.data); setJournal(res.payload.data);
setSideSheetVisible(true);
setPushData(row); setPushData(row);
setSideSheetVisible(true);
}); });
}} theme="borderless"> }} theme="borderless">
日志 查看
</Button> </Button>
</div> </div>
); );
@ -479,8 +478,7 @@ const Carrierpigeon = (props) => {
> >
<Table <Table
columns={setupp.filter((s) => s)} columns={setupp.filter((s) => s)}
// dataSource={StatusPushList.data} dataSource={StatusPushList.rows}
dataSource={StatusPushList}
bordered={false} bordered={false}
empty="暂无数据" empty="暂无数据"
style={{ style={{
@ -498,10 +496,10 @@ const Carrierpigeon = (props) => {
}} }}
> >
<span style={{ lineHeight: "30px" }}> <span style={{ lineHeight: "30px" }}>
{StatusPushList.total}条策略 {StatusPushList.count}条策略
</span> </span>
<Pagination <Pagination
total={StatusPushList.total} total={StatusPushList.count}
showSizeChanger showSizeChanger
currentPage={query.page + 1} currentPage={query.page + 1}
pageSizeOpts={[10, 20, 30, 40]} pageSizeOpts={[10, 20, 30, 40]}
@ -556,8 +554,7 @@ function mapStateToProps (state) {
user: auth.user, user: auth.user,
actions: global.actions, actions: global.actions,
members: members.data, members: members.data,
StatusPushList: StatusPushList.data || [], StatusPushList: StatusPushList.data || {},
// StatusPushList: StatusPushList.data || {},
}; };
} }

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

@ -47,7 +47,7 @@ export const ApiTable = {
getStatusSimpleAll:'status/simple_all',//获取全部状态码简略信息 getStatusSimpleAll:'status/simple_all',//获取全部状态码简略信息
getCameraListAll:'camera/listAll',//获取所有摄像头信息 getCameraListAll:'camera/listAll',//获取所有摄像头信息
getStatusPush:'status/push',//获取推送配置 getStatusPush:'status/push',//获取推送配置
putSasdtatusPush:'sasdtatus/push',//编辑推送配置 putSasdtatusPush:'status/push',//编辑推送配置
delPush:'status/push/{configId}',//删除推送配置 delPush:'status/push/{configId}',//删除推送配置
putPushBanned:'status/push/banned',//禁用推送配置 putPushBanned:'status/push/banned',//禁用推送配置
getPushCopy:'status/push/{configId}/copy',//复制推送配置 getPushCopy:'status/push/{configId}/copy',//复制推送配置

2
code/VideoAccess-VCMP/web/package.json

@ -7,7 +7,7 @@
"test": "mocha", "test": "mocha",
"start-vite": "cross-env NODE_ENV=developmentVite npm run start-params", "start-vite": "cross-env NODE_ENV=developmentVite npm run start-params",
"start": "cross-env NODE_ENV=development npm run start-params", "start": "cross-env NODE_ENV=development npm run start-params",
"start-params": "node server -p 5000 -u http://10.8.30.24:4000 --apiVcmpUrl http://localhost:4000 --apiAuthUrl http://10.8.30.24:4200 --apiAnxinyunUrl http://10.8.30.24:4100 --iotAuthWeb http://localhost:5200 --iotVideoServer ws://221.230.55.27:8081", "start-params": "node server -p 5000 -u http://10.8.30.34:4000 --apiVcmpUrl http://localhost:4000 --apiAuthUrl http://10.8.30.34:4200 --apiAnxinyunUrl http://10.8.30.34:4100 --iotAuthWeb http://localhost:5200 --iotVideoServer ws://221.230.55.27:8081",
"deploy": "export NODE_ENV=production&& npm run build && node server", "deploy": "export NODE_ENV=production&& npm run build && node server",
"build-dev": "cross-env NODE_ENV=development&&webpack --config webpack.config.js", "build-dev": "cross-env NODE_ENV=development&&webpack --config webpack.config.js",
"build": "export NODE_ENV=production&&webpack --config webpack.config.prod.js" "build": "export NODE_ENV=production&&webpack --config webpack.config.prod.js"

Loading…
Cancel
Save