Merge branch 'release_electronic_bid_evaluation_room' into 'release_20230102'

1.6 电子评标室

See merge request eshop/fe_service_ebtp_frontend!112
This commit is contained in:
jl-zhoujl2
2023-01-06 13:50:52 +00:00
7 changed files with 657 additions and 329 deletions

View File

@ -3,7 +3,7 @@ import React, { useEffect, useRef, useState } from 'react';
import '../style.less'
import { authCheck, ModalList, onCell, onHeaderCell, OverviewItem, ScreenLabel, ScreenTitle, ScrollTable } from '../Home';
import Circle3199 from '@/assets/monitor/circle-3199.png';
import { getDecryptDataAPI, getNoOpenAssessListAPI, getNoOpenListAPI, getNoOpenNumberAPI, getThreeDayNoEndAPI, getThreeDayNoEndCountAPI, getThreeDaysUnSendAnnoCountAPI, getThreeDaysUnSendAnnoListAPI } from '../service';
import { getDecryptDataAPI, getNoOpenAssessListAPI, getNoOpenAssessNumberAPI, getNoOpenListAPI, getNoOpenNumberAPI, getThreeDayNoEndAPI, getThreeDayNoEndCountAPI, getThreeDaysUnSendAnnoCountAPI, getThreeDaysUnSendAnnoListAPI } from '../service';
import { isNotEmpty } from '@/utils/CommonUtils';
const MonitorException: React.FC<{}> = () => {
@ -16,7 +16,9 @@ const MonitorException: React.FC<{}> = () => {
//超过1小时未开标数量-列表
const [noOpenListData, setNoOpenListData] = useState<any[]>([]);
//开标后超过6小时未开启评审室-列表
const [noOpenAssessListData, setNoOpenAssessListData] = useState<any>();
const [noOpenAssessListData, setNoOpenAssessListData] = useState<any[]>([]);
//开标后超过6小时未开启评审室-数量
const [noOpenAssessNumber, setNoOpenAssessNumber] = useState<string | number>(0);
//异常监控-解密异常、mac地址相同及相关项目列表
const [decryptData, setDecryptData] = useState<any>();
//评审室关闭3日内未发布公示数
@ -29,6 +31,8 @@ const MonitorException: React.FC<{}> = () => {
const [modalListData, setModalListData] = useState<any[]>([]);
//ModalList Type
const [exceptionType, setExceptionType] = useState<any>();
//selectKey
const [selectKey, setSelectKey] = useState<number>(-1);
//权限校验
const auth = useRef<boolean>(authCheck());
//超过1小时未开标数量
@ -57,17 +61,52 @@ const MonitorException: React.FC<{}> = () => {
}
//开标后超过6小时未开启评审室-列表
const getNoOpenAssessList = () => {
getNoOpenAssessListAPI({ pageNo: 1, pageSize: 100 }).then(res => {
getNoOpenAssessListAPI({ "timeLimit": "6", "dayNumber": "30" }).then(res => {
if (res?.code == 200) {
setNoOpenAssessListData(res?.data);
}
})
}
//异常监控-解密异常、mac地址相同及相关项目列表
//开标后超过6小时未开启评审室-数量
const getNoOpenAssessNumber = () => {
getNoOpenAssessNumberAPI({ "timeLimit": "6", "dayNumber": "30" }).then(res => {
if (res?.code == 200) {
setNoOpenAssessNumber(res?.data);
}
})
}
//异常监控-解密异常、mac地址相同及相关项目列表jectRecord?
const getDecryptData = () => {
getDecryptDataAPI().then(res => {
if (res?.code == 200) {
setDecryptData(res?.data);
const data = res?.data;
if (data?.decryptExceptionList?.length > 0) {
for (let i = 0, length = data.decryptExceptionList.length; i < length; i++) {
data.decryptExceptionList[i]["regionDictName"] = data.decryptExceptionList[i].projectRecord?.regionDictName;
data.decryptExceptionList[i]["projectName"] = data.decryptExceptionList[i].projectRecord?.projectName;
data.decryptExceptionList[i]["ownerContactName"] = data.decryptExceptionList[i].projectRecord?.ownerContactName;
data.decryptExceptionList[i]["ownerContactTel"] = data.decryptExceptionList[i].projectRecord?.ownerContactTel;
data.decryptExceptionList[i]["tenderAgencyName"] = data.decryptExceptionList[i].projectRecord?.tenderAgencyName;
data.decryptExceptionList[i]["appManagerTel"] = data.decryptExceptionList[i].projectRecord?.appManagerTel;
data.decryptExceptionList[i]["recruitStartTime"] = data.decryptExceptionList[i].projectRecord?.recruitStartTime;
data.decryptExceptionList[i]["bidMethodDict"] = data.decryptExceptionList[i].projectRecord?.bidMethodDict;
}
}
if (data?.macSameList?.length > 0) {
for (let i = 0, length = data.macSameList.length; i < length; i++) {
data.macSameList[i]["regionDictName"] = data.macSameList[i].projectRecord?.regionDictName;
data.macSameList[i]["projectName"] = data.macSameList[i].projectRecord?.projectName;
data.macSameList[i]["ownerContactName"] = data.macSameList[i].projectRecord?.ownerContactName;
data.macSameList[i]["ownerContactTel"] = data.macSameList[i].projectRecord?.ownerContactTel;
data.macSameList[i]["tenderAgencyName"] = data.macSameList[i].projectRecord?.tenderAgencyName;
data.macSameList[i]["appManagerTel"] = data.macSameList[i].projectRecord?.appManagerTel;
data.macSameList[i]["recruitStartTime"] = data.macSameList[i].projectRecord?.recruitStartTime;
data.macSameList[i]["bidMethodDict"] = data.macSameList[i].projectRecord?.bidMethodDict;
}
}
setDecryptData(data);
}
})
}
@ -104,12 +143,43 @@ const MonitorException: React.FC<{}> = () => {
getThreeDayNoEnd();
getNoOpenList();
getNoOpenAssessList();
getNoOpenAssessNumber();
getDecryptData();
getThreeDaysUnSendAnnoCount();
getThreeDaysUnSendAnnoList();
getThreeDayNoEndCount();
}
}, [])
useEffect(() => {
let interval: any = null;
let count = 0;
let lengthMap = [noOpenListData.length, noOpenAssessListData.length, isNotEmpty(decryptData?.decryptExceptionList) ? decryptData?.decryptExceptionList.length : 0, threeDayNoEndData.length, isNotEmpty(decryptData?.macSameList) ? decryptData?.macSameList.length : 0, threeDaysUnSendAnnoList.length].sort((a, b) => b - a);
if (lengthMap[0] > 1) {//至少2条才能滚动
interval = setInterval(() => {
if (count < lengthMap[0]) {
setSelectKey(count);
const v0 = document.getElementsByClassName("scroll-select-bg")[0];
const v1 = document.getElementsByClassName("scroll-select-bg")[1];
const v2 = document.getElementsByClassName("scroll-select-bg")[2];
const v3 = document.getElementsByClassName("scroll-select-bg")[3];
const v4 = document.getElementsByClassName("scroll-select-bg")[4];
const v5 = document.getElementsByClassName("scroll-select-bg")[5];
v0?.scrollIntoView(false);
v1?.scrollIntoView(false);
v2?.scrollIntoView(false);
v3?.scrollIntoView(false);
v4?.scrollIntoView(false);
v5?.scrollIntoView(false);
count++;
} else {
count = 0;
}
}, 3000)
}
return () => {
clearInterval(interval);
}
}, [noOpenListData, noOpenAssessListData, decryptData?.decryptExceptionList, threeDayNoEndData, decryptData?.macSameList, threeDaysUnSendAnnoList])
const columns: any[] = [
{
@ -206,8 +276,8 @@ const MonitorException: React.FC<{}> = () => {
},
{
title: '预算金额(元)',
dataIndex: 'budgetAmount',
key: 'budgetAmount',
dataIndex: 'bidSectContractPrice',
key: 'bidSectContractPrice',
align: 'center',
width: '25%',
onCell,
@ -248,8 +318,8 @@ const MonitorException: React.FC<{}> = () => {
},
{
title: '省分',
dataIndex: 'provinceName',
key: 'provinceName',
dataIndex: 'province',
key: 'province',
align: 'center',
width: '15%',
ellipsis: true,
@ -332,13 +402,13 @@ const MonitorException: React.FC<{}> = () => {
},
{
title: '预算金额(元)',
dataIndex: 'budgetAmount',
key: 'budgetAmount',
dataIndex: 'bidSectContractPrice',
key: 'bidSectContractPrice',
align: 'center',
width: '25%',
onCell,
onHeaderCell,
render: (_: any, record: any) => isNotEmpty(record.budgetAmount) ? Number(record.budgetAmount).toFixed(2) : 0,
render: (_: any, record: any) => isNotEmpty(record.bidSectContractPrice) ? Number(record.bidSectContractPrice).toFixed(2) : 0,
},
{
title: '采购经理',
@ -395,8 +465,8 @@ const MonitorException: React.FC<{}> = () => {
},
{
title: '预算金额(元)',
dataIndex: 'budgetAmount',
key: 'budgetAmount',
dataIndex: 'bidSectContractPrice',
key: 'bidSectContractPrice',
align: 'center',
width: '25%',
onCell,
@ -432,7 +502,7 @@ const MonitorException: React.FC<{}> = () => {
<OverviewItem icon={Circle3199} title="一小时内未开标" number={noOpenNumberData} unit="个" />
<OverviewItem icon={Circle3199} title="解密异常" number={decryptData?.decryptExceptionCount} unit="次" />
<OverviewItem icon={Circle3199} title="MAC地址相同" number={decryptData?.macSameCount} unit="个" />
<OverviewItem icon={Circle3199} title="开标后6小时未开启评审" number={noOpenAssessListData?.length} unit="个" />
<OverviewItem icon={Circle3199} title="开标后6小时未开启评审" number={noOpenAssessNumber} unit="个" />
<OverviewItem icon={Circle3199} title="开启评审后3日未结束评标" number={threeDayNoEndCount} unit="个" />
<OverviewItem icon={Circle3199} title="评标结束3日未公示" number={threeDaysUnSendAnnoCount} unit="个" />
{/* <OverviewItem icon={Circle3199} title="重新评标次数" number={62520} unit="次" /> */}
@ -443,11 +513,11 @@ const MonitorException: React.FC<{}> = () => {
<div className="monitor-left-main">
<ScreenLabel title="1小时未开标项目列表" extra={<span className='monitor-extra-pointer' onClick={() => { setExceptionType(null); setModalListData(noOpenListData); setModalListVisible(true); }}>more</span>} />
<div className="monitor-exception-card">
<ScrollTable dataSource={noOpenListData} columns={columns} ynum={266} />
<ScrollTable dataSource={noOpenListData} columns={columns} ynum={266} rowKey="sectionId" selectKey={selectKey} />
</div>
<ScreenLabel title="开标后六小时未开启评审" extra={<span className='monitor-extra-pointer' onClick={() => { setExceptionType(null); setModalListData(noOpenAssessListData); setModalListVisible(true); }}>more</span>} />
<div className="monitor-exception-card">
<ScrollTable dataSource={noOpenAssessListData} columns={columns} ynum={266} />
<ScrollTable dataSource={noOpenAssessListData} columns={columns} ynum={266} selectKey={selectKey} />
</div>
</div>
</Col>
@ -455,11 +525,11 @@ const MonitorException: React.FC<{}> = () => {
<div className="monitor-center-main">
<ScreenLabel title="解密异常项目列表" extra={<span className='monitor-extra-pointer' onClick={() => { setExceptionType("解密异常"); setModalListData(decryptData?.decryptExceptionList ? decryptData?.decryptExceptionList : []); setModalListVisible(true); }}>more</span>} />
<div className="monitor-exception-card">
<ScrollTable dataSource={decryptData?.decryptExceptionList} columns={columnsSecond} ynum={266} />
<ScrollTable dataSource={decryptData?.decryptExceptionList} columns={columnsSecond} selectKey={selectKey} ynum={266} />
</div>
<ScreenLabel title="开启评审后3日未结束评标" extra={<span className='monitor-extra-pointer' onClick={() => { setExceptionType("开启评审后3日未结束评标"); setModalListData(threeDayNoEndData); setModalListVisible(true); }}>more</span>} />
<div className="monitor-exception-card">
<ScrollTable dataSource={threeDayNoEndData} columns={columnsForth} ynum={266} />
<ScrollTable dataSource={threeDayNoEndData} columns={columnsForth} ynum={266} selectKey={selectKey} />
</div>
</div>
</Col>
@ -467,11 +537,11 @@ const MonitorException: React.FC<{}> = () => {
<div className="monitor-right-main">
<ScreenLabel title="MAC地址重复项目列表" extra={<span className='monitor-extra-pointer' onClick={() => { setExceptionType("MAC地址重复"); setModalListData(decryptData?.macSameList ? decryptData?.macSameList : []); setModalListVisible(true); }}>more</span>} />
<div className="monitor-exception-card">
<ScrollTable dataSource={decryptData?.macSameList} columns={columnsFifth} ynum={266} />
<ScrollTable dataSource={decryptData?.macSameList} columns={columnsFifth} ynum={266} selectKey={selectKey} />
</div>
<ScreenLabel title="评标结束后3日内未发布公示" extra={<span className='monitor-extra-pointer' onClick={() => { setExceptionType("评标结束后3日内未发布公示"); setModalListData(threeDaysUnSendAnnoList); setModalListVisible(true); }}>more</span>} />
<div className="monitor-exception-card">
<ScrollTable dataSource={threeDaysUnSendAnnoList} columns={columnsThird} ynum={266} />
<ScrollTable dataSource={threeDaysUnSendAnnoList} columns={columnsThird} ynum={266} selectKey={selectKey} />
</div>
</div>
</Col>

View File

@ -1,4 +1,4 @@
import { Button, Col, Descriptions, Divider, Dropdown, Empty, Menu, message, Modal, Progress, Row, Space, Table } from 'antd';
import { Button, Col, Descriptions, Divider, Dropdown, Empty, Input, Menu, MenuProps, message, Modal, Progress, Row, Space, Table } from 'antd';
import { debounce } from 'lodash';
import React, { useEffect, useMemo, useRef, useState } from 'react';
import '../style.less'
@ -14,10 +14,10 @@ import right from '@/assets/monitor/right.png';
import { CaretRightOutlined, DownOutlined } from '@ant-design/icons';
import './china';
import * as echarts from 'echarts';
import { getActiveSupplierAPI, getAnnoCountAPI, getAnnualAndTenderAgentAPI, getExpertNumberAPI, getMonitorListAPI, getOpeningListAPI, getReviewDistributionAPI, getSupplierCountAPI, getTodayOpeningAPI } from '../service';
import { getActiveSupplierAPI, getAnnoCountAPI, getAnnualAndTenderAgentAPI, getExpertNumberAPI, getMonitorListAPI, getOpeningListAPI, getReviewDistributionAPI, getSupplierCountAPI, getTodayInfoAPI, getTodayOpeningAPI } from '../service';
import moment from 'moment';
import { isEmpty, isNotEmpty } from '@/utils/CommonUtils';
import { getSessionUserData } from '@/utils/session';
import { getDicData, getSessionUserData } from '@/utils/session';
import { history } from 'umi';
export const onCell = () => ({ className: "monitor-table-content" });
@ -56,6 +56,15 @@ export const proviceEnum = {
"0065": "新疆",
"001000": "集团"
}
function getYearMap() {
const year: number = moment().year();//当前年份
const data: { label: string, value: string }[] = [];
for (let i = 0, length = year - 2021 + 1; i < length; i++) {
data.push({ label: (year - i) + "年", value: String(year - i) })
}
return data;
}
export const yearMap: { label: string, value: string }[] = getYearMap();
function dealWithData(mapd: any[]) {
let geoCoordMap = {
: [125.35, 43.88],
@ -92,20 +101,38 @@ function dealWithData(mapd: any[]) {
西: [115.864528, 28.687675]
};
let data = [];
for (let key in geoCoordMap) {
for (let i = 0, length = mapd.length; i < length; i++) {
const ele = mapd[i];
if (ele.provincesName == key) {
geoCoordMap[key].push(Number(ele.allNumber));
geoCoordMap[key].push(Number(ele.opeingNumber));
geoCoordMap[key].push(Number(ele.assessNumber));
break;
}
}
data.push({ name: key, value: geoCoordMap[key] });
// for (let key in geoCoordMap) {
// for (let i = 0, length = mapd.length; i < length; i++) {
// const ele = mapd[i];
// if (ele.provincesName == key) {
// geoCoordMap[key].push(Number(ele.allNumber));
// geoCoordMap[key].push(Number(ele.opeingNumber));
// geoCoordMap[key].push(Number(ele.assessNumber));
// break;
// }
// }
// data.push({ name: key, value: geoCoordMap[key] });
// }
for (let i = 0, length = mapd.length; i < length; i++) {
const ele = mapd[i];
data.push({ name: ele.provincesName, value: [...geoCoordMap[ele.provincesName], Number(ele.allNumber), Number(ele.opeingNumber), Number(ele.assessNumber)] });
}
return data;
}
/**
* 字典code回显dicName
* @param dictList[]
* @param code
*/
export const changeDict = (dictList: any[], code: any) => {
let name = '';
dictList.forEach((ele: any) => {
if (ele.code == code) {
name = ele.dicName;
}
});
return name;
};
const columns: any[] = [
{
@ -332,6 +359,50 @@ export const SelectItem = (props: { onSelectChange: (value: string) => void, opt
</Dropdown>
)
}
//下拉框-招标代理选择
export const SelectRadio = (props: { onSelectChange: (value: string) => void, options: ({ label: string, value: string })[], defaultText?: string, hidden?: boolean }) => {
const { onSelectChange, options, defaultText = "全部", hidden = false } = props;
const [selectedItem, setSelectItem] = useState<string | number>(defaultText);
const [open, setOpen] = useState(false);
const [optionsList, setOptionsList] = useState<{ label: string, value: string }[]>([]);
const handleOpenChange = (flag: boolean) => {
setOpen(flag);
};
const handleMenuClick = () => {
setOpen(false);
};
const onChange = (e: any) => {
const data = e.target.value;
const list = options.filter(item => item.label.includes(data));
setOptionsList(list);
}
useEffect(() => {
options.length > 0 && setOptionsList(options);
}, [options])
const menu = (
<Space size={4}>
<div><Input placeholder="代理机构名称" bordered={false} onChange={onChange} /></div>
{optionsList.slice(0, 56).map(item => (
<div key={item.value} onClick={() => { setSelectItem(item.label); onSelectChange(item.value); handleMenuClick(); }}>{item.label}</div>
))}
{optionsList.length > 56 && "..."}
</Space>
);
return (
<Dropdown overlay={menu} trigger={["click"]} visible={open} onVisibleChange={handleOpenChange} overlayClassName="monitor-select-radio-dropdown" placement="bottomRight">
<div className='monitor-select-btn' hidden={hidden}>
<span>
<Space>
{selectedItem}
<DownOutlined />
</Space>
</span>
</div>
</Dropdown>
)
}
//阶段卡片
export const StageCard = (props: { percentage: string | number, total: string | number, firstTitle: string, secondTitle: string, thirdTitle: string, firstNumber: string | number, secondNumber: string | number, thirdNumber: string | number }) => {
const { percentage, total, firstTitle, secondTitle, thirdTitle, firstNumber, secondNumber, thirdNumber } = props;
@ -387,20 +458,26 @@ export const StageCard = (props: { percentage: string | number, total: string |
)
}
//滚动列表
export const ScrollTable = (props: { dataSource: any[], columns: any[], rollTime?: number, rollNum?: number, ynum?: number }) => {
const { dataSource, columns, rollTime = 50, rollNum = 5, ynum = 300 } = props;
export const ScrollTable = (props: { dataSource: any[], columns: any[], rollTime?: number, rollNum?: number, ynum?: number, rowKey?: string, selectKey?: number }) => {
const { dataSource, columns, rollTime = 10, rollNum = 5, ynum = 300, rowKey = "id", selectKey = -1 } = props;
return (
<div style={{ ["--monitor-table-height" as any]: `${ynum}px` }}>
<Table
pagination={false}
className="monitor-scroll-table"
rowKey="id"
rowKey={rowKey}
bordered={false}
scroll={{
y: ynum,
scrollToFirstRowOnChange: true,
// scrollToFirstRowOnChange: true,
}}
// dataSource={tableData}
rowClassName={(record, index) => {
if (index == selectKey) {
return "scroll-select-bg"; //highlight样式需要自己定义
}
return "scroll-select-default";
}}
dataSource={dataSource}
columns={columns}
onRow={record => {
@ -413,14 +490,14 @@ export const ScrollTable = (props: { dataSource: any[], columns: any[], rollTime
)
}
//统计列表
export const StatisticTable = (props: { dataSource: any[], columns: any[], rollTime?: number, rollNum?: number, ynum?: number }) => {
const { dataSource, columns, rollTime = 50, rollNum = 5, ynum = 300 } = props;
export const StatisticTable = (props: { dataSource: any[], columns: any[], rollTime?: number, rollNum?: number, ynum?: number, rowKey?: string }) => {
const { dataSource, columns, rollTime = 50, rollNum = 5, ynum = 300, rowKey = "id" } = props;
return (
<div style={{ ["--monitor-table-height" as any]: `${ynum}px` }}>
<Table
pagination={false}
className="monitor-statistic-table"
rowKey="id"
rowKey={rowKey}
size='small'
bordered={false}
scroll={{
@ -510,6 +587,9 @@ export const ModalList = (props: { modalVisible: boolean, onCancel: () => void,
const contentStyle = { color: "#fff" };
const titleStyle = { color: "#1b7ef2", fontWeight: "bold", marginBottom: '24px' };
const dividerStyle = { borderColor: "#999", margin: "12px 0 24px" };
//初始化字典
let dic: any = getDicData();
let dicData: any = JSON.parse(dic);
return (
<Modal
destroyOnClose
@ -529,9 +609,11 @@ export const ModalList = (props: { modalVisible: boolean, onCancel: () => void,
<Descriptions>
<Descriptions.Item label="异常类型" labelStyle={labelStyle} contentStyle={contentStyle}>{isNotEmpty(exceptionType) ? exceptionType : item?.exType}</Descriptions.Item>
<Descriptions.Item label="项目名称" labelStyle={labelStyle} contentStyle={contentStyle}>{item?.projectName}</Descriptions.Item>
<Descriptions.Item label="标段名称" labelStyle={labelStyle} contentStyle={contentStyle}>{item?.bidSectName || item?.sectionName}</Descriptions.Item>
<Descriptions.Item label="省分" labelStyle={labelStyle} contentStyle={contentStyle}>{item?.provinceName || item?.regionDictName || item?.province}</Descriptions.Item>
<Descriptions.Item label="采购经理" labelStyle={labelStyle} contentStyle={contentStyle}>{item?.ownerContactName}</Descriptions.Item>
<Descriptions.Item label="采购经理电话" labelStyle={labelStyle} contentStyle={contentStyle}>{item?.ownerContactTel}</Descriptions.Item>
<Descriptions.Item label="标段状态" labelStyle={labelStyle} contentStyle={contentStyle}>{(item?.state || item?.sectionState || item?.sectionStatus) == 9 ? "异常处理" : changeDict(item?.bidMethodDict ? dicData[`business_module=${item?.bidMethodDict}`] : [], item?.businessModule)}</Descriptions.Item>
<Descriptions.Item label="招标代理机构" labelStyle={labelStyle} contentStyle={contentStyle}>{item?.tenderAgencyName}</Descriptions.Item>
<Descriptions.Item label="代理机构电话" labelStyle={labelStyle} contentStyle={contentStyle}>{item?.appManagerTel}</Descriptions.Item>
<Descriptions.Item label="开标时间" labelStyle={labelStyle} contentStyle={contentStyle}>{item?.openTime || item?.recruitStartTime || item?.openingTime}</Descriptions.Item>
@ -564,8 +646,7 @@ export const GraphChart = (props: { type: string, chartData: any[], chartColor?:
let mapData: any[] = [];
if (type == "map") {//地图处理数据
dataValue = dealWithData(chartData);
// mapData = dataValue.splice(0, 3);
mapData = dataValue;
mapData = dataValue.splice(0, 3);
}
const autoTooltip = (index: number) => {
myChart.dispatchAction({
@ -577,6 +658,18 @@ export const GraphChart = (props: { type: string, chartData: any[], chartColor?:
},
});
}
const autoSelect = (index: number) => {
myChart.dispatchAction({
type: 'select',
seriesIndex: 0,
dataIndex: index,
});
myChart.dispatchAction({
type: 'showTip',
seriesIndex: 0,
dataIndex: index,
});
}
const colors = ['#1B7EF2', '#29F1FA', '#1B7EF2'];
const categoryOption: EChartsOption = {
color: colors,
@ -740,7 +833,13 @@ export const GraphChart = (props: { type: string, chartData: any[], chartColor?:
coordinateSystem: "geo",
data: dataValue,
symbolSize: function (val) {
return val[2] == 0 ? 8 : Math.floor(val[2] / 1.2);
if (val[2] < 9) {
return 8;
} else if (val[2] > 30) {
return 30;
} else {
return val[2];
}
},
symbol: "circle",
// symbolSize: 8,
@ -774,48 +873,54 @@ export const GraphChart = (props: { type: string, chartData: any[], chartColor?:
disabled: true
},
},
// {
// name: "",
// type: "effectScatter",
// coordinateSystem: "geo",
// data: mapData,
// symbolSize: 16,
// // symbolSize: function (val) {
// // return Math.floor(val[1] / 4);
// // },
// tooltip: {
// formatter(value) {
// return value.data.name + "<br/>" + "今日评标总数:" + value.data.value[2] + "<br/>" + "电子招标:" + value.data.value[3] + "<br/>" + "电子评标:" + value.data.value[4];
// },
// backgroundColor: "#0a0c11cc",
// textStyle: {
// color: '#fff'
// },
// show: true
// },
// encode: {
// value: 2
// },
// showEffectOn: "render",
// rippleEffect: {
// brushType: "stroke",
// color: "rgb(36,203,255)",
// period: 9,
// scale: 5
// },
// label: {
// formatter: "{b}",
// position: "right",
// color: "#fff",
// show: true
// },
// itemStyle: {
// color: "rgb(36,203,255)",
// shadowBlur: 2,
// shadowColor: "#333"
// },
// zlevel: 1
// }
{
name: "",
type: "effectScatter",
coordinateSystem: "geo",
data: mapData,
// symbolSize: 16,
symbolSize: function (val) {
if (val[2] < 9) {
return 8;
} else if (val[2] > 30) {
return 30;
} else {
return val[2];
}
},
tooltip: {
formatter(value) {
return value.data.name + "<br/>" + "今日评标总数:" + value.data.value[2] + "<br/>" + "电子招标:" + value.data.value[3] + "<br/>" + "电子评标:" + value.data.value[4];
},
backgroundColor: "#0a0c11cc",
textStyle: {
color: '#fff'
},
show: true
},
encode: {
value: 2
},
showEffectOn: "render",
rippleEffect: {
brushType: "stroke",
color: "rgb(36,203,255)",
period: 9,
scale: 5
},
label: {
formatter: "{b}",
position: "right",
color: "#fff",
show: true
},
itemStyle: {
color: "rgb(36,203,255)",
shadowBlur: 2,
shadowColor: "#333"
},
zlevel: 1
}
]
};
const gaugeOption: EChartsOption = {
@ -917,9 +1022,6 @@ export const GraphChart = (props: { type: string, chartData: any[], chartColor?:
}
const mapTwiceOption: EChartsOption = {
tooltip: {
trigger: 'item',
showDelay: 0,
transitionDuration: 0.2,
show: false,
},
geo: {
@ -937,8 +1039,8 @@ export const GraphChart = (props: { type: string, chartData: any[], chartColor?:
}
},
visualMap: {
min: 1,
max: 50,
min: 0,
max: 100,
inRange: {
color: [
'#01417f',
@ -963,6 +1065,19 @@ export const GraphChart = (props: { type: string, chartData: any[], chartColor?:
// label: {
// show: false
// },
tooltip: {
formatter(value) {
if (value.data?.name) {
return value.data.name + "<br/>" + "活跃供应商数量:" + value.data?.data.supplierCount + "<br/>" + "投标次数总量:" + value.data?.data.tenderCount;
}
return "";
},
backgroundColor: "#0a0c11cc",
textStyle: {
color: '#fff'
},
show: true
},
emphasis: {
label: {
show: true,
@ -1216,7 +1331,7 @@ export const GraphChart = (props: { type: string, chartData: any[], chartColor?:
if (type == "mapTwice") {
myChart.on('selectchanged', function (params: any) {
if (params.selected.length > 0) {
onSelect(chartData[params.selected[0].dataIndex[0]].name);
onSelect(chartData[params.selected[0].dataIndex[0]]?.name);
} else {
onSelect("");
}
@ -1238,16 +1353,29 @@ export const GraphChart = (props: { type: string, chartData: any[], chartColor?:
myChart && myChart.resize();
};
let interval: any = null;
// if (type == "map") {//地图自动轮播tooltip
// let index = 0;
// interval = setInterval(() => {
// autoTooltip(index)
// index++;
// if (index >= mapData.length) {
// index = 0;
// }
// }, 10000)
// }
if (type == "map") {//地图自动轮播tooltip
let index = 0;
interval = setInterval(() => {
autoTooltip(index);
index++;
if (index >= mapData.length) {
index = 0;
}
}, 10000)
}
if (type == "mapTwice") {//地图自动轮播tooltip
let index = 1;
autoSelect(0);
if (chartData.length > 1) {
interval = setInterval(() => {
autoSelect(index);
index++;
if (index >= chartData.length) {
index = 0;
}
}, 10000)
}
}
window.addEventListener("resize", debounce(() => resize(), 100));
return () => {
window.removeEventListener("resize", debounce(() => resize(), 100));
@ -1289,14 +1417,17 @@ const MonitorHome: React.FC<{}> = () => {
const [annoCount, setAnnoCount] = useState<string | number>("");
//评审专家数量
const [expertNumber, setExpertNumber] = useState<string | number>("");
//年度&月度 year-年度 month-月度
const [ymChange, setYmChange] = useState<string>("year");
//评标室监控
const [monitorList, setMonitorList] = useState<any[]>([{ status: "3" }, { status: "3" }, { status: "3" }]);
const [monitorList, setMonitorList] = useState<any[]>([]);
//今日开标-评标阶段,评标及时率
const [todayInfoData, setTodayInfoData] = useState<any>();
//权限校验
const auth = useRef<boolean>(authCheck());
const bidStatusMap = ["准备评标", "正在评标", "评标结束", "暂无数据"];
const statusColorMap = ["card-text-orange", "card-text-green", "card-text-purple", "card-text-white"];
//year select
const localYear: string = moment().month() < 2 ? String(moment().year() - 1) : String(moment().year());
const [yearSelect, setYearSelect] = useState<string>(localYear);
const mapChart = useMemo(() => {
return reviewDistributionData.length > 0 && <GraphChart type="map" chartData={reviewDistributionData} />
}, [reviewDistributionData])
@ -1325,8 +1456,8 @@ const MonitorHome: React.FC<{}> = () => {
})
}
//上面前三个指标和招标代理实施项目统计
const getAnnualAndTenderAgent = () => {
getAnnualAndTenderAgentAPI().then(res => {
const getAnnualAndTenderAgent = (ym: any) => {
getAnnualAndTenderAgentAPI(ym).then(res => {
if (res?.code == 200) {
const data = res?.data;
if (data.agencyProjectYear.length > 0) {
@ -1335,20 +1466,13 @@ const MonitorHome: React.FC<{}> = () => {
data.agencyProjectYear[i]["maxNum"] = max1;
}
}
if (data.agencyProjectMonth.length > 0) {
const max2 = data.agencyProjectMonth[0].num;
for (let i = 0, length = data.agencyProjectMonth.length; i < length; i++) {
data.agencyProjectMonth[i]["maxNum"] = max2;
}
}
setAnnualAndTenderAgentData(data);
}
})
}
//活跃供应商
const getActiveSupplier = () => {
getActiveSupplierAPI().then(res => {
const getActiveSupplier = (ym: string) => {
getActiveSupplierAPI(ym).then(res => {
if (res?.code == 200) {
const data = res?.data;
if (data.length > 0) {
@ -1363,7 +1487,7 @@ const MonitorHome: React.FC<{}> = () => {
}
//参与供应商数
const getSupplierCount = (ym: string) => {
getSupplierCountAPI({ type: ym }).then(res => {
getSupplierCountAPI({ year: Number(ym) }).then(res => {
if (res?.code == 200) {
setSupplierCount(res?.data);
}
@ -1371,7 +1495,7 @@ const MonitorHome: React.FC<{}> = () => {
}
//公告公示数量
const getAnnoCount = (ym: string) => {
getAnnoCountAPI({ type: ym }).then(res => {
getAnnoCountAPI(ym).then(res => {
if (res?.code == 200) {
setAnnoCount(res?.data);
}
@ -1395,11 +1519,16 @@ const MonitorHome: React.FC<{}> = () => {
}
})
}
//今日开标-评标阶段,评标及时率
const getTodayInfo = () => {
getTodayInfoAPI().then(res => {
if (res?.code == 200) {
setTodayInfoData(res?.data);
}
})
}
//监控室点击事件
const onCardClick = (item: any) => {
if (item.status == "3") {
return;
}
if (item.status == "0") {
message.info("当前评标室未开启,请等待开启后查看");
return;
@ -1409,36 +1538,41 @@ const MonitorHome: React.FC<{}> = () => {
state: { monitorId: item.id },
})
}
//onYearSelect
const onYearSelect = (value: string) => {
setYearSelect(value);
}
useEffect(() => {
if (auth.current) {
getTodayOpening();
getReviewDistribution();
getOpeningList();
getAnnualAndTenderAgent();
getActiveSupplier();
getMonitorList();
getTodayInfo();
}
}, [])
useEffect(() => {
if (auth.current) {
getSupplierCount(ymChange);
getAnnoCount(ymChange);
getExpertNumber(ymChange);
getSupplierCount(yearSelect);
getAnnoCount(yearSelect);
getAnnualAndTenderAgent(yearSelect);
getExpertNumber(yearSelect);
getActiveSupplier(yearSelect);
}
}, [ymChange])
}, [yearSelect])
return (
<ScreenTitle title="智能招标采购室">
<div className="top-main">
<div className='monitor-top-exchange'>
<span onClick={() => { setYmChange("year") }}></span> | <span onClick={() => { setYmChange("month") }}></span>
<SelectItem options={yearMap} onSelectChange={onYearSelect} defaultText={localYear + "年"} />
</div>
<Row className="monitor-top-main-flex">
<Col span={4}><MetricItems icon={Frame10116} title="电子招标总数" number={ymChange == "year" ? annualAndTenderAgentData?.bidProjectCountYear : annualAndTenderAgentData?.bidProjectCountMonth} unit="个" /></Col>
<Col span={4}><MetricItems icon={Frame10117} title="电子谈判总数" number={ymChange == "year" ? annualAndTenderAgentData?.negoProjectCountYear : annualAndTenderAgentData?.negoProjectCountMonth} unit="个" /></Col>
<Col span={4}><MetricItems icon={Frame10118} title="预算金额" number={ymChange == "year" ? annualAndTenderAgentData?.projectBudgetYear?.toFixed(2) : annualAndTenderAgentData?.projectBudgetMonth?.toFixed(2)} unit="亿元" /></Col>
<Col span={4}><MetricItems icon={Frame10116} title="电子招标总数" number={annualAndTenderAgentData?.bidProjectCountYear} unit="个" /></Col>
<Col span={4}><MetricItems icon={Frame10117} title="电子谈判总数" number={annualAndTenderAgentData?.negoProjectCountYear} unit="个" /></Col>
<Col span={4}><MetricItems icon={Frame10118} title="预算金额" number={annualAndTenderAgentData?.projectBudgetYear?.toFixed(2)} unit="亿元" /></Col>
<Col span={4}><MetricItems icon={Frame10119} title="公告公示数量" number={annoCount} unit="个" /></Col>
<Col span={4}><MetricItems icon={Frame10120} title="评标专家数量" number={expertNumber} unit="人次" /></Col>
<Col span={4}><MetricItems icon={Frame10121} title="参与供应商" number={supplierCount} unit="家次" /></Col>
@ -1448,7 +1582,7 @@ const MonitorHome: React.FC<{}> = () => {
<Col span={8}>
<div className="monitor-left-main">
<div className="monitor-label-pointer" onClick={() => { window.open("/ElecMonitor/OpenToday") }}>
<ScreenLabel title="今日开标" extra={<span>&nbsp;&nbsp;{isNotEmpty(todayOpeningData?.sectionNumber) ? todayOpeningData?.sectionNumber : 0}&nbsp;&nbsp;&nbsp;&nbsp;{isNotEmpty(todayOpeningData?.complete) ? Number(todayOpeningData?.complete).toFixed(0) : 0}&nbsp;&nbsp;&nbsp;&nbsp;{isNotEmpty(todayOpeningData?.rate) ? todayOpeningData?.rate : 0}</span>} />
<ScreenLabel title="今日开标" extra={<span>&nbsp;&nbsp;{isNotEmpty(todayOpeningData?.sectionNumber) ? todayOpeningData?.sectionNumber : 0}&nbsp;&nbsp;&nbsp;&nbsp;{isNotEmpty(todayOpeningData?.sectionNumber) && todayOpeningData?.sectionNumber != "0" ? Number(((Number(todayOpeningData?.banner) / todayOpeningData?.sectionNumber) * 100).toFixed(0)) : 0}%&nbsp;&nbsp;&nbsp;&nbsp;{(isNotEmpty(todayInfoData?.sectionNumber) && todayInfoData?.sectionNumber != "0") ? Number(((Number(todayInfoData?.resultNumber) / todayInfoData?.sectionNumber) * 100).toFixed(0)) : 0}%</span>} />
</div>
<div className="scroll-table">
<ScrollTable dataSource={todayOpeningData?.todayList} columns={columns} ynum={266} />
@ -1473,11 +1607,9 @@ const MonitorHome: React.FC<{}> = () => {
<ScreenLabel title="智能评标监控" />
</div>
<div className="bid-evaluation">
{/* <div> */}
<Row gutter={16}>
{monitorList.length > 0 ? <div><Row gutter={16}>
{monitorList.map((item, index) => (
<Col span={8} key={index}>
{/* <div> */}
<div className="card-default-01" onClick={() => onCardClick(item)}>
<img src={default_play}></img>
<div className={statusColorMap[item.status]}>{bidStatusMap[item.status]}</div>
@ -1485,12 +1617,9 @@ const MonitorHome: React.FC<{}> = () => {
<div className="evaluation-text">
<span>{item?.projectName}</span>
</div>
{/* </div> */}
</Col>
))}
</Row>
{/* </div> */}
</Row></div> : <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} className="monitor-modal-empty" />}
</div>
</div>
</Col>

View File

@ -1,104 +1,13 @@
import { Col, Row } from 'antd';
import React, { useEffect, useRef, useState } from 'react';
import '../style.less'
import { authCheck, ModalList, onCell, onHeaderCell, OverviewItem, ProgressItem, proviceEnum, ScreenLabel, ScreenTitle, ScrollTable, StageCard } from '../Home';
import { authCheck, changeDict, ModalList, onCell, onHeaderCell, OverviewItem, ProgressItem, proviceEnum, ScreenLabel, ScreenTitle, ScrollTable, StageCard } from '../Home';
import Circle3199 from '@/assets/monitor/circle-3199.png';
import { getDecryptSuccessRateTodayAPI, getNoOpenListAPI, getNoOpenNumberAPI, getTodayInfoAPI, getTodayOpeningAPI, getUnopenSixAPI, getUnopenTenAPI } from '../service';
import { isNotEmpty } from '@/utils/CommonUtils';
const statusMap = ["未开标", "开标", "唱标", "唱标结束", "取消开标", "", "", "", "", "异常处理"];
import { getDicData } from '@/utils/session';
// const statusMap = ["未开标", "开标", "唱标", "唱标结束", "取消开标", "", "", "", "", "异常处理"];
const columns: any[] = [
{
title: '省分',
dataIndex: 'provinceName',
key: 'provinceName',
width: '20%',
align: "center",
ellipsis: true,
onCell,
onHeaderCell,
// render: (_: any, record: any) => proviceEnum[record.provinceDictId],
},
{
title: '项目名称',
dataIndex: 'projectName',
key: 'projectName',
align: "center",
ellipsis: true,
width: '30%',
onCell,
onHeaderCell,
},
{
title: '采购预算',
dataIndex: 'bidSectContractPrice',
key: 'bidSectContractPrice',
align: "center",
width: '30%',
onCell,
onHeaderCell,
},
{
title: '开标时间',
dataIndex: 'openTime',
key: 'openTime',
align: "center",
width: '20%',
onCell,
onHeaderCell,
},
];
const reiColumns: any[] = [
{
title: '省分',
dataIndex: 'provinceName',
key: 'provinceName',
align: "center",
width: '20%',
ellipsis: true,
onCell,
onHeaderCell,
// render: (_: any, record: any) => proviceEnum[record.provinceDictId],
},
{
title: '项目名称',
dataIndex: 'projectName',
key: 'projectName',
align: "center",
ellipsis: true,
width: '20%',
onCell,
onHeaderCell,
},
{
title: '采购预算',
dataIndex: 'bidSectContractPrice',
key: 'bidSectContractPrice',
align: "center",
width: '20%',
onCell,
onHeaderCell,
},
{
title: '开标时间',
dataIndex: 'openTime',
key: 'openTime',
align: "center",
width: '20%',
onCell,
onHeaderCell,
},
{
title: '状态',
dataIndex: 'state',
key: 'state',
align: "center",
width: '20%',
onCell,
onHeaderCell,
render: (_: any, record: any) => statusMap[record.state],
},
];
const OpenToday: React.FC<{}> = () => {
//今日开标-评标阶段,评标及时率
const [todayInfoData, setTodayInfoData] = useState<any>();
@ -124,8 +33,119 @@ const OpenToday: React.FC<{}> = () => {
const [modalListData, setModalListData] = useState<any[]>([]);
//ModalList Type
const [exceptionType, setExceptionType] = useState<any>();
//selectKey
const [selectKey, setSelectKey] = useState<number>(-1);
//权限校验
const auth = useRef<boolean>(authCheck());
//定时器描述
const _time = 60000;
//初始化字典
let dic: any = getDicData();
let dicData: any = JSON.parse(dic);
const columns: any[] = [
{
title: '省分',
dataIndex: 'provinceName',
key: 'provinceName',
width: '20%',
align: "center",
ellipsis: true,
onCell,
onHeaderCell,
// render: (_: any, record: any) => proviceEnum[record.provinceDictId],
},
{
title: '标段名称',
dataIndex: 'projectName',
key: 'projectName',
align: "center",
ellipsis: true,
width: '20%',
onCell,
onHeaderCell,
render: (_: any, record: any) => <span><span title={record.projectName}>{record.projectName}</span><br /><span title={record.sectionName}>{record.sectionName}</span></span>,
},
{
title: '采购预算',
dataIndex: 'bidSectContractPrice',
key: 'bidSectContractPrice',
align: "center",
width: '20%',
onCell,
onHeaderCell,
},
{
title: '开标时间',
dataIndex: 'openTime',
key: 'openTime',
align: "center",
width: '20%',
onCell,
onHeaderCell,
},
{
title: '标段状态',
dataIndex: 'sectionState',
key: 'sectionState',
align: "center",
width: '20%',
onCell,
onHeaderCell,
render: (_: any, record: any) => record?.sectionState == 9 ? "异常处理" : changeDict(record?.bidMethodDict ? dicData[`business_module=${record?.bidMethodDict}`] : [], record?.businessModule),
},
];
const reiColumns: any[] = [
{
title: '省分',
dataIndex: 'provinceName',
key: 'provinceName',
align: "center",
width: '20%',
ellipsis: true,
onCell,
onHeaderCell,
// render: (_: any, record: any) => proviceEnum[record.provinceDictId],
},
{
title: '标段名称',
dataIndex: 'projectName',
key: 'projectName',
align: "center",
ellipsis: true,
width: '20%',
onCell,
onHeaderCell,
render: (_: any, record: any) => <span><span title={record.projectName}>{record.projectName}</span><br /><span title={record.sectionName}>{record.sectionName}</span></span>,
},
{
title: '采购预算',
dataIndex: 'bidSectContractPrice',
key: 'bidSectContractPrice',
align: "center",
width: '20%',
onCell,
onHeaderCell,
},
{
title: '开标时间',
dataIndex: 'openTime',
key: 'openTime',
align: "center",
width: '20%',
onCell,
onHeaderCell,
},
{
title: '标段状态',
dataIndex: 'sectionState',
key: 'sectionState',
align: "center",
width: '20%',
onCell,
onHeaderCell,
render: (_: any, record: any) => record?.sectionState == 9 ? "异常处理" : changeDict(record?.bidMethodDict ? dicData[`business_module=${record?.bidMethodDict}`] : [], record?.businessModule),
},
];
//今日开标-评标阶段,评标及时率
const getTodayInfo = () => {
getTodayInfoAPI().then(res => {
@ -192,27 +212,62 @@ const OpenToday: React.FC<{}> = () => {
}
})
}
//页面数据获取
const getPageData = () => {
getTodayInfo();
getDecryptSuccessRateToday();
getTodayOpening();
getUnopenSix();
getUnopenTen();
getNoOpenNumber();
getNoOpenList();
}
useEffect(() => {
let interval: any;
if (auth.current) {
getTodayInfo();
getDecryptSuccessRateToday();
getTodayOpening();
getUnopenSix();
getUnopenTen();
getNoOpenNumber();
getNoOpenList();
getPageData();
interval = setInterval(() => {
getPageData();
}, _time);
}
return () => {
clearInterval(interval);
}
}, [])
useEffect(() => {
let interval: any = null;
let count = 0;
let lengthMap = [isNotEmpty(todayOpeningData?.todayList) ? todayOpeningData?.todayList.length : 0, isNotEmpty(todayOpeningData?.importantList) ? todayOpeningData?.importantList.length : 0].sort((a, b) => b - a);
if (lengthMap[0] > 1) {//至少2条才能滚动
interval = setInterval(() => {
if (count < lengthMap[0]) {
setSelectKey(count);
const v0 = document.getElementsByClassName("scroll-select-bg")[0];
const v1 = document.getElementsByClassName("scroll-select-bg")[1];
v0?.scrollIntoView(false);
v1?.scrollIntoView(false);
count++;
} else {
count = 0;
}
}, 3000)
}
return () => {
clearInterval(interval);
}
}, [todayOpeningData?.todayList, todayOpeningData?.importantList])
return (
<ScreenTitle title="今日开标">
<div className="top-main top-main-bottom">
<div className='monitor-top-exchange'>
<span onClick={() => { window.open("/ElecMonitor/Exception") }}></span>
<div className='monitor-exception-btn'>
<span onClick={() => { window.open("/ElecMonitor/Exception") }}></span>
</div>
</div>
<Row gutter={30}>
<Col span={7}>
<div className='monitor-tender-card'>
<div className='monitor-tender-top'>
<ScreenLabel title="开标阶段" />
<div className='monitor-tender-card'>
<StageCard percentage={isNotEmpty(todayOpeningData?.sectionNumber) && todayOpeningData?.sectionNumber != "0" ? Number(((Number(todayOpeningData?.banner) / todayOpeningData?.sectionNumber) * 100).toFixed(0)) : 0} total={isNotEmpty(todayOpeningData?.sectionNumber) ? todayOpeningData?.sectionNumber : 0} firstTitle="已开标" firstNumber={`${isNotEmpty(todayOpeningData?.openNumber) ? Number(todayOpeningData?.openNumber).toFixed(0) : 0}`} secondTitle="已解密" secondNumber={`${isNotEmpty(todayOpeningData?.decrypt) ? Number(todayOpeningData?.decrypt).toFixed(0) : 0}`} thirdTitle="已唱标" thirdNumber={`${isNotEmpty(todayOpeningData?.banner) ? Number(todayOpeningData?.banner).toFixed(0) : 0}`} />
@ -220,19 +275,19 @@ const OpenToday: React.FC<{}> = () => {
</div>
</Col>
<Col span={10}>
<div className="monitor-top-space-flex monitor-today-overview-width">
<div className="monitor-top-space-flex monitor-today-overview-width monitor-top-space-top">
<OverviewItem icon={Circle3199} title="标段总数" number={isNotEmpty(todayOpeningData?.sectionNumber) ? todayOpeningData?.sectionNumber : 0} unit="个" />
<OverviewItem icon={Circle3199} title="已完成" number={isNotEmpty(todayOpeningData?.complete) ? Number(todayOpeningData?.complete).toFixed(0) : 0} unit="个" />
<OverviewItem icon={Circle3199} title="完成率" number={isNotEmpty(todayOpeningData?.rate) ? todayOpeningData?.rate.slice(0, todayOpeningData?.rate.length - 1) : 0} unit="%" />
<OverviewItem icon={Circle3199} title="已开标" number={isNotEmpty(todayOpeningData?.openNumber) ? Number(todayOpeningData?.openNumber).toFixed(0) : 0} unit="个" />
<OverviewItem icon={Circle3199} title="已评标" number={isNotEmpty(todayInfoData?.openAssessNumber) ? todayInfoData?.openAssessNumber : 0} unit="" />
</div>
<div className="monitor-top-space-flex">
<ProgressItem progress={isNotEmpty(decryptSuccessRateTodayData?.successRate) ? Number(Number(decryptSuccessRateTodayData?.successRate).toFixed(0)) : 100} title="解密成功率" leftTitle='解密成功' rightTitle='解密失败' leftNumber={isNotEmpty(decryptSuccessRateTodayData?.successNum) ? Number(decryptSuccessRateTodayData?.successNum) : 0} rightNumber={isNotEmpty(decryptSuccessRateTodayData?.failNum) ? Number(decryptSuccessRateTodayData?.failNum) : 0} leftClick={() => { }} rightClick={() => { setExceptionType("解密异常"); setModalListData(isNotEmpty(decryptSuccessRateTodayData?.decryptFailProjectList) ? decryptSuccessRateTodayData?.decryptFailProjectList : []); setModalListVisible(true); }} />
<ProgressItem progress={isNotEmpty(todayOpeningData?.sectionNumber) ? todayOpeningData?.sectionNumber != 0 ? Number((((todayOpeningData?.sectionNumber - Number(noOpenNumberTwo)) / Number(todayOpeningData?.sectionNumber)) * 100).toFixed(0)) : 100 : 100} title="开标及时率" leftTitle='2小时未开标' rightTitle='5小时未开标' leftNumber={noOpenNumberTwo} rightNumber={noOpenNumberFive} leftClick={() => { setExceptionType(null); setModalListData(noOpenListTwo); setModalListVisible(true); }} rightClick={() => { setExceptionType(null); setModalListData(noOpenListFive); setModalListVisible(true); }} />
<ProgressItem progress={isNotEmpty(todayInfoData?.sectionNumber) ? todayInfoData?.sectionNumber != 0 ? Number((((todayInfoData?.sectionNumber - Number(todayInfoData?.sixTimelyRate)) / Number(todayInfoData?.sectionNumber)) * 100).toFixed(0)) : 100 : 100} title="评标及时率" leftTitle='6小时未评标' rightTitle='10小时未评标' leftNumber={todayInfoData?.sixTimelyRate} rightNumber={todayInfoData?.tenTimelyRate} leftClick={() => { setExceptionType(null); setModalListData(unopenSixData); setModalListVisible(true); }} rightClick={() => { setExceptionType(null); setModalListData(unopenTenData); setModalListVisible(true); }} />
<ProgressItem progress={isNotEmpty(todayOpeningData?.sectionNumber) ? todayOpeningData?.sectionNumber != 0 ? Number((((todayOpeningData?.sectionNumber - Number(noOpenNumberTwo)) / Number(todayOpeningData?.sectionNumber)) * 100).toFixed(0)) : 100 : 100} title="开标及时率" leftTitle='2小时未开标' rightTitle='5小时未开标' leftNumber={noOpenNumberTwo} rightNumber={noOpenNumberFive} leftClick={() => { setExceptionType("2小时未开标"); setModalListData(noOpenListTwo); setModalListVisible(true); }} rightClick={() => { setExceptionType("5小时未开标"); setModalListData(noOpenListFive); setModalListVisible(true); }} />
<ProgressItem progress={isNotEmpty(todayInfoData?.sectionNumber) ? todayInfoData?.sectionNumber != 0 ? Number((((todayInfoData?.sectionNumber - Number(todayInfoData?.sixTimelyRate)) / Number(todayInfoData?.sectionNumber)) * 100).toFixed(0)) : 100 : 100} title="评标及时率" leftTitle='6小时未评标' rightTitle='10小时未评标' leftNumber={todayInfoData?.sixTimelyRate} rightNumber={todayInfoData?.tenTimelyRate} leftClick={() => { setExceptionType("6小时未评标"); setModalListData(unopenSixData); setModalListVisible(true); }} rightClick={() => { setExceptionType("10小时未评标"); setModalListData(unopenTenData); setModalListVisible(true); }} />
</div>
</Col>
<Col span={7}>
<div className='monitor-tender-card'>
<div className='monitor-tender-top'>
<ScreenLabel title="评标阶段" />
<div className='monitor-tender-card'>
<StageCard percentage={(isNotEmpty(todayInfoData?.sectionNumber) && todayInfoData?.sectionNumber != "0") ? Number(((Number(todayInfoData?.resultNumber) / todayInfoData?.sectionNumber) * 100).toFixed(0)) : 0} total={isNotEmpty(todayInfoData?.sectionNumber) ? todayInfoData?.sectionNumber : 0} firstTitle="开启评审" firstNumber={`${isNotEmpty(todayInfoData?.openAssessNumber) ? todayInfoData?.openAssessNumber : 0}`} secondTitle="专家签到" secondNumber={`${isNotEmpty(todayInfoData?.signExpertNumber) ? todayInfoData?.signExpertNumber : 0}/${isNotEmpty(todayInfoData?.totalExpertNumber) ? todayInfoData?.totalExpertNumber : 0}`} thirdTitle="评审汇总" thirdNumber={`${isNotEmpty(todayInfoData?.resultNumber) ? todayInfoData?.resultNumber : 0}`} />
@ -245,13 +300,13 @@ const OpenToday: React.FC<{}> = () => {
<Col span={12}>
<ScreenLabel title="今日开标明细" />
<div className='monitor-tender-card'>
<ScrollTable dataSource={todayOpeningData?.todayList} columns={columns} ynum={530} />
<ScrollTable dataSource={todayOpeningData?.todayList} columns={columns} ynum={540} selectKey={selectKey} />
</div>
</Col>
<Col span={12}>
<ScreenLabel title="重保项目" />
<div className='monitor-tender-card'>
<ScrollTable dataSource={isNotEmpty(todayOpeningData?.importantList) ? todayOpeningData?.importantList : []} columns={reiColumns} ynum={530} />
<ScrollTable dataSource={isNotEmpty(todayOpeningData?.importantList) ? todayOpeningData?.importantList : []} columns={reiColumns} ynum={540} selectKey={selectKey} />
</div>
</Col>
</Row>

View File

@ -1,11 +1,12 @@
import { Col, Progress, Row } from 'antd';
import React, { useEffect, useMemo, useRef, useState } from 'react';
import '../style.less'
import { authCheck, GraphChart, MetricItems, onCell, onHeaderCell, ScreenLabel, ScreenTitle, SelectItem, StatisticTable } from '../Home';
import { authCheck, GraphChart, MetricItems, onCell, onHeaderCell, ScreenLabel, ScreenTitle, SelectItem, StatisticTable, yearMap } from '../Home';
import Frame10116 from '@/assets/monitor/Frame-10116.png';
import Frame10121 from '@/assets/monitor/Frame-10121.png';
import { getActiveSupplierRankAPI, getProvinceActiveSupplierInfoAPI, getSupplierInfoAPI } from '../service';
import { isNotEmpty } from '@/utils/CommonUtils';
import moment from 'moment';
const columns: any[] = [
{
@ -70,13 +71,16 @@ const Supplier: React.FC<{}> = () => {
const monthOrYear = useRef<string>("yearData");
//指标项 tenderCount-投标次数 selectCount-中选次数 bidCost-中选金额
const metric = useRef<string>("tenderCount");
const metricMap = { tenderCount: "投标次数", selectCount: "中选次数", bidCost: "中选金额" };
const metricMap = { tenderCount: "投标次数", selectCount: "中选次数", bidCost: "中选金额(万元)" };
//省份
const province = useRef<string>("");
//图表数据
const [chartData, setChartData] = useState<any[]>([]);
//权限校验
const auth = useRef<boolean>(authCheck());
//year select
const localYear: string = moment().month() < 2 ? String(moment().year() - 1) : String(moment().year());
const [yearSelect, setYearSelect] = useState<string>(localYear);
const transverseBarChart = useMemo(() => {
return chartData.length > 0 && <GraphChart type="transverseBar" chartData={chartData} />
}, [chartData])
@ -90,16 +94,16 @@ const Supplier: React.FC<{}> = () => {
}, [provinceData])
//上面六个指标
const getSupplierInfo = () => {
getSupplierInfoAPI().then(res => {
const getSupplierInfo = (ym: string) => {
getSupplierInfoAPI(ym).then(res => {
if (res?.code == 200) {
setSupplierInfoData(res?.data);
}
})
}
//全国活跃供应商排名
const getActiveSupplierRank = () => {
getActiveSupplierRankAPI().then(res => {
const getActiveSupplierRank = (ym: string) => {
getActiveSupplierRankAPI(ym).then(res => {
if (res?.code == 200) {
const data = JSON.parse(res?.data)
rankDataRef.current = data;
@ -108,24 +112,27 @@ const Supplier: React.FC<{}> = () => {
})
}
//供应商概况-省份活跃供应商
const getProvinceActiveSupplierInfo = () => {
getProvinceActiveSupplierInfoAPI().then(res => {
const getProvinceActiveSupplierInfo = (ym: string) => {
getProvinceActiveSupplierInfoAPI(ym).then(res => {
if (res?.code == 200) {
provinceActiveSupplierInfoData.current = res?.data;
setProvinceData(res?.data.map((item: any) => ({ name: item.provinceName, value: 0 })))
const data = res?.data ? res?.data : [];
provinceActiveSupplierInfoData.current = data;
setProvinceData(data.map((item: any) => ({ name: item.provinceName, value: item.supplierCount, data: item })))
}
})
}
//onSelectChange select变更事件
const onSelectChange = (value: string | number) => {
if (rankDataRef.current) {
const data = rankDataRef.current[value];
const data = rankDataRef.current[value] ? rankDataRef.current[value] : [];
if (data.length > 0) {
const max = data[0].tenderCount;
for (let i = 0, length = data.length; i < length; i++) {
data[i]["maxTenderCount"] = max;
}
setActiveSupplierRankData(data)
setActiveSupplierRankData(data);
} else {
setActiveSupplierRankData([]);
}
}
@ -157,18 +164,25 @@ const Supplier: React.FC<{}> = () => {
}
}
}
//onYearSelect
const onYearSelect = (value: string) => {
setYearSelect(value);
}
useEffect(() => {
if (auth.current) {
getSupplierInfo();
getActiveSupplierRank();
getProvinceActiveSupplierInfo();
getSupplierInfo(yearSelect);
getActiveSupplierRank(yearSelect);
getProvinceActiveSupplierInfo(yearSelect);
}
}, [])
}, [yearSelect])
return (
<ScreenTitle title="供应商概况">
<div className="top-main">
<div className="monitor-top-space-flex">
<div className='monitor-top-exchange'>
<SelectItem options={yearMap} onSelectChange={onYearSelect} defaultText={localYear + "年"} />
</div>
<div className="monitor-top-space-flex monitor-top-space-top monitor-top-flex-space">
<MetricItems icon={Frame10116} title="投标总次数" number={supplierInfoData?.totalTenderCount} unit="次" />
<MetricItems icon={Frame10121} title="投标供应商" number={supplierInfoData?.totalSupplierCount} unit="家" />
<MetricItems icon={Frame10116} title="年度投标次数" number={supplierInfoData?.yearlyTotalTenderCount} unit="次" />
@ -191,7 +205,7 @@ const Supplier: React.FC<{}> = () => {
</Col>
<Col span={16}>
<div className="monitor-right-main">
<ScreenLabel title="省分活跃供应商排名" extra={<span><span className={monthOrYear.current == "yearData" ? 'monitor-extra-pointer monitor-extra-pointer-select' : 'monitor-extra-pointer'} onClick={() => { monthOrYear.current = "yearData"; chartDataChange(); }}></span> | <span className={monthOrYear.current == "monthData" ? 'monitor-extra-pointer monitor-extra-pointer-select' : 'monitor-extra-pointer'} onClick={() => { monthOrYear.current = "monthData"; chartDataChange(); }}></span>&nbsp;&nbsp;&nbsp;&nbsp;<span className={metric.current == "tenderCount" ? 'monitor-extra-pointer monitor-extra-pointer-select' : 'monitor-extra-pointer'} onClick={() => { metric.current = "tenderCount"; chartDataChange(); }}></span> | <span className={metric.current == "selectCount" ? 'monitor-extra-pointer monitor-extra-pointer-select' : 'monitor-extra-pointer'} onClick={() => { metric.current = "selectCount"; chartDataChange(); }}></span> | <span className={metric.current == "bidCost" ? 'monitor-extra-pointer monitor-extra-pointer-select' : 'monitor-extra-pointer'} onClick={() => { metric.current = "bidCost"; chartDataChange(); }}></span>&nbsp;&nbsp;&nbsp;&nbsp;{province.current}</span>} />
<ScreenLabel title="省分活跃供应商排名" extra={<span><span className={metric.current == "tenderCount" ? 'monitor-extra-pointer monitor-extra-pointer-select' : 'monitor-extra-pointer'} onClick={() => { metric.current = "tenderCount"; chartDataChange(); }}></span> | <span className={metric.current == "selectCount" ? 'monitor-extra-pointer monitor-extra-pointer-select' : 'monitor-extra-pointer'} onClick={() => { metric.current = "selectCount"; chartDataChange(); }}></span> | <span className={metric.current == "bidCost" ? 'monitor-extra-pointer monitor-extra-pointer-select' : 'monitor-extra-pointer'} onClick={() => { metric.current = "bidCost"; chartDataChange(); }}></span>&nbsp;&nbsp;&nbsp;&nbsp;{province.current}</span>} />
<Row>
<Col span={14}>
<div className="monitor-supplier-rank">

View File

@ -1,13 +1,14 @@
import { Col, Radio, Row } from 'antd';
import React, { useEffect, useMemo, useRef, useState } from 'react';
import '../style.less'
import { authCheck, GraphChart, onCell, onHeaderCell, OverviewItem, ScreenLabel, ScreenTitle, SelectItem, StatisticTable } from '../Home';
import { authCheck, GraphChart, onCell, onHeaderCell, OverviewItem, ScreenLabel, ScreenTitle, SelectItem, SelectRadio, StatisticTable, yearMap } from '../Home';
import Circle3197 from '@/assets/monitor/circle-3197.png';
import Circle3198 from '@/assets/monitor/circle-3198.png';
import Circle3199 from '@/assets/monitor/circle-3199.png';
import Circle3200 from '@/assets/monitor/circle-3200.png';
import { getTenderAgentDataAPI, getProvinceByAgencyAPI } from '../service';
import { isNotEmpty } from '@/utils/CommonUtils';
import moment from 'moment';
const columns: any[] = [
{
@ -71,6 +72,11 @@ const TenderAgent: React.FC<{}> = () => {
const [provinceData, setProvinceData] = useState<any[]>([]);
//btn select
const [btnSelect, setBtnSelect] = useState<string>("0");
//year select
const localYear: string = moment().month() < 2 ? String(moment().year() - 1) : String(moment().year());
const [yearSelect, setYearSelect] = useState<string>(localYear);
//存一份
const selectAgency = useRef<string>("");
//权限校验
const auth = useRef<boolean>(authCheck());
// const gaugeChartData = [{ value: 20 }]
@ -94,8 +100,8 @@ const TenderAgent: React.FC<{}> = () => {
}, [provinceByAgencyData])
//相关统计数据
const getTenderAgentData = () => {
getTenderAgentDataAPI().then(res => {
const getTenderAgentData = (year: string) => {
getTenderAgentDataAPI(year).then(res => {
if (res?.code == 200) {
setTenderAgentData(res?.data);
const data = res?.data.agencyProjectMonth;//左侧条形图数据处理
@ -113,7 +119,7 @@ const TenderAgent: React.FC<{}> = () => {
setMonthData(monthDataMap)
const selectData: any[] = res?.data.agencyList.map((item: any) => ({ label: item.agencyName, value: item.agencyId }));//右侧代理机构下拉
selectData.unshift({ label: "请选择", value: "all" });
// selectData.unshift({ label: "请选择", value: "all" });
setSelectData(selectData);
const province = res?.data.agencyListByProvince;//招标代理省份分布数据
@ -129,8 +135,8 @@ const TenderAgent: React.FC<{}> = () => {
})
}
//代理分布省分
const getProvinceByAgency = (agencyId: string) => {
getProvinceByAgencyAPI(agencyId).then(res => {
const getProvinceByAgency = (agencyId: string, year: string) => {
getProvinceByAgencyAPI(agencyId, year).then(res => {
if (res?.code == 200) {
const data = res?.data;
const agencyData = data.map((item: any) => ({ name: item.province, value: Number(item.dlxms), data: item }));
@ -143,20 +149,27 @@ const TenderAgent: React.FC<{}> = () => {
}
//onSelectChange select变更事件
const onSelectChange = (value: string) => {
if (value != "all") {
getProvinceByAgency(value);
} else {
setProvinceByAgencyData([]);
}
getProvinceByAgency(value, yearSelect);
selectAgency.current = value;
}
//onYearSelect
const onYearSelect = (value: string) => {
setYearSelect(value);
}
useEffect(() => {
if (auth.current) {
getTenderAgentData();
getTenderAgentData(yearSelect);
if (selectAgency.current != "") {
getProvinceByAgency(selectAgency.current, yearSelect);
}
}
}, [])
}, [yearSelect])
return (
<ScreenTitle title="招标代理机构概况">
<div className="top-main top-main-bottom">
<div className='monitor-top-exchange'>
<SelectItem options={yearMap} onSelectChange={onYearSelect} defaultText={localYear + "年"} />
</div>
<Row gutter={50} className="monitor-top-space-top">
<Col span={24}>
<ScreenLabel title="年度概览" />
@ -164,7 +177,7 @@ const TenderAgent: React.FC<{}> = () => {
<OverviewItem icon={Circle3197} title="代理机构数量" number={tenderAgentData?.agencyProjectCountYear.dljg} unit="个" />
<OverviewItem icon={Circle3198} title="代理机构人员数量" number={tenderAgentData?.agencyProjectCountYear.dljgry} unit="人" />
<OverviewItem icon={Circle3199} title="代理机构项目数量" number={tenderAgentData?.agencyProjectCountYear.dlxms} unit="个" />
<OverviewItem icon={Circle3200} title="代理项目预算金额" number={tenderAgentData?.agencyProjectCountYear.dlxmys} unit="亿元" />
<OverviewItem icon={Circle3200} title="代理项目预算金额" number={tenderAgentData?.agencyProjectCountYear.dlxmys?.toFixed(0)} unit="亿元" />
<OverviewItem icon={Circle3199} title="代理项目完成率" number={isNotEmpty(tenderAgentData?.agencyProjectCountYear.wcl) ? (tenderAgentData?.agencyProjectCountYear.wcl * 100).toFixed(0) : 0} unit="%" />
</div>
</Col>
@ -194,7 +207,7 @@ const TenderAgent: React.FC<{}> = () => {
{categoryChart}
</div>
<div>
<StatisticTable dataSource={tenderAgentData?.agencyProjectListYear} columns={columns} ynum={266} />
<StatisticTable dataSource={tenderAgentData?.agencyProjectListYear?.slice(0, 15)} columns={columns} ynum={266} />
</div>
</Col>
<Col span={16}>
@ -204,7 +217,7 @@ const TenderAgent: React.FC<{}> = () => {
<Radio.Button value="0"></Radio.Button>
<Radio.Button value="1"></Radio.Button>
</Radio.Group>
<SelectItem options={selectData} onSelectChange={onSelectChange} defaultText="请选择" hidden={btnSelect == "1"} />
<SelectRadio options={selectData} onSelectChange={onSelectChange} defaultText="请选择" hidden={btnSelect == "1"} />
</div>
<div className="monitor-tender-map">
{btnSelect == "0" ? agencyMapChart : mapChart}

View File

@ -35,8 +35,8 @@ export async function getOpeningListAPI(data: any) {
* 首页-上面前三个指标和招标代理实施项目统计
* @param data
*/
export async function getAnnualAndTenderAgentAPI() {
return request('/api/biz-service-ebtp-statistics/indexMonitor/getProjectData', {
export async function getAnnualAndTenderAgentAPI(year: any) {
return request(`/api/biz-service-ebtp-statistics/indexMonitor/getProjectData/${year}`, {
method: 'GET',
});
}
@ -45,8 +45,8 @@ export async function getAnnualAndTenderAgentAPI() {
* 首页-活跃供应商
* @param data
*/
export async function getActiveSupplierAPI() {
return request('/api/biz-service-ebtp-statistics/indexMonitor/indexQuerySupplier', {
export async function getActiveSupplierAPI(params: any) {
return request(`/api/biz-service-ebtp-statistics/indexMonitor/indexQuerySupplier/${params}`, {
method: 'GET',
});
}
@ -55,9 +55,9 @@ export async function getActiveSupplierAPI() {
* 首页-参与供应商数
*/
export async function getSupplierCountAPI(params: any) {
return request('/api/biz-service-ebtp-statistics/v1/tenderMonitor/supplierCount', {
return request(`/api/biz-service-ebtp-statistics/v1/tenderMonitor/supplierCount`, {
method: 'GET',
params: { ...params }
params: params
});
}
@ -65,9 +65,8 @@ export async function getSupplierCountAPI(params: any) {
* 首页-公告公示数量
*/
export async function getAnnoCountAPI(params: any) {
return request('/api/biz-service-ebtp-statistics/indexMonitor/annoCount', {
return request(`/api/biz-service-ebtp-statistics/indexMonitor/annoCount/${params}`, {
method: 'GET',
params: { ...params }
});
}
@ -131,6 +130,17 @@ export async function getNoOpenAssessListAPI(data: any) {
});
}
/**
* 异常监控-开标后超过6小时未开启评审室-数量
* @param data
*/
export async function getNoOpenAssessNumberAPI(data: any) {
return request('/api/biz-service-ebtp-statistics/opening/noOpenAssessNumber', {
method: 'POST',
data: { ...data },
});
}
/**
* 异常监控-解密异常、mac地址相同及相关项目列表
*/
@ -195,8 +205,8 @@ export async function getDecryptSuccessRateTodayAPI() {
/**
* 供应商概况-上面六个指标
*/
export async function getSupplierInfoAPI() {
return request('/api/biz-service-ebtp-statistics/v1/tenderMonitor/supplierInfo', {
export async function getSupplierInfoAPI(params: any) {
return request(`/api/biz-service-ebtp-statistics/v1/tenderMonitor/supplierInfo/${params}`, {
method: 'GET',
});
}
@ -204,8 +214,8 @@ export async function getSupplierInfoAPI() {
/**
* 供应商概况-全国活跃供应商排名
*/
export async function getActiveSupplierRankAPI() {
return request('/api/biz-service-ebtp-statistics/v1/tenderMonitor/activeSupplierRank', {
export async function getActiveSupplierRankAPI(params: any) {
return request(`/api/biz-service-ebtp-statistics/v1/tenderMonitor/activeSupplierRank/${params}`, {
method: 'GET',
});
}
@ -213,8 +223,8 @@ export async function getActiveSupplierRankAPI() {
/**
* 供应商概况-省份活跃供应商
*/
export async function getProvinceActiveSupplierInfoAPI() {
return request('/api/biz-service-ebtp-statistics/v1/tenderMonitor/provinceActiveSupplierInfo', {
export async function getProvinceActiveSupplierInfoAPI(params: any) {
return request(`/api/biz-service-ebtp-statistics/v1/tenderMonitor/provinceActiveSupplierInfo/${params}`, {
method: 'GET',
});
}
@ -222,16 +232,16 @@ export async function getProvinceActiveSupplierInfoAPI() {
/**
* 招标代理机构概况-相关统计数据
*/
export async function getTenderAgentDataAPI() {
return request('/api/biz-service-ebtp-statistics/tenderAgent/getTenderAgentData', {
export async function getTenderAgentDataAPI(year: string) {
return request('/api/biz-service-ebtp-statistics/tenderAgent/getTenderAgentData/' + year, {
method: 'GET',
});
}
/**
* 招标代理机构概况-代理分布省分
*/
export async function getProvinceByAgencyAPI(agencyId: any) {
return request(`/api/biz-service-ebtp-statistics/tenderAgent/getProvinceByAgency/${agencyId}`, {
export async function getProvinceByAgencyAPI(agencyId: any, year: any) {
return request(`/api/biz-service-ebtp-statistics/tenderAgent/getProvinceByAgency/${agencyId}/${year}`, {
method: 'GET',
});
}

View File

@ -81,26 +81,25 @@
.monitor-top-main-flex {
margin-left: 80px;
margin-top: 20px;
margin-top: 8px;
}
.monitor-top-exchange {
height: 16px;
line-height: 16px;
color: #FFFFFF;
text-align: right;
display: flex;
justify-content: flex-end;
align-items: center;
&>span {
font-size: 14px;
color: #FFFFFF;
line-height: 16px;
cursor: pointer;
.monitor-exception-btn {
.monitor-select-btn;
background-color: #12304e99;
&:hover {
color: #1b7ef2;
text-decoration: underline;
&>span {
color: #1b7ef2;
}
}
}
}
.monitor-top-space-flex {
@ -135,7 +134,11 @@
}
.monitor-top-space-top {
margin-top: 20px;
margin-top: 8px;
}
.monitor-top-flex-space {
justify-content: space-around;
}
}
@ -246,13 +249,14 @@
height: 170px;
background-clip: border-box;
filter: blur(0px);
.flex-center;
.card-default-01 {
background-image: url('~@/assets/screen/default_pic01.jpg');
background-repeat: no-repeat;
background-size: 100% 100%;
height: 120px;
margin-top: 14px;
margin-top: 20px;
position: relative;
cursor: pointer;
@ -407,6 +411,10 @@
margin-top: 20px;
}
.monitor-tender-top {
margin-top: 8px;
}
.monitor-supplier-card {
margin-top: 20px;
text-align: right;
@ -716,6 +724,10 @@
.ant-table-body {
height: var(--monitor-table-height);
}
.scroll-select-bg {
background: #66666666;
}
}
.monitor-statistic-table {
@ -1013,11 +1025,6 @@
.monitor-select-dropdown {
&>ul {
height: 99vh;
overflow-y: scroll;
}
.ant-dropdown-menu {
background-color: #081a30;
}
@ -1033,6 +1040,36 @@
}
}
.monitor-select-radio-dropdown {
.ant-dropdown-menu {
background-color: #081a30;
width: 900px;
}
.ant-dropdown-menu-item,
.ant-dropdown-menu-submenu-title {
color: #FFFFFF;
display: inline-block;
}
.ant-dropdown-menu-item:hover,
.ant-dropdown-menu-submenu-title:hover {
background-color: #1b7ef2;
}
.ant-dropdown-menu-item:first-child,
.ant-dropdown-menu-submenu-title:first-child {
background-color: transparent;
width: 900px;
&>div>input {
color: #fff;
width: 50%;
}
}
}
.monitor-select-btn {
outline: none;
position: relative;
@ -1111,14 +1148,14 @@
line-height: 16px;
}
}
}
.monitor-modal-empty {
.ant-empty-image {
color: #fff;
}
.monitor-modal-empty {
.ant-empty-image {
color: #fff;
}
.ant-empty-description {
color: #fff;
}
.ant-empty-description {
color: #fff;
}
}