8.9
This commit is contained in:
@ -47,6 +47,16 @@ export default [
|
||||
path: '/401',
|
||||
component: './401',
|
||||
},
|
||||
{
|
||||
path: '/MonitorScreen',
|
||||
routes: [
|
||||
{
|
||||
name: 'Home',
|
||||
path: '/MonitorScreen/Home',
|
||||
component: './MonitorScreen/Home',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
BIN
src/assets/screen/title_bg.png
Normal file
BIN
src/assets/screen/title_bg.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
BIN
src/assets/screen/top_bg.png
Normal file
BIN
src/assets/screen/top_bg.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 29 KiB |
BIN
src/assets/screen/warn_icon_01.png
Normal file
BIN
src/assets/screen/warn_icon_01.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
BIN
src/assets/screen/warn_icon_02.png
Normal file
BIN
src/assets/screen/warn_icon_02.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
396
src/pages/MonitorScreen/Home/index.tsx
Normal file
396
src/pages/MonitorScreen/Home/index.tsx
Normal file
@ -0,0 +1,396 @@
|
||||
import { Col, Descriptions, Radio, Row, Table } from 'antd';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import './style.less';
|
||||
import * as echarts from 'echarts';
|
||||
import warn_icon_01 from '@/assets/screen/warn_icon_01.png'
|
||||
import warn_icon_02 from '@/assets/screen/warn_icon_02.png'
|
||||
import moment from 'moment';
|
||||
|
||||
const onCell = (_: any, rowIndex: any) => ({ className: rowIndex % 2 == 0 ? "screen-table-odd-content" : "screen-table-even-content", });
|
||||
const onHeaderCell = () => ({ className: "screen-table-header", });
|
||||
|
||||
const evalColumn: any[] = [
|
||||
{
|
||||
title: '项目名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
ellipsis: true,
|
||||
onCell,
|
||||
onHeaderCell,
|
||||
},
|
||||
{
|
||||
title: '时间',
|
||||
dataIndex: 'time',
|
||||
key: 'time',
|
||||
align: 'center',
|
||||
onCell,
|
||||
onHeaderCell,
|
||||
},
|
||||
{
|
||||
title: '所属单位',
|
||||
dataIndex: 'unit',
|
||||
key: 'unit',
|
||||
align: 'center',
|
||||
ellipsis: true,
|
||||
onCell,
|
||||
onHeaderCell,
|
||||
},
|
||||
{
|
||||
title: '评标地点',
|
||||
dataIndex: 'place',
|
||||
key: 'place',
|
||||
align: 'center',
|
||||
ellipsis: true,
|
||||
onCell,
|
||||
onHeaderCell,
|
||||
},
|
||||
{
|
||||
title: '专家人数',
|
||||
dataIndex: 'number',
|
||||
key: 'number',
|
||||
align: 'center',
|
||||
onCell,
|
||||
onHeaderCell,
|
||||
},
|
||||
];
|
||||
const todayEvalColumn: any[] = [
|
||||
{
|
||||
title: '项目名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
ellipsis: true,
|
||||
width: '20%',
|
||||
onCell,
|
||||
onHeaderCell,
|
||||
},
|
||||
{
|
||||
title: '中标供应商名称',
|
||||
dataIndex: 'supplierName',
|
||||
key: 'supplierName',
|
||||
ellipsis: true,
|
||||
align: 'center',
|
||||
onCell,
|
||||
onHeaderCell,
|
||||
},
|
||||
{
|
||||
title: '拟签约金额',
|
||||
dataIndex: 'money',
|
||||
key: 'money',
|
||||
align: 'center',
|
||||
ellipsis: true,
|
||||
width: '25%',
|
||||
onCell,
|
||||
onHeaderCell,
|
||||
},
|
||||
];
|
||||
|
||||
const dataSource = [
|
||||
{
|
||||
id: '1',
|
||||
name: '中国联通集团股份有限公司',
|
||||
time: "11:00",
|
||||
unit: '北京',
|
||||
place: '评标地点',
|
||||
number: '5',
|
||||
supplierName: '通信工程局有限责任公司',
|
||||
money: '100000',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: '中国联通集团股份有限公司',
|
||||
time: "11:00",
|
||||
unit: '北京',
|
||||
place: '评标地点',
|
||||
number: '7',
|
||||
supplierName: '通信工程局有限责任公司',
|
||||
money: '100000',
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
name: '中国联通集团股份有限公司',
|
||||
time: "11:00",
|
||||
unit: '北京',
|
||||
place: '评标地点',
|
||||
number: '7',
|
||||
supplierName: '通信工程局有限责任公司',
|
||||
money: '100000',
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
name: '中国联通集团股份有限公司',
|
||||
time: "11:00",
|
||||
unit: '北京',
|
||||
place: '评标地点',
|
||||
number: '7',
|
||||
supplierName: '通信工程局有限责任公司',
|
||||
money: '100000',
|
||||
},
|
||||
{
|
||||
id: '5',
|
||||
name: '中国联通集团股份有限公司',
|
||||
time: "11:00",
|
||||
unit: '北京',
|
||||
place: '评标地点',
|
||||
number: '7',
|
||||
supplierName: '通信工程局有限责任公司',
|
||||
money: '100000',
|
||||
},
|
||||
];
|
||||
const GraphChart = (props: { type: string }) => {
|
||||
const { type } = props;
|
||||
const random = Math.random().toString();
|
||||
useEffect(() => {
|
||||
type EChartsOption = echarts.EChartsOption;
|
||||
const chartDom = document.getElementById(random)!;
|
||||
const myChart = echarts.init(chartDom);
|
||||
const categoryOption: any = {
|
||||
legend: { top: '3%', textStyle: { color: '#fff' } },
|
||||
tooltip: {},
|
||||
grid: { left: '8%', right: '4%', top: '16%', bottom: 60 },
|
||||
dataset: {
|
||||
dimensions: ['product', '专家人数', '专家签到数量'],
|
||||
source: [
|
||||
{ product: '招标项目', '专家人数': 43.3, '专家签到数量': 85.8, },
|
||||
{ product: '公开比选', '专家人数': 83.1, '专家签到数量': 73.4, },
|
||||
{ product: '公开询价', '专家人数': 86.4, '专家签到数量': 65.2, },
|
||||
{ product: '公开招募', '专家人数': 72.4, '专家签到数量': 53.9, },
|
||||
{ product: '竞争性谈判', '专家人数': 72.4, '专家签到数量': 53.9, },
|
||||
{ product: '单一来源', '专家人数': 72.4, '专家签到数量': 53.9, },
|
||||
]
|
||||
},
|
||||
xAxis: { type: 'category', axisLabel: { interval: 0, color: '#fff' } },
|
||||
yAxis: { axisLabel: { color: '#fff' } },
|
||||
// Declare several bar series, each will be mapped
|
||||
// to a column of dataset.source by default.
|
||||
series: [{ type: 'bar' }, { type: 'bar' }]
|
||||
};
|
||||
const pieOption: any = {
|
||||
legend: {
|
||||
orient: 'vertical',
|
||||
right: '3%',
|
||||
top: 'middle',
|
||||
textStyle: { color: '#fff' }
|
||||
},
|
||||
tooltip: {},
|
||||
dataset: {
|
||||
source: [
|
||||
['product', 'today', 'tomorrow', 'total'],
|
||||
['招标项目', 86.5, 92.1, 85.7],
|
||||
['公开比选', 41.1, 30.4, 65.1],
|
||||
['公开询价', 24.1, 67.2, 79.5],
|
||||
['公开招募', 55.2, 67.1, 69.2],
|
||||
['竞争性谈判', 86.4, 65.2, 82.5],
|
||||
['单一来源', 72.4, 53.9, 39.1],
|
||||
]
|
||||
},
|
||||
series: [
|
||||
{
|
||||
type: 'pie',
|
||||
radius: ['44%', '77%'],
|
||||
center: ['15%', '45%'],
|
||||
// No encode specified, by default, it is 'today'.
|
||||
label: {
|
||||
show: false,
|
||||
position: 'center'
|
||||
},
|
||||
emphasis: {
|
||||
label: {
|
||||
show: true,
|
||||
fontSize: 24,
|
||||
fontWeight: 'bold',
|
||||
color: '#fff'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'pie',
|
||||
radius: ['44%', '77%'],
|
||||
center: ['45%', '45%'],
|
||||
label: {
|
||||
show: false,
|
||||
position: 'center'
|
||||
},
|
||||
emphasis: {
|
||||
label: {
|
||||
show: true,
|
||||
fontSize: 24,
|
||||
fontWeight: 'bold',
|
||||
color: '#fff'
|
||||
}
|
||||
},
|
||||
encode: {
|
||||
itemName: 'product',
|
||||
value: 'tomorrow'
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'pie',
|
||||
radius: ['44%', '77%'],
|
||||
center: ['75%', '45%'],
|
||||
label: {
|
||||
show: false,
|
||||
position: 'center'
|
||||
},
|
||||
emphasis: {
|
||||
label: {
|
||||
show: true,
|
||||
fontSize: '20px',
|
||||
fontWeight: 'bold',
|
||||
color: '#fff'
|
||||
}
|
||||
},
|
||||
encode: {
|
||||
itemName: 'product',
|
||||
value: 'total'
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const option: EChartsOption = type == "pie" ? pieOption : categoryOption;
|
||||
myChart.setOption(option);
|
||||
}, [])
|
||||
return (
|
||||
<div id={random} style={{ width: '100%', height: '100%' }}></div>
|
||||
)
|
||||
}
|
||||
|
||||
export default () => {
|
||||
const [time, setTime] = useState<string>('');
|
||||
useEffect(() => {
|
||||
|
||||
const interval = setInterval(function () {
|
||||
const date = moment().format("YYYY-MM-DD HH:mm:ss");
|
||||
setTime(date);
|
||||
}, 1000);
|
||||
return () => {
|
||||
clearInterval(interval)
|
||||
};
|
||||
}, [])
|
||||
//异常预警
|
||||
const EarlyWarn = ({ img, name, num }: { img: string, name: string, num: string | number }) => {
|
||||
return (
|
||||
<div className='screen-warn-content'>
|
||||
<img src={img} className='screen-warn-img' />
|
||||
<div className='screen-warn-content'>
|
||||
<div className='screen-warn-num'>{num}</div>
|
||||
<div>{name}</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<div className="screen-bg">
|
||||
<div className='top-block'>
|
||||
</div>
|
||||
<div className='top'>
|
||||
<Row>
|
||||
<Col span={6}>
|
||||
<div className='top-left'>
|
||||
<span>当前时间:2022-07-14 07:00:00</span>
|
||||
</div>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<div className='top-title'>
|
||||
<span>数字化评标监控平台</span>
|
||||
</div>
|
||||
</Col>
|
||||
<Col span={6}>
|
||||
<div className='top-right'>
|
||||
<span>当前时间:{time}</span>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
<Row className="screen-content">
|
||||
<Col span={18}>
|
||||
<Row>
|
||||
<Col span={8} className='screen-right4'>
|
||||
<div className='screen-card'>
|
||||
<div className='card-title'>
|
||||
<span>今日评标专家数量</span>
|
||||
</div>
|
||||
<GraphChart type="category" />
|
||||
</div>
|
||||
<div className='screen-card screen-top8'>
|
||||
<div className='card-title'>
|
||||
<span>评标室监控</span>
|
||||
</div>
|
||||
<Descriptions size="small" column={2}>
|
||||
<Descriptions.Item label="项目名称" span={2}>监控及相关设备IT服务建设购置项目</Descriptions.Item>
|
||||
<Descriptions.Item label="标段名称">监控及相关设备IT服务建设购置项目(标段一)</Descriptions.Item>
|
||||
<Descriptions.Item label="监控设备名称">摄像头1</Descriptions.Item>
|
||||
<Descriptions.Item label="评标室名称">集团第一评标室</Descriptions.Item>
|
||||
<Descriptions.Item label="省分">北京</Descriptions.Item>
|
||||
</Descriptions>
|
||||
</div>
|
||||
</Col>
|
||||
<Col span={16} className='screen-left4 screen-right4'>
|
||||
<div className='middle-c'>
|
||||
<div className='map-bg'>
|
||||
大屏地图
|
||||
</div>
|
||||
</div>
|
||||
</Col>
|
||||
<Col span={24} className='screen-top8 screen-right4'>
|
||||
<div className='screen-card'>
|
||||
<div className='screen-graph-top'>
|
||||
<span className='screen-graph-title'>今日项目数量:50</span>
|
||||
<span className='screen-graph-title'>明日项目数量:40</span>
|
||||
<span className='screen-graph-title'>累计项目数量:500</span>
|
||||
<Radio.Group defaultValue="a" buttonStyle="solid" size='small'>
|
||||
<Radio.Button value="a">当月</Radio.Button>
|
||||
<Radio.Button value="b">年</Radio.Button>
|
||||
</Radio.Group>
|
||||
</div>
|
||||
<div className='screen-graph-chart'>
|
||||
<GraphChart type="pie" />
|
||||
</div>
|
||||
<div className='screen-graph-end'>
|
||||
<span>>>项目列表</span>
|
||||
</div>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
<Col span={6} className='screen-left4'>
|
||||
<div className='screen-card'>
|
||||
<div className='card-title'>
|
||||
<span>异常预警</span>
|
||||
</div>
|
||||
<div className='screen-warn'>
|
||||
<EarlyWarn name="陌生人预警" img={warn_icon_01} num={10} />
|
||||
<EarlyWarn name="评标室人数预警" img={warn_icon_02} num={20} />
|
||||
</div>
|
||||
</div>
|
||||
<div className='screen-card screen-top8'>
|
||||
<div className='card-title'>
|
||||
<span>评标中项目(20)</span>
|
||||
</div>
|
||||
<Table
|
||||
pagination={false}
|
||||
className="screen-table"
|
||||
rowKey="id"
|
||||
size="small"
|
||||
dataSource={dataSource}
|
||||
columns={evalColumn}
|
||||
/>
|
||||
</div>
|
||||
<div className='screen-card screen-top8'>
|
||||
<div className='card-title'>
|
||||
<span>今日中标项目信息(10)</span>
|
||||
</div>
|
||||
<Table
|
||||
pagination={false}
|
||||
className="screen-table"
|
||||
rowKey="id"
|
||||
size="small"
|
||||
dataSource={dataSource}
|
||||
columns={todayEvalColumn}
|
||||
/>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
};;
|
231
src/pages/MonitorScreen/Home/style.less
Normal file
231
src/pages/MonitorScreen/Home/style.less
Normal file
@ -0,0 +1,231 @@
|
||||
@import '~antd/lib/style/themes/default.less';
|
||||
|
||||
@screen-img-url: "~@/assets/screen";
|
||||
@screen-color: #041a6d;
|
||||
|
||||
.screen-bg {
|
||||
background: @screen-color;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
text-decoration: none;
|
||||
border: none;
|
||||
|
||||
.top-block {
|
||||
height: 1rem;
|
||||
}
|
||||
|
||||
.top {
|
||||
background-image: url('@{screen-img-url}/top_bg.png');
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
|
||||
.top-title {
|
||||
text-align: center;
|
||||
letter-spacing: 0.6rem;
|
||||
text-indent: 0.6rem;
|
||||
}
|
||||
|
||||
.top-title span {
|
||||
display: inline-block;
|
||||
color: #fff;
|
||||
font-size: xx-large;
|
||||
position: relative;
|
||||
top: -0.625rem;
|
||||
line-height: 61px;
|
||||
}
|
||||
|
||||
.top-left {
|
||||
color: #fff;
|
||||
font-size: large;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.top-right {
|
||||
.top-left;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.screen-card {
|
||||
height: calc(~"(100vh - 61px - 3rem) / 3");
|
||||
width: 100%;
|
||||
border: 1px solid rgba(255, 255, 255, 0.45);
|
||||
border-radius: 4px;
|
||||
|
||||
.card-title {
|
||||
background-image: url('@{screen-img-url}/title_bg.png');
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.card-title span {
|
||||
color: #ffcd00;
|
||||
line-height: 36px;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.screen-warn {
|
||||
display: flex;
|
||||
justify-content: space-evenly;
|
||||
align-items: center;
|
||||
height: calc(92.6% - 36px);
|
||||
}
|
||||
|
||||
.screen-table {
|
||||
margin-top: 0.5rem;
|
||||
height: calc(100% - 36px - 0.5rem);
|
||||
overflow: hidden;
|
||||
|
||||
.ant-table-container table>thead>tr:first-child th:first-child {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.ant-table-container table>thead>tr:first-child th:last-child {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.ant-table-tbody>tr.ant-table-row:hover>td {
|
||||
background: #0e3583;
|
||||
}
|
||||
|
||||
.screen-table-header {
|
||||
background: #045da8;
|
||||
color: #fff;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.screen-table-odd-content {
|
||||
.screen-table-header;
|
||||
background: #041a6d;
|
||||
color: #2adff5;
|
||||
}
|
||||
|
||||
.screen-table-even-content {
|
||||
.screen-table-odd-content;
|
||||
background: #0e3583;
|
||||
}
|
||||
}
|
||||
|
||||
.screen-graph-top {
|
||||
color: #2cdbf5;
|
||||
font-size: 1rem;
|
||||
padding-top: 0.75rem;
|
||||
|
||||
.screen-graph-title {
|
||||
display: inline-block;
|
||||
width: 30%;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.screen-graph-chart {
|
||||
height: calc(~"100% - 25px - 0.75rem");
|
||||
}
|
||||
|
||||
.screen-graph-end {
|
||||
color: #2cdbf5;
|
||||
// display: flex;
|
||||
// justify-content: flex-end;
|
||||
|
||||
// &>span {
|
||||
// width: 9%;
|
||||
// position: relative;
|
||||
// top: -6px;
|
||||
// }
|
||||
position: absolute;
|
||||
right: 4%;
|
||||
bottom: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.screen-warn-content {
|
||||
display: flex;
|
||||
justify-content: left;
|
||||
color: #fff;
|
||||
|
||||
.screen-warn-img {
|
||||
height: 56px;
|
||||
width: 56px;
|
||||
}
|
||||
|
||||
.screen-warn-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
margin-left: 0.625rem;
|
||||
}
|
||||
|
||||
.screen-warn-num {
|
||||
color: #f6c507;
|
||||
font-size: 1.6rem;
|
||||
line-height: 1.6rem;
|
||||
}
|
||||
}
|
||||
|
||||
.screen-content {
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.screen-top8 {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.screen-bottom8 {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.screen-left4 {
|
||||
padding-left: 0.25rem;
|
||||
}
|
||||
|
||||
.screen-right4 {
|
||||
padding-right: 0.25rem;
|
||||
}
|
||||
|
||||
.middle-c {
|
||||
border: 3px solid #009dff;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 4px;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
padding: 0.5rem;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 82%;
|
||||
bottom: -3px;
|
||||
top: -3px;
|
||||
left: 9%;
|
||||
border-bottom: 3px solid @screen-color;
|
||||
border-top: 3px solid @screen-color;
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
height: 66%;
|
||||
left: -3px;
|
||||
right: -3px;
|
||||
top: 17%;
|
||||
border-left: 3px solid @screen-color;
|
||||
border-right: 3px solid @screen-color;
|
||||
}
|
||||
|
||||
.map-bg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: white;
|
||||
padding: 1rem;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 0 3rem rgba(100, 200, 255, .5) inset;
|
||||
background: rgba(0, 0, 0, 0);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user