Browse Source

控制台

dev
deartibers 2 years ago
parent
commit
367d86e0bd
  1. BIN
      web/client/assets/images/console/hong_1.png
  2. BIN
      web/client/assets/images/console/huang_1.png
  3. BIN
      web/client/assets/images/console/icon_all.png
  4. BIN
      web/client/assets/images/console/icon_offline.png
  5. BIN
      web/client/assets/images/console/icon_online.png
  6. BIN
      web/client/assets/images/console/icon_up.png
  7. BIN
      web/client/assets/images/console/icon_webpage.png
  8. BIN
      web/client/assets/images/console/lan_1.png
  9. BIN
      web/client/assets/images/console/lv_1.png
  10. BIN
      web/client/assets/images/console/member.png
  11. BIN
      web/client/assets/images/console/onGoing.png
  12. BIN
      web/client/assets/images/console/suo.png
  13. BIN
      web/client/assets/images/console/yonghu.png
  14. 263
      web/client/src/layout/components/header/index.jsx
  15. 31
      web/client/src/layout/containers/layout/index.jsx
  16. 489
      web/client/src/sections/console/containers/console.jsx
  17. 3
      web/client/src/sections/console/containers/index.js
  18. 82
      web/client/src/sections/console/containers/userCenter.jsx
  19. 10
      web/client/src/sections/console/routes.js
  20. 21
      web/client/src/sections/console/style.less
  21. 14
      web/client/src/sections/service/actions/emPush.jsx
  22. 5
      web/client/src/sections/service/actions/index.js
  23. 171
      web/client/src/sections/service/components/pushModal.jsx
  24. 506
      web/client/src/sections/service/containers/emPush.jsx
  25. 10
      web/client/src/sections/service/style.less
  26. 2
      web/client/src/utils/webapi.js

BIN
web/client/assets/images/console/hong_1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
web/client/assets/images/console/huang_1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
web/client/assets/images/console/icon_all.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
web/client/assets/images/console/icon_offline.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
web/client/assets/images/console/icon_online.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
web/client/assets/images/console/icon_up.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 619 B

BIN
web/client/assets/images/console/icon_webpage.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
web/client/assets/images/console/lan_1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
web/client/assets/images/console/lv_1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
web/client/assets/images/console/member.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
web/client/assets/images/console/onGoing.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
web/client/assets/images/console/suo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 694 B

BIN
web/client/assets/images/console/yonghu.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 924 B

263
web/client/src/layout/components/header/index.jsx

@ -6,133 +6,160 @@ import { IconTreeTriangleDown } from '@douyinfe/semi-icons';
import "./index.less";
const Header = (props) => {
const { dispatch, history, user, actions, socket, headerItems, tochange } = props;
const { dispatch, history, user, actions, socket, headerItems, tochange } = props;
return (
<>
<div id="top-slider">
<Nav
mode={"horizontal"}
onClick={({ itemKey }) => {
if (itemKey == "logout") {
dispatch(actions.auth.logout(user));
if (socket) {
socket.disconnect();
}
history.push(`/signin`);
}
}}
style={{
height: 48,
minWidth: 520,
background: '#1D2343',
backgroundSize: "100% 100%",
color: "white",
}}
header={{
logo: (
<img
src="/assets/images/install/long_logo.png"
style={{ display: "inline-block", width: 200, height: 40, marginLeft: -24 }}
/>
),
text: (
<>
{/* <SplitButtonGroup style={{ marginLeft: 10 }} aria-label="项目操作按钮组"> */}
<Button theme="solid" type="primary" style={{ width: 52, height: 24, background: '#005ABD' }}>全局</Button>
{/* <Dropdown onVisibleChange={(v) => { }} menu={{}} trigger="click" position="bottomRight"> */}
<Button style={{ width: 16, height: 24, background: '#005ABD' }} theme="solid" type="primary" icon={<IconTreeTriangleDown />}></Button>
{/* </Dropdown> */}
{/* </SplitButtonGroup> */}
</>
),
}}
footer={
<>
{headerItems.map((item, index) => {
if (item.hasOwnProperty('items')) {
return (
<Nav.Sub
key={index + 'a'}
itemKey={item.itemKey}
text={item.text}
dropdownStyle={{ color: '#F2F3F5' }}
>
{item.hasOwnProperty('items') && item.items.map((ite, idx) => (
<Nav.Item key={idx + 'd'} itemKey={ite.itemKey} text={ite.text} onClick={() => { tochange(ite); }} />
))}
</Nav.Sub>
)
return (
<>
<div id="top-slider">
<Nav
mode={"horizontal"}
onClick={({ itemKey }) => {
if (itemKey == "logout") {
dispatch(actions.auth.logout(user));
if (socket) {
socket.disconnect();
}
history.push(`/signin`);
}
else {
return (
<div key='console' style={{display:'inline-flex'}}>
<img src="/assets/images/background/console.png" style={{ width: 24, marginRight: -10 }} />
<Nav.Item key={index + 'a'} itemKey={item.itemKey} text={item.text} onClick={() => { tochange(item) }} />
</div>
}}
style={{
height: 48,
minWidth: 520,
background: '#1D2343',
backgroundSize: "100% 100%",
color: "white",
}}
header={{
logo: (
<img
src="/assets/images/install/long_logo.png"
style={{ display: "inline-block", width: 200, height: 40, marginLeft: -24 }}
/>
),
text: (
<>
)
}
})}
<Nav.Sub
itemKey={"user"}
text={
<div
style={{
marginLeft: -8,
display: "inline-block",
color: "white",
}}
>
<Avatar size="extra-small" color="light-blue" style={{ marginRight: 4 }}>
{user?.name?.substr(0, 1)}
</Avatar>
<div style={{
display: "inline-block", position: "relative",
top: 10,
left: 4,
marginRight: 4,
}}
>
</div>
</div>
}
>
<div style={{ width: 200, padding: 16, background: '#c7bebeeb' }}>
<div style={{ display: "flex" }}>
<Avatar size="default" color="light-blue" style={{ marginRight: 4 }}>
{user?.name?.substr(0, 1)}
</Avatar>
<div style={{ fontSize: 12 }}>
{user.name}
<div title={user?.department?.map(v => v.name + '、')} style={{ width: 100, overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis' }}>{user?.department?.map(v => v.name + '、')}</div>
</div>
</div>
<div>用户中心</div>
<div>安全认证</div>
</div>
<Nav.Item itemKey={"logout"} text={"退出"} style={{ textAlign: "center" }} />
{/* <SplitButtonGroup style={{ marginLeft: 10 }} aria-label="项目操作按钮组"> */}
<Button theme="solid" type="primary" style={{ width: 52, height: 24, background: '#005ABD' }}>全局</Button>
{/* <Dropdown onVisibleChange={(v) => { }} menu={{}} trigger="click" position="bottomRight"> */}
<Button style={{ width: 16, height: 24, background: '#005ABD' }} theme="solid" type="primary" icon={<IconTreeTriangleDown />}></Button>
{/* </Dropdown> */}
{/* </SplitButtonGroup> */}
</>
),
}}
footer={
<>
{headerItems.map((item, index) => {
if (item.hasOwnProperty('items')) {
return (
<Nav.Sub
key={index + 'a'}
itemKey={item.itemKey}
text={item.text}
dropdownStyle={{ color: '#F2F3F5' }}
>
{item.hasOwnProperty('items') && item.items.map((ite, idx) => (
<Nav.Item key={idx + 'd'} itemKey={ite.itemKey} text={ite.text} onClick={() => { tochange(ite); }} />
))}
</Nav.Sub>
)
}
else {
return (
<div key='console' style={{ display: 'inline-flex' }}>
<img src="/assets/images/background/console.png" style={{ width: 24, marginRight: -10 }} />
<Nav.Item key={index + 'a'} itemKey={item.itemKey} text={item.text} onClick={() => { tochange(item) }} />
</div>
)
}
})}
<Nav.Sub
itemKey={"user"}
text={
<div
style={{
marginLeft: -8,
display: "inline-block",
color: "white",
}}
>
<Avatar size="extra-small" color="light-blue" style={{ marginRight: 4 }}>
{user?.name?.substr(0, 1)}
</Avatar>
<div style={{
display: "inline-block", position: "relative",
top: 10,
left: 4,
marginRight: 4,
}}
>
</div>
</div>
}
>
<div style={{ width: 133, }}>
<div style={{ display: "flex", alignItems: 'center', background: '#F0F5FF', padding: '8px 0px 8px 12px' }}>
<Avatar size="extra-small" color="light-blue" style={{ marginRight: 4 }}>
{user?.name?.substr(0, 1)}
</Avatar>
<div style={{ fontSize: 12, color: '#4A4A4A' }}>
{user.name}
<div title={user?.department?.map(v => v.name + '、')} style={{ width: 60, overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis', color: '#969799', fontSize: 12 }}>{user?.department?.map(v => v.name + '、')}</div>
</div>
</div>
</div>
<div style={{ display: 'flex', alignItems: 'center', height: 30, borderBottom: '1px solid #F2F3F5', cursor: "pointer" }}
onClick={() => {
history.push(`/userCenter`);
}}>
<div style={{ width: 15, height: 15, marginLeft: 20 }}>
<img src="/assets/images/console/yonghu.png" alt="" style={{ width: '100%', height: '100%' }} />
</div>
<div style={{ color: '#646566', fontSize: 12, marginLeft: 9 }}>
用户中心
</div>
</div>
<div style={{ display: 'flex', alignItems: 'center', height: 30, borderBottom: '1px solid #F2F3F5', cursor: "pointer" }}>
<div style={{ width: 15, height: 15, marginLeft: 20 }}>
<img src="/assets/images/console/suo.png" alt="" style={{ width: '100%', height: '100%' }} />
</div>
<div style={{ color: '#646566', fontSize: 12, marginLeft: 9 }}>
安全认证
</div>
</div>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: 27, color: '#646566', fontSize: 12, cursor: "pointer" }}
onClick={() => {
dispatch(actions.auth.logout(user));
if (socket) {
socket.disconnect();
}
history.push(`/signin`);
}}>
退出
{/* <Nav.Item itemKey={"logout"} text={"退出"} style={{ textAlign: "center" }} /> */}
</div>
{/* collapseButton collapseText */}
{/* collapseButton collapseText */}
</Nav.Sub>
</>
}
/>
</div>
</>
);
</Nav.Sub>
</>
}
/>
</div>
</>
);
};
function mapStateToProps (state) {
const { global, auth, webSocket } = state;
return {
actions: global.actions,
user: auth.user,
socket: webSocket.socket,
};
const { global, auth, webSocket } = state;
return {
actions: global.actions,
user: auth.user,
socket: webSocket.socket,
};
}
export default connect(mapStateToProps)(Header);

31
web/client/src/layout/containers/layout/index.jsx

@ -9,6 +9,7 @@ import Footer from '../../components/footer';
import { resize } from '../../actions/global';
import * as NProgress from 'nprogress';
import PerfectScrollbar from 'perfect-scrollbar';
import { useLocation } from "react-router";
NProgress.configure({
template: `
@ -22,7 +23,7 @@ NProgress.configure({
});
let scrollbar
// const location111 = useLocation();
const LayoutContainer = props => {
const {
dispatch, msg, user, copyright, children, sections, clientWidth, clientHeight,
@ -116,7 +117,7 @@ const LayoutContainer = props => {
if (lastSelectedKeys) {//
for (let i = 0; i < nextItems.length; i++) {
if (JSON.parse(lastSelectedKeys)[0] == nextItems[i].itemKey) {
let openArr = []
for (let j = 0; j < nextItems[i].items.length; j++) {
openArr.push(nextItems[i].items[j].itemKey)
@ -137,6 +138,30 @@ const LayoutContainer = props => {
}
}, [])
useEffect(() => {
let pathnameArr = location.pathname.split('/')
let openArr = []
for (let i = 0; i < allItems.length; i++) {
if (allItems[i].items) {
for (let j = 0; j < allItems[i].items.length; j++) {
if (allItems[i].items[j].items) {
for (let k = 0; k < allItems[i].items[j].items.length; k++) {
if (allItems[i].items[j].items[k].to == location.pathname) {
for (let o = 0; o < allItems[i].items.length; o++) {
openArr.push(allItems[i].items[o].itemKey)
}
localStorage.setItem('poms_selected_sider', JSON.stringify([pathnameArr[1]]))
localStorage.setItem('poms_open_sider', JSON.stringify(openArr))
setLeftItems(allItems[i].items)
setLeftShow(true)
}
}
}
}
}
}
}, [location])
useEffect(() => {
NProgress.done();
if ((!user || !user.authorized)) {
@ -173,7 +198,7 @@ const LayoutContainer = props => {
// websocket 使
useEffect(() => {
// console.log(socket)
// console.log(socket)
if (socket) {
socket.on('CAMERA_ONLINE', function (msg) {
console.info(msg);

489
web/client/src/sections/console/containers/console.jsx

@ -1,16 +1,87 @@
import React, { useEffect } from 'react';
import React, { useEffect, useState } from 'react';
import { connect } from 'react-redux';
import { Spin, Card } from '@douyinfe/semi-ui';
import { Timeline, Card, Button } from '@douyinfe/semi-ui';
import { push } from 'react-router-redux';
import '../style.less'
import PerfectScrollbar from "perfect-scrollbar";
const { Meta } = Card;
let newScrollbar;
let overviewScrollbar;
let memberScrollbar;
let equipmentScrollbar;
let webScrollbar;
let problemsScrollbar;
const Console = (props) => {
const { dispatch, actions, user, loading, socket } = props
const stationList = [
'url(/assets/images/console/lan_1.png)',
'url(/assets/images/console/lv_1.png)',
'url(/assets/images/console/huang_1.png)',
'url(/assets/images/console/hong_1.png)'
]
const [timelineList, setTimelineList] = useState(['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''])//
const [memberList, setMemberList] = useState(['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''])//
const [equipmentList, setEquipmentList] = useState(['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''])//
const [webList, setWebList] = useState(['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''])//web
const [problemsList, setProblemsList] = useState(['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''])//&
useEffect(() => {
// ACTION
// dispatch(actions.example.getMembers(user.orgId))
}, [])
useEffect(() => {
newScrollbar = new PerfectScrollbar("#news", {
suppressScrollX: true,
});
const domProject = document.getElementById("news");
if (domProject && newScrollbar) {
newScrollbar.update();
}
overviewScrollbar = new PerfectScrollbar("#overview", {
suppressScrollY: true,
});
const domProject1 = document.getElementById("overview");
if (domProject1 && overviewScrollbar) {
overviewScrollbar.update();
}
memberScrollbar = new PerfectScrollbar("#member", {
suppressScrollX: true,
});
const domProject2 = document.getElementById("member");
if (domProject2 && memberScrollbar) {
memberScrollbar.update();
}
equipmentScrollbar = new PerfectScrollbar("#equipment", {
suppressScrollX: true,
});
const domProject3 = document.getElementById("equipment");
if (domProject3 && equipmentScrollbar) {
equipmentScrollbar.update();
}
webScrollbar = new PerfectScrollbar("#web", {
suppressScrollX: true,
});
const domProject4 = document.getElementById("web");
if (domProject4 && webScrollbar) {
webScrollbar.update();
}
problemsScrollbar = new PerfectScrollbar("#problems", {
suppressScrollX: true,
});
const domProject5 = document.getElementById("problems");
if (domProject5 && problemsScrollbar) {
problemsScrollbar.update();
}
// ACTION
// dispatch(actions.example.getMembers(user.orgId))
})
// websocket 使
// useEffect(() => {
@ -28,8 +99,418 @@ const Console = (props) => {
return (
<>
<div>
<img src="/assets/images/install/watting.png" alt="" style={{ width: 'calc(100% + 16px)', position: "relative",top: -12, left: -8, }} />
<div style={{ padding: '0px 40px' }} className='console'>
{/* 头部 */}
<div style={{ margin: '4px 0px 14px', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
<div style={{ display: 'flex', alignItems: 'center' }}>
<div style={{ color: '#4A4A4A', fontSize: 14 }}>
HI欢迎回来行业服务部
</div>
<div style={{ fontFamily: 'YouSheBiaoTiHei', fontSize: 20, color: '#005ABD', marginLeft: 4 }}>
刘昊然
</div>
</div>
<div style={{ width: 25, height: 25, cursor: "pointer" }}>
<img src="/assets/images/console/icon_all.png" alt="" style={{ width: '100%', height: '100%' }} />
</div>
</div>
{/* 主体 */}
<div style={{ display: 'flex' }}>
{/* 左边 */}
<div style={{ width: 1464 }}>
{/* 工作台和统计概览 */}
<div style={{ background: '#FFFFFF', boxShadow: '0px 0px 12px 2px rgba(220,222,224,0.2)', borderRadius: 2, paddingTop: 20, paddingLeft: 24 }}>
{/* 我的工作台 */}
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
<div style={{ display: 'flex', alignItems: 'center' }}>
<div style={{ width: 0, height: 20, borderLeft: '3px solid #005ABD', borderTop: '3px solid transparent', borderBottom: '3px solid transparent' }}></div>
<div style={{ fontFamily: "YouSheBiaoTiHei", fontSize: 24, color: '#101531', marginLeft: 8 }}>我的工作台</div>
<div style={{ marginLeft: 6, fontSize: 12, color: '#969799', fontFamily: "DINExp", }}>MY WORK STATION</div>
</div>
<div style={{ marginRight: 25 }}>
<img title='设置' src="/assets/images/problem/setup.png" style={{ width: 18, height: 18, cursor: "pointer" }} onClick={() => setSetup(true)} />
</div>
</div>
<div style={{ marginTop: 30, display: 'flex' }}>
<div style={{ marginTop: 20, marginLeft: 36 }}>
<div style={{ display: 'flex', alignItems: 'center', }}>
<div style={{ width: 120, fontSize: 14, color: '#969799' }}>
剩余问题:
</div>
<div style={{ fontSize: 16, color: '#4A4A4A', width: 91 }}>
122
</div>
</div>
<div style={{ display: 'flex', alignItems: 'center', marginTop: 26 }}>
<div style={{ width: 120, fontSize: 14, color: '#969799' }}>
今日新增问题:
</div>
<div style={{ fontSize: 16, color: '#4A4A4A', width: 91, display: 'flex' }}>
<div>
12223
</div>
<div style={{ display: 'flex', alignItems: 'center', marginLeft: 4 }}>
<img title='设置' src="/assets/images/console/icon_up.png" style={{ width: 18, height: 18 }} />
</div>
</div>
</div>
<div style={{ display: 'flex', alignItems: 'center', marginTop: 26 }}>
<div style={{ width: 120, fontSize: 14, color: '#969799' }}>
今日处理:
</div>
<div style={{ fontSize: 16, color: '#4A4A4A', width: 91 }}>
3
</div>
</div>
</div>
{/* 循环类型 */}
{
stationList.map((item, index) => {
return (
<div key={item} style={{ background: item, backgroundSize: "100% 100%", width: 270, height: 135, marginRight: 26 }}>
<div style={{ margin: '35px 0px 0px 134px' }}>
<div>
<span style={{ fontSize: 14, color: '#4A4A4A' }}>关注的项目</span>
<span style={{ fontSize: 12, color: '#4A4A4A' }}>()</span>
</div>
<div style={{ marginTop: 15, display: 'flex', alignItems: 'center' }}>
<div style={{ fontSize: 32, color: index == 0 ? '#0F7EFB' : index == 1 ? '#0091A1' : index == 2 ? '#FE9812' : '#FF7575', fontFamily: 'YouSheBiaoTiHei' }}>112</div>
<div style={{ fontSize: 12, color: '#969799', marginLeft: 4 }}>进行中</div>
</div>
</div>
</div>
)
})
}
</div>
{/* 统计概览 */}
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginTop: 25 }}>
<div style={{ display: 'flex', alignItems: 'center' }}>
<div style={{ width: 0, height: 20, borderLeft: '3px solid #005ABD', borderTop: '3px solid transparent', borderBottom: '3px solid transparent' }}></div>
<div style={{ fontFamily: "YouSheBiaoTiHei", fontSize: 24, color: '#101531', marginLeft: 8 }}>统计概览</div>
<div style={{ marginLeft: 6, fontSize: 12, color: '#969799', fontFamily: "DINExp", }}>STATISTICAL OVERVIEW</div>
</div>
<div style={{ marginRight: 25 }}>
<img title='设置' src="/assets/images/problem/setup.png" style={{ width: 18, height: 18, cursor: "pointer" }} onClick={() => setSetup(true)} />
</div>
</div>
<div id='overview' style={{ position: 'relative' }}>
<div style={{ display: 'inline-flex', marginTop: 16 }}>
{/* 项目里程碑 */}
<div style={{ marginBottom: 30, width: 466, height: 221, border: '1px solid rgba(220,222,224,0.2)', boxShadow: '0px 2px 12px 1px #F2F3F5', borderRadius: 2 }}>
<div style={{ margin: '20px 0px 20px 24px', color: '#4A4A4A', fontSize: 16, fontWeight: 'bold' }}>
项目里程碑
</div>
<div style={{ display: 'flex', marginBottom: 20, marginLeft: 24 }}>
<div style={{ display: 'flex' }}>
<div style={{ fontSize: 14, color: '#969799', marginRight: 4 }}>
立项时间
</div>
<div style={{ fontSize: 14, color: '#4A4A4A', width: 104 }}>
2022-5-12
</div>
</div>
<div style={{ display: 'flex' }}>
<div style={{ fontSize: 14, color: '#969799', marginRight: 4 }}>
施工时间
</div>
<div style={{ fontSize: 14, color: '#4A4A4A' }}>
2022-5-12至2022-12-12
</div>
</div>
</div>
<div style={{ display: 'flex', marginBottom: 24, marginLeft: 24 }}>
<div style={{ display: 'flex' }}>
<div style={{ fontSize: 14, color: '#969799', marginRight: 4 }}>
内验时间
</div>
<div style={{ fontSize: 14, color: '#4A4A4A', width: 104 }}>
2023-1-18
</div>
</div>
<div style={{ display: 'flex' }}>
<div style={{ fontSize: 14, color: '#969799', marginRight: 4 }}>
外验时间
</div>
<div style={{ fontSize: 14, color: '#4A4A4A' }}>
2023-3-18
</div>
</div>
</div>
<div style={{ display: 'flex', marginBottom: 17, marginLeft: 24 }}>
<div style={{ fontSize: 14, color: '#969799', marginRight: 4 }}>
工程维保时间
</div>
<div style={{ fontSize: 14, color: '#4A4A4A' }}>
2022-11-11
</div>
</div>
<div style={{ display: 'flex', background: 'linear-gradient(252deg, #F9FBFF 0%, #DBE7FF 100%)', height: 38, justifyContent: 'space-between' }}>
<div style={{ display: 'flex', marginLeft: 24, alignItems: 'center' }}>
<div style={{ fontSize: 14, color: '#646566', marginRight: 4 }}>
售后维修时间
</div>
<div style={{ fontSize: 14, color: '#4A4A4A' }}>
2022-11-11至2023-12-14
</div>
</div>
<img src="/assets/images/console/onGoing.png" alt="进行中" />
</div>
</div>
{/* 相关成员 */}
<div style={{ width: 360, height: 221, marginLeft: 20, paddingLeft: 24, border: '1px solid rgba(220,222,224,0.2)', boxShadow: '0px 2px 12px 1px #F2F3F5', borderRadius: 2 }}>
<div style={{ margin: '20px 0px 17px 0px', color: '#4A4A4A', fontSize: 16, fontWeight: 'bold' }}>
相关成员
</div>
<div id='member' style={{ position: 'relative', height: 161 }}>
{memberList.map((item, index) => {
return (
<div key={index+'member'} style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 15 }}>
<div style={{ display: 'flex', alignItems: 'center' }}>
<div style={{ width: 18, height: 18 }}>
<img src="/assets/images/console/member.png" alt="成员" style={{ width: '100%', height: '100%' }} />
</div>
<div style={{ marginLeft: 8, fontSize: 14, color: '#4A4A4A' }}>
刘昊然
</div>
<div style={{ fontSize: 12, color: '#969799' }}>
负责人
</div>
</div>
<div style={{ color: '#969799', fontSize: 14, marginRight: 22 }}>
行业服务部
</div>
</div>
)
})}
</div>
</div>
{/* 平台设备接入 */}
<div style={{ width: 360, height: 221, marginLeft: 20, paddingLeft: 24, border: '1px solid rgba(220,222,224,0.2)', boxShadow: '0px 2px 12px 1px #F2F3F5', borderRadius: 2 }}>
<div style={{ margin: '20px 0px 17px 0px', color: '#4A4A4A', fontSize: 16, fontWeight: 'bold', marginBottom: 16 }}>
平台设备接入
</div>
<div id='equipment' style={{ position: 'relative', height: 161 }}>
{
equipmentList.map((item, index) => {
return (
<div key={index+'equipment'} style={{ marginBottom: 15, display: 'flex' }}>
<div style={{ color: '#969799', fontSize: 14, width: 167 }}>
5阶ZK1高清摄球机
</div>
<div style={{ color: '#4A4A4A', fontSize: 14, width: 81 }}>
视频
</div>
<div style={{ width: 18, height: 18, marginRight: 8 }}>
<img src="/assets/images/console/icon_online.png" alt="网络" style={{ width: '100%', height: '100%' }} />
{/* <img src="/assets/images/console/icon_offline.png" alt="网络" style={{ width: '100%', height: '100%' }} /> */}
</div>
<div style={{ color: '#0F7EFB', fontSize: 14 }}>
在线
</div>
{/* <div style={{color:'#969799',fontSize:14}}>
掉线
</div> */}
</div>
)
})
}
</div>
</div>
{/* 关联web应用 */}
<div style={{ width: 360, height: 221, marginLeft: 20, paddingLeft: 24, border: '1px solid rgba(220,222,224,0.2)', boxShadow: '0px 2px 12px 1px #F2F3F5', borderRadius: 2 }}>
<div style={{ margin: '20px 0px 17px 0px', color: '#4A4A4A', fontSize: 16, fontWeight: 'bold', marginBottom: 15 }}>
关联web应用
</div>
<div id='web' style={{ position: 'relative', height: 161 }}>
{
webList.map((item, index) => {
return (
<div key={index+'web'} style={{ marginBottom: 15, display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
<div style={{ display: 'flex' }}>
<div style={{ width: 18, height: 18, marginRight: 8 }}>
<img src="/assets/images/console/icon_webpage.png" alt="web应用" style={{ width: '100%', height: '100%' }} />
</div>
<div style={{ color: '#646566', fontSize: 14, borderBottom: '1px dotted #0F7EFB' }}>
superchangnan.anxiny
</div>
</div>
<div style={{ color: '#4A4A4A', fontSize: 14, marginRight: 40 }}>
第三方
</div>
</div>
)
})
}
</div>
</div>
{/* 异常&问题 */}
<div style={{ width: 399, height: 221, marginLeft: 20, marginRight: 20, paddingLeft: 24, border: '1px solid rgba(220,222,224,0.2)', boxShadow: '0px 2px 12px 1px #F2F3F5', borderRadius: 2 }}>
<div style={{ margin: '20px 0px 17px 0px', color: '#4A4A4A', fontSize: 16, fontWeight: 'bold' }}>
异常&问题
</div>
<div id='problems' style={{ position: 'relative', height: 161 }}>
{
problemsList.map((item, index) => {
return (
<div style={{ marginBottom: 15, paddingRight: 30, }}>
<div style={{ fontSize: 14, color: '#646566' }}>
告警源A数据信息中断诊断为 <span style={{ color: '#0F7EFB', borderBottom: '1px dotted #0F7EFB', cursor: "pointer" }}>服务异常请前往确认</span>
</div>
<div style={{ color: '#969799', fontSize: 12, marginRight: 40, marginTop: 4 }}>
2022-05-21 15:23:41
</div>
</div>
)
})
}
</div>
</div>
</div>
</div>
</div>
<div style={{ background: '#FFFFFF', boxShadow: '0px 0px 12px 2px rgba(220,222,224,0.2)', borderRadius: 2, paddingTop: 20, paddingLeft: 24, marginTop: 22 }}>
{/* BI分析模块 */}
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
<div style={{ display: 'flex', alignItems: 'center' }}>
<div style={{ width: 0, height: 20, borderLeft: '3px solid #005ABD', borderTop: '3px solid transparent', borderBottom: '3px solid transparent' }}></div>
<div style={{ fontFamily: "YouSheBiaoTiHei", fontSize: 24, color: '#101531', marginLeft: 8 }}>我的工作台</div>
<div style={{ marginLeft: 6, fontSize: 12, color: '#969799', fontFamily: "DINExp", }}>MY WORK STATION</div>
</div>
<div style={{ marginRight: 25 }}>
<img title='设置' src="/assets/images/problem/setup.png" style={{ width: 18, height: 18, cursor: "pointer" }} onClick={() => setSetup(true)} />
</div>
</div>
</div>
</div>
{/* 右边 */}
<div style={{ width: 365, marginLeft: 20 }}>
{/* 最新动态 */}
<div style={{ background: '#FFFFFF', boxShadow: '0px 0px 12px 2px rgba(220,222,224,0.2)', borderRadius: 2, paddingTop: 20, paddingLeft: 21, height: 639, }}>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
<div style={{ display: 'flex', alignItems: 'center' }}>
<div style={{ width: 0, height: 20, borderLeft: '3px solid #005ABD', borderTop: '3px solid transparent', borderBottom: '3px solid transparent' }}></div>
<div style={{ fontFamily: "YouSheBiaoTiHei", fontSize: 24, color: '#101531', marginLeft: 8 }}>最新动态</div>
<div style={{ marginLeft: 6, fontSize: 12, color: '#969799', fontFamily: "DINExp", }}>RECENT NEWS</div>
</div>
<div style={{ marginRight: 25 }}>
<img title='设置' src="/assets/images/problem/setup.png" style={{ width: 18, height: 18, cursor: "pointer" }} onClick={() => setSetup(true)} />
</div>
</div>
<div id='news' style={{ height: 578, position: 'relative', marginTop: 10, }}>
<Timeline mode="center" style={{ marginLeft: '-56px' }}>
{timelineList.map((item, index) => {
return (
<Timeline.Item key={index+'time'} time="2019-07-14 10:35" className={index % 2 == 0 ? 'even' : 'odd'} >
A项目DTU设备状态异常诊断为离线
</Timeline.Item>
)
})}
</Timeline>
</div>
</div>
{/* 我常用的工具 */}
<div style={{ marginTop: 20, background: '#FFFFFF', boxShadow: '0px 0px 12px 2px rgba(220,222,224,0.2)', borderRadius: 2, paddingTop: 20, paddingLeft: 21, height: 303 }}>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
<div style={{ display: 'flex', alignItems: 'center' }}>
<div style={{ width: 0, height: 20, borderLeft: '3px solid #005ABD', borderTop: '3px solid transparent', borderBottom: '3px solid transparent' }}></div>
<div style={{ fontFamily: "YouSheBiaoTiHei", fontSize: 24, color: '#101531', marginLeft: 8 }}>我常用的工具</div>
<div style={{ marginLeft: 6, fontSize: 12, color: '#969799', fontFamily: "DINExp", }}>MY USUAL TOOLS</div>
</div>
</div>
<div style={{ marginTop: 24 }}>
<Button
theme="solid"
type="primary"
style={{
width: 94,
height: 29,
borderRadius: 2,
marginRight: 10,
marginBottom: 15,
background: '#0F7EFB',
color: '#FFFFFF',
border: '1px solid #0F7EFB'
}}
onClick={() => {
dispatch(push('/install/authentication/roles'));
}}
>
工单管理
</Button>
<Button
theme="solid"
type="primary"
style={{
width: 94,
height: 29,
borderRadius: 2,
marginRight: 10,
marginBottom: 15,
background: '#0F7EFB',
color: '#FFFFFF',
border: '1px solid #0F7EFB'
}}
// onClick={() => { }}
>
信鸽服务
</Button>
<Button
theme="solid"
type="primary"
style={{
width: 94,
height: 29,
borderRadius: 2,
marginRight: 10,
marginBottom: 15,
background: '#0F7EFB',
color: '#FFFFFF',
border: '1px solid #0F7EFB'
}}
// onClick={() => { }}
>
数据告警
</Button>
<Button
theme="solid"
type="primary"
style={{
width: 94,
height: 29,
borderRadius: 2,
marginRight: 10,
marginBottom: 15,
background: '#0F7EFB',
color: '#FFFFFF',
border: '1px solid #0F7EFB'
}}
// onClick={() => { }}
>
项目资料
</Button>
</div>
<div style={{ marginTop: 4 }}>
<Button
theme="solid"
type="primary"
style={{
width: 302,
height: 40,
borderRadius: 2,
marginRight: 32,
background: '#F2F3F5',
color: '#0F7EFB',
border: '1px solid #F2F3F5'
}}
// onClick={() => { }}
>
添加
</Button>
</div>
</div>
</div>
</div>
</div>
</>
)

3
web/client/src/sections/console/containers/index.js

@ -1,5 +1,6 @@
'use strict';
import Console from './console';
import UserCenter from './userCenter';
export { Console };
export { Console, UserCenter };

82
web/client/src/sections/console/containers/userCenter.jsx

@ -0,0 +1,82 @@
import React, { useEffect, useState } from 'react';
import { connect } from 'react-redux';
import { Avatar, Card, Button } from '@douyinfe/semi-ui';
import { push } from 'react-router-redux';
import '../style.less'
import PerfectScrollbar from "perfect-scrollbar";
const { Meta } = Card;
const UserCenter = (props) => {
const { dispatch, actions, user, loading, socket } = props
useEffect(() => {
console.log('user',user);
// ACTION
// dispatch(actions.example.getMembers(user.orgId))
}, [])
useEffect(() => {
// ACTION
// dispatch(actions.example.getMembers(user.orgId))
})
// websocket 使
// useEffect(() => {
// console.log(socket)
// if (socket) {
// socket.on('TEST', function (msg) {
// console.info(msg);
// });
// return () => {
// socket.off("TEST");
// }
// }
// }, [socket])
return (
<>
<div style={{ padding: '0px 40px' }}>
{/* 头部 */}
<div style={{ margin: '4px 0px 14px', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
<div style={{ display: 'flex', alignItems: 'center' }}>
<div style={{ color: '#4A4A4A', fontSize: 14 }}>
HI欢迎回来行业服务部
</div>
<div style={{ fontFamily: 'YouSheBiaoTiHei', fontSize: 20, color: '#005ABD', marginLeft: 4 }}>
刘昊然
</div>
</div>
</div>
{/* 主体 */}
<div style={{ background: '#FFFFFF', boxShadow: '0px 0px 12px 2px rgba(220,222,224,0.2)', borderRadius: 2, paddingTop: 20, paddingLeft: 24 }}>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
<div style={{ display: 'flex', alignItems: 'center' }}>
<div style={{ width: 0, height: 20, borderLeft: '3px solid #005ABD', borderTop: '3px solid transparent', borderBottom: '3px solid transparent' }}></div>
<div style={{ fontFamily: "YouSheBiaoTiHei", fontSize: 24, color: '#101531', marginLeft: 8 }}>用户中心</div>
<div style={{ marginLeft: 6, fontSize: 12, color: '#969799', fontFamily: "DINExp", }}>USER CENTER</div>
</div>
</div>
<div style={{ marginTop: 42,marginLeft:70 }}>
<Avatar size="large" style={{ margin: 4,cursor:'default' }} color="light-blue" alt='User'>
{user.name.split('')[0]}
</Avatar>
</div>
</div>
{/* moment(row.createTime).format("YYYY-MM-DD HH:mm:ss") */}
</div>
</>
)
}
function mapStateToProps (state) {
const { auth, global, members, webSocket } = state;
return {
// loading: members.isRequesting,
user: auth.user,
// actions: global.actions,
// members: members.data,
// socket: webSocket.socket
};
}
export default connect(mapStateToProps)(UserCenter);

10
web/client/src/sections/console/routes.js

@ -1,5 +1,5 @@
'use strict';
import { Console, } from './containers';
import { Console,UserCenter } from './containers';
export default [{
type: 'inner',
@ -10,4 +10,12 @@ export default [{
component: Console,
// 不设置 component 则面包屑禁止跳转
}
}, {
type: 'inner',
route: {
path: "/userCenter",
key: 'userCenter',
breadcrumb: '用户中心',
component: UserCenter
}
}];

21
web/client/src/sections/console/style.less

@ -1,7 +1,18 @@
#example {
box-shadow: 3px 3px 2px black;
.even{
.semi-timeline-item-head-default{
background-color: #005ABD;
}
}
#example:hover {
color: yellowgreen;
.odd{
.semi-timeline-item-head-default{
background-color: #FFFFFF;
border: 1px solid #A4CFFF;
}
}
.semi-timeline-item-content-time{
font-size: 14px;
}
.semi-timeline-item-content{
font-size: 12px;
width: calc(59% - 14px) !important;
}

14
web/client/src/sections/service/actions/emPush.jsx

@ -0,0 +1,14 @@
'use strict';
import { ApiTable, basicAction } from '$utils'
export function getPush () { //
return dispatch => basicAction({
type: 'get',
dispatch: dispatch,
actionType: 'GET_PUSH',
url: `${ApiTable.getPush}`,
msg: { error: '获取推送配置列表失败' },
reducer: { name: '' }
});
}

5
web/client/src/sections/service/actions/index.js

@ -1,2 +1,7 @@
'use strict';
import * as emPush from './emPush'
export default {
...emPush
}

171
web/client/src/sections/service/components/pushModal.jsx

@ -0,0 +1,171 @@
import React, { useState, useRef, useEffect } from "react";
import { connect } from "react-redux";
import { Modal, Form } from "@douyinfe/semi-ui";
import { IconAlertCircle } from '@douyinfe/semi-icons';
function pushModal (props) {
const {
close,
cancel,
visible,
dispatch,
pepList,
actions,
adminEdit,//
editObj,
} = props;
const { install } = actions;
const form = useRef();//
const [disablePeople, setDisablePeople] = useState(true); //
const [peopleList, setPeopleList] = useState([]); //List
const [departmentId, setDepartmentId] = useState(); //id
const [peopleId, setPeopleId] = useState(); //id
//
useEffect(() => {
if (editObj.id) {
let departmentList = []
for (let i = 0; i < pepList.length; i++) {
if (pepList[i].id == editObj.departments[0].id) {
departmentList = pepList[i].users
}
}
setPeopleList(departmentList)
setDepartmentId(editObj.departments[0].id)
setPeopleId(editObj.pepUserId)
setDisablePeople(false)
}
}, []);
function handleOk () {
//
form.current
.validate()
.then((values) => {
if (adminEdit) {
dispatch(install.deteleOrganizationAdmin({id:editObj.id,msg:''})).then(
dispatch(install.postOrganizationUser({ role: ['admin'], pepUserId: values.pepUserId, msg: '修改管理员' })).then((res) => {//(PEP)
if (res.success) {
close();
}
})
)
}
else {
dispatch(install.postOrganizationUser({ role: ['admin'], pepUserId: values.pepUserId, msg: '新增管理员' })).then((res) => {//(PEP)
if (res.success) {
close();
}
})
}
})
}
function handleCancel () {
cancel();
//
}
return (
<>
<Modal
title="管理员设置"
okText="确定"
cancelText="取消"
visible={visible}
onOk={handleOk}
width={607}
onCancel={handleCancel}
>
<div style={{ margin: "0px 25px" }}>
<div style={{ width: '100%', height: 32, background: '#F4F8FF', borderRadius: 2, border: '1px solid #C7E1FF', display: 'flex', alignItems: 'center' }}>
<div style={{ display: 'flex', alignItems: 'center', marginLeft: 12 }}><IconAlertCircle style={{ color: '#0F7EFB' }} /></div>
<div style={{ color: '#0F7EFB', fontSize: 12, marginLeft: 8 }}>成员成为管理员后拥有平台所有权限和项目成员的普通角色会被禁用</div>
</div>
<Form
allowEmpty
labelPosition="left"
labelAlign="right"
labelWidth="90px"
onValueChange={(values, field) => {
for (var key in field) {
if (key == 'department') {
if (values.department >= 0) {
let departmentList = []
for (let i = 0; i < pepList.length; i++) {
if (pepList[i].id == values.department) {
departmentList = pepList[i].users
}
}
setPeopleList(departmentList)
setDisablePeople(false)
form.current.setValue('pepUserId', undefined);
}
else {
setPeopleList([])
setDisablePeople(true)
form.current.setValue('pepUserId', undefined);
}
}
}
}}
getFormApi={(formApi) => (form.current = formApi)}
>
<div>
<Form.Select
label="选择部门:"
field="department"
placeholder="请选择部门"
style={{ width: 417 }}
rules={[{ required: true, message: "请选择部门" }]}
initValue={departmentId || ""}
showClear
>
{
pepList.map((item, index) => {
return (
<Form.Select.Option key={index} value={item.id}>
{item.name}
</Form.Select.Option>
)
})
}
</Form.Select>
</div>
<div>
<Form.Select
label="选择人员:"
field="pepUserId"
placeholder="请选择人员"
style={{ width: 417 }}
rules={[{ required: true, message: "请选择人员" }]}
initValue={peopleId || ""}
showClear
disabled={disablePeople}
>
{
peopleList.map((item, index) => {
return (
<Form.Select.Option key={item.id} value={item.id}>
{item.name}
</Form.Select.Option>
)
})
}
</Form.Select>
</div>
</Form>
</div>
</Modal>
</>
);
}
function mapStateToProps (state) {
const { auth, global, members } = state;
return {
// loading: members.isRequesting,
user: auth.user,
actions: global.actions,
// members: members.data,
};
}
export default connect(mapStateToProps)(pushModal);

506
web/client/src/sections/service/containers/emPush.jsx

@ -1,34 +1,498 @@
import React, { useEffect } from 'react';
import React, { useEffect, useRef, useState } from 'react';
import { connect } from 'react-redux';
import { Skeleton, Button, Pagination, Form, Popconfirm, Table } from '@douyinfe/semi-ui';
import { SkeletonScreen, } from "$components";
import moment from "moment";
import pushModal from '../components/pushModal'
import '../style.less'
import { Setup } from "$components";
// import { set } from 'nprogress';
const EmPush = (props) => {
const form = useRef();//
const { dispatch, actions, user, loading, socket } = props
const { service } = actions;
const [setup, setSetup] = useState(false); //
const [setupp, setSetupp] = useState([]);//
const [tableSetup, setTableSetup] = useState([]); //
const [query, setQuery] = useState({ limit: 10, page: 0 }); //
const [limits, setLimits] = useState()//
const mylimits = useRef(); //
const [selected, setSelected] = useState([]) //
const [pushModal, setPushModal] = useState(false) //
const [systemEdit, setSystemEdit] = useState(false) //
const [anxincloudList, setAnxincloudList] = useState([]) //
const [peplist, setPeplist] = useState([]) //PEP
const [appList, setAppList] = useState([]) //
const [pepProjectId, setPepProjectId] = useState() //id
const [anxincloudArr, setAnxincloudArr] = useState([]) //
const [pepname, setPepname] = useState() //
const [anxinDelete, setAnxinDelete] = useState([]) //,
const [appArr, setAppArr] = useState([]) //
const [bindId, setBindId] = useState() //id
const [tableKey, setTableKey] = useState([]) //id
const page = useRef(query.page);//
const EMPUSH = "empush";
const tableList = [//
{
title: '推送信息',
list: [
{ name: "策略类型", value: "pushWay" },
{ name: "推送机制", value: "noticeWay" },
{ name: "监听设备数量", value: "monitorCount" },
{ name: "累计推送次数", value: "logCount" },
]
},
];
const Server = (props) => {
const { dispatch, actions, user, loading, socket } = props
useEffect(() => {
function handleRow (record, index) {//
//
if (index % 2 === 0) {
return {
style: {
background: '#FAFCFF',
}
};
} else {
return {};
}
}
}, [])
const [tableData, setTableData] = useState([]) //
useEffect(() => {
attribute();
dispatch(service.getPush(query)).then((res) => {//
console.log('res.payload.datares.payload.data',res.payload.data);
// setAnxincloudList(res.payload.data)
})
// dispatch(install.getProjectPmanage(query)).then((res) => {//PEP
// setPeplist(res.payload.data)
// })
// dispatch(install.getProjectAppList(query)).then((res) => {//
// setAppList(res.payload.data)
// })
localStorage.getItem(EMPUSH) == null
? localStorage.setItem(
EMPUSH,
JSON.stringify(['pushWay','noticeWay','logCount','monitorCount'])
)
: "";
}, [])
useEffect(() => {
// getProjectPomsList();
}, [query]);
return (
<>
<div>
<img src="/assets/images/install/watting.png" alt="" style={{ width: 'calc(100% + 16px)', position: "relative", top: -12, left: -8, }} />
</div>
</>
)
function getProjectPomsList () {
// dispatch(install.getProjectPoms(query)).then((res) => {//
// if (res.success) {
// let mytableData = JSON.parse(JSON.stringify(res.payload.data.rows));
// let mytableKey = []
// for (let index = 0; index < mytableData.length; index++) {
// mytableData[index].key = mytableData[index].id
// mytableKey.push(mytableData[index].id)
// }
// setTableKey(mytableKey)
// setTableData(mytableData)
// setLimits(res.payload.data.count)
// mylimits.current = res.payload.data.rows.length
// }
// })
}
const [columns, setColumns] = useState([//
{
title: "策略编号",
dataIndex: "index",
key: 'index',
render: (text, r, index) => {
return index + 1;
},
},
{
title: '策略名称',
dataIndex: "pepProjectName",
key: 'pepProjectName',
render: (_, row) => {
return row.pepProjectName
}
},
{
title: "操作",
width: "20%",
dataIndex: "text",
key: 'text',
render: (_, row) => {
return (
<div style={{ display: "flex" }}>
<Button
theme="borderless"
// disabled={row.pepProjectIsDelete == 1}
// onClick={() => {
// setPushModal(true);
// setPepname(row.name)
// if (!row.name) {
// setPepProjectId(row.pepProjectId)
// }
// else {
// setPepProjectId()
// }
// let myanxinArr = []
// let anxinErrorList = []
// for (let i = 0; i < row.anxinProject.length; i++) {
// if (row.anxinProject[i].projectState !== -1) {
// myanxinArr.push(row.anxinProject[i].id)
// }
// else {
// anxinErrorList.push(row.anxinProject[i].name)
// }
// }
// setAnxinDelete(anxinErrorList)
// let myapparr = []
// let myarrarrList = JSON.parse(JSON.stringify(row.apps))
// for (let j = 0; j < row.apps.length; j++) {
// delete myarrarrList[j].projectApp
// myapparr.push(JSON.stringify(myarrarrList[j]))
// }
// setAppArr(myapparr)
// setAnxincloudArr(myanxinArr)
// setBindId(row.id)
// setSystemEdit(true)
// }}
>
修改
</Button>
<Button theme="borderless">禁用</Button>
<Popconfirm
title="删除后对应的项目全局将无法进入和显示,对应的信鸽服务也会被禁用"
arrowPointAtCenter={false}
showArrow={true}
position="topRight"
onConfirm={() => {
// dispatch(install.deleteProjectBind({ bindId: row?.id, msg: '' })).then(() => {
// if (page.current > 0 && mylimits.current < 2) {
// setQuery({ limit: 10, page: page.current - 1 })
// } else {
// setQuery({ limit: 10, page: page.current })
// }
// })
}}
>
<Button theme="borderless">删除</Button>
</Popconfirm>
</div>
);
},
},
])
const rowSelection = {
selectedRowKeys: selected,
onChange: (selectedRowKeys, selectedRows) => {
setSelected(selectedRows.map(v => v.key))
},
}
//
function attribute () {
const arr = localStorage.getItem(EMPUSH)
? JSON.parse(localStorage.getItem(EMPUSH))
: [];
const column = [
{
title: "关联项目",
dataIndex: "noticeWay",
key: "noticeWay",
render: (_, r, index) => {
return r.noticeWay;
},
},
{
title: "创建时间",
dataIndex: "logCount",
key: "logCount",
render: (_, r, index) => {
return (r.logCount + '次')
},
},
{
title: "接收人",
dataIndex: "monitorCount",
key: "monitorCount",
render: (_, r, index) => {
return r.monitorCount
},
},
{
title: "监听问题",
dataIndex: "pushWay",
key: "pushWay",
render: (_, r, index) => {
return r.pushWay=='email' ? '邮件通知' : '短信通知';
},
},
{
title: "通知时效",
dataIndex: "text1",
key: "text1",
render: (_, r, index) => {
return r.text1
},
},
{
title: "启用状态",
dataIndex: "text2",
key: "text2",
render: (_, r, index) => {
return r.text2
},
},
{
title: "推送次数",
dataIndex: "time",
key: "time",
render: (_, r, index) => {
return r.time
},
},
];
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);
}
return (
<>
<div style={{ background: '#FFFFFF', margin: '8px 12px', padding: '20px 20px 0px 20px' }}>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
<div style={{ display: 'flex', alignItems: 'center' }}>
<div style={{ width: 0, height: 20, borderLeft: '3px solid #005ABD', borderTop: '3px solid transparent', borderBottom: '3px solid transparent' }}></div>
<div style={{ fontFamily: "YouSheBiaoTiHei", fontSize: 24, color: '#101531', marginLeft: 8 }}>EM推送</div>
<div style={{ marginLeft: 6, fontSize: 12, color: '#969799', fontFamily: "DINExp", }}>Em push</div>
</div>
<div style={{ marginRight: 20, display: 'flex', alignItems: 'center' }} className='empush'>
<Form
onSubmit={(values) => console.log(values)}
// onValueChange={values=>console.log(values)}
getFormApi={(formApi) => (form.current = formApi)}
layout="horizontal"
style={{ position: "relative", width: "100%", flex: 1 }}
>
<Form.Input
label='搜索:'
field='seacth'
maxLength="16"
placeholder="搜项目、结构物或推送策略名"
labelPosition="left"
style={{ width: 292, marginRight: 10, marginBottom: 16 }}
/>
<Form.Select
label='推送类型:'
labelPosition="left"
field='pushType'
style={{ width: 116, marginRight: 10, color: "#F9F9F9", }}
placeholder="全部"
filter
showClear
>
{/* {.map((item) => {
return (
<Form.Select.Option key={item.value} value={item.value}>
{item.name}
</Form.Select.Option>
);
})} */}
</Form.Select>
<Form.Select
label='启用状态:'
labelPosition="left"
field='enableType'
style={{ width: 116, marginRight: 10, color: "#F9F9F9", }}
placeholder="全部"
filter
showClear
>
{/* {.map((item) => {
return (
<Form.Select.Option key={item.value} value={item.value}>
{item.name}
</Form.Select.Option>
);
})} */}
</Form.Select>
</Form>
<Button
theme="solid"
type="primary"
style={{
width: 80,
height: 32,
borderRadius: 2,
marginRight: 32,
background:'#FFFFFF',
color:'#005ABD',
border:'1px solid #005ABD'
}}
// onClick={() => { }}
>
查询
</Button>
<div style={{display: 'flex', alignItems: 'center'}}>
<img title='设置' src="/assets/images/problem/setup.png" style={{ width: 18, height: 18, cursor: "pointer" }} onClick={() => setSetup(true)} />
</div>
<Button
theme="solid"
type="primary"
style={{
width: 136,
height: 32,
borderRadius: 2,
marginLeft: 32
}}
onClick={() => {
setPushModal(true);
setSystemEdit(false)
setPepProjectId()
setPepname()
setAnxinDelete([])
setAppArr([])
setAnxincloudArr()
setBindId()
}}
>
添加推送策略
</Button>
</div>
</div>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20, marginTop: 5 }}>
<div style={{ fontSize: 12, color: '#8B8B8B' }}>预留预留预留预留预留预留预留预留预留预留预留预留预留预留预留预留预留预留预留预留预留预留</div>
</div>
<div style={{ marginTop: 20 }}>
<Skeleton
// loading={loading}
loading={false}
active={true}
placeholder={SkeletonScreen()}
>
<Table
columns={setupp.filter((s) => s)}
dataSource={tableData}
bordered={false}
empty="暂无数据"
pagination={false}
onRow={handleRow}
rowSelection={rowSelection}
/>
</Skeleton>
<div
style={{
display: "flex",
justifyContent: "space-between",
padding: "20px 20px",
}}
>
<div>
<div style={{ display: 'inline-block', lineHeight: '30px', fontSize: 13, color: 'gray' }}>勾选<span style={{ fontWeight: 400, color: '#0F7EFB', }}> {selected.length} </span>信息</div>
<Button onClick={() => {
if (selected.length == tableKey.length) {
setSelected([])
}
else {
setSelected(tableKey)
}
}} style={{ fontSize: 13, width: 93, height: 24, borderRadius: '1px', background: '#FFFFFF', border: '1px solid #0F7EFB', color: '#0F7EFB', fontWeight: 400, margin: '0 10px' }}>
{mylimits.current == selected.length ? '取消全选' : '全选'}
</Button>
<Popconfirm
title="删除后对应的项目全局将无法进入和显示,对应的信鸽服务也会被禁用"
arrowPointAtCenter={false}
showArrow={true}
position="topRight"
onConfirm={() => {
// dispatch(install.deleteProjectBind({ bindId: selected.join(','), msg: '' })).then(() => {
// if (page.current > 0 && mylimits.current == selected.length) {
// setQuery({ limit: 10, page: page.current - 1 })
// } else {
// setQuery({ limit: 10, page: page.current })
// }
// setSelected([])
// })
}}
>
<Button type='primary' theme='solid' style={{ fontSize: 13, width: 93, height: 24, borderRadius: '1px', border: '1px solid #0F7EFB', color: '#FFFFFF', fontWeight: 400, }}>批量删除</Button>
</Popconfirm>
</div>
<div style={{ display: 'flex', }}>
<span style={{ lineHeight: "30px", fontSize: 13, color: 'rgba(0,90,189,0.8)' }}>
{limits}条信息
</span>
<Pagination
className="22"
total={limits}
showSizeChanger
currentPage={query.page + 1}
pageSizeOpts={[10, 20, 30, 40]}
onChange={(currentPage, pageSize) => {
setQuery({ limit: pageSize, page: currentPage - 1 });
page.current = currentPage - 1
setSelected([])
}}
/>
</div>
</div>
</div>
</div>
{/* {//映射关系弹框
pushModal ?
<PushModal
visible={true}
anxincloudList={anxincloudList}
systemEdit={systemEdit}
peplist={peplist}
appList={appList}
pepname={pepname}
anxincloudArr={anxincloudArr}
pepProjectId={pepProjectId}
anxinDelete={anxinDelete}
appArr={appArr}
bindId={bindId}
cancel={() => {
setPushModal(false);
}}
close={() => {
setPushModal(false);
getProjectPomsList()
}} >
</PushModal> : ''
} */}
{setup ? (
<Setup
tableType={EMPUSH}
tableList={tableList}
close={() => {
setSetup(false);
attribute();
// setcameraSetup(false);
}}
/>
) : (
""
)}
</>
)
}
function mapStateToProps (state) {
const { auth, global, members, webSocket } = state;
return {
// loading: members.isRequesting,
// user: auth.user,
// actions: global.actions,
// members: members.data,
// socket: webSocket.socket
};
const { auth, global, ProjectPoms } = state;
return {
// loading: ProjectPoms.isRequesting,
user: auth.user,
actions: global.actions,
// members: members.data,
};
}
export default connect(mapStateToProps)(Server);
export default connect(mapStateToProps)(EmPush);

10
web/client/src/sections/service/style.less

@ -1,7 +1,5 @@
#example {
box-shadow: 3px 3px 2px black;
}
#example:hover {
color: yellowgreen;
.empush{
.semi-input-wrapper{
margin-bottom: 0px !important;
}
}

2
web/client/src/utils/webapi.js

@ -48,6 +48,8 @@ export const ApiTable = {
putAlarmVideoConfirm: 'alarm/video/confirm', //确认视频告警信息
getVcmpAuth: 'vcmp/auth', // 获取视频平台应用鉴权token
//服务-信鸽服务
getPush: "push", //获取推送配置列表
};
export const RouteTable = {

Loading…
Cancel
Save