diff --git a/src/assets/images/warn.png b/src/assets/images/warn.png new file mode 100644 index 0000000000000000000000000000000000000000..8d97c57fdea03073b3352d0e3e0b1e14061354f7 Binary files /dev/null and b/src/assets/images/warn.png differ diff --git a/src/components/DescriptionItem/index.less b/src/components/DescriptionItem/index.less index 39e477f801901772f3003429a638e8b0513a9665..00134b0cfc0654dddb3ab82d63168c93742d0eea 100644 --- a/src/components/DescriptionItem/index.less +++ b/src/components/DescriptionItem/index.less @@ -1,6 +1,8 @@ .value { font-family: D-DIN; font-size: 30px; +} +.gradientValue { background: linear-gradient(to bottom, rgb(170, 255, 246), rgb(37, 187, 255)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; diff --git a/src/components/DescriptionItem/index.tsx b/src/components/DescriptionItem/index.tsx index c9c647a8fcb17b75a06b2bca15a541ee0c00c0d4..340515e1b833c15d500c65abe1fbf3849e4c3ef6 100644 --- a/src/components/DescriptionItem/index.tsx +++ b/src/components/DescriptionItem/index.tsx @@ -1,5 +1,6 @@ import { Space } from 'antd'; -import React, { CSSProperties, memo } from 'react'; +import classNames from 'classnames'; +import React, { CSSProperties, Fragment, memo } from 'react'; import CountUp from 'react-countup'; import styles from './index.less'; @@ -17,6 +18,7 @@ interface DescriptionItemProps { onClick?: () => void; } +/** @name 描述列表项 */ const DescriptionItem: React.FC<DescriptionItemProps> = memo((props) => { const { value, @@ -35,7 +37,9 @@ const DescriptionItem: React.FC<DescriptionItemProps> = memo((props) => { const ValueAndUnit = ( <Space align="center" size="small"> <CountUp - className={styles.value} + className={classNames(styles.value, { + [styles.gradientValue]: !valueStyle?.color, + })} end={Number(value)} style={valueStyle} preserveValue @@ -62,15 +66,15 @@ const DescriptionItem: React.FC<DescriptionItemProps> = memo((props) => { style={{ ...style, cursor: onClick ? 'pointer' : 'default' }} > {reverseName ? ( - <> + <Fragment> {Label} {ValueAndUnit} - </> + </Fragment> ) : ( - <> + <Fragment> {ValueAndUnit} {Label} - </> + </Fragment> )} </div> ); diff --git a/src/pages/GlobalModalServices/index.tsx b/src/pages/GlobalModalServices/index.tsx index 4728027709151c287f0aeecd760f0d6222ab9336..a4469d503bc6dfd167a59ad319f9daf3e7f92fd8 100644 --- a/src/pages/GlobalModalServices/index.tsx +++ b/src/pages/GlobalModalServices/index.tsx @@ -30,7 +30,7 @@ const getModalElement = (modalKey: ModalKey) => { } }; -/** @module 全居弹窗服务 */ +/** @module 全局弹窗服务 */ const GlobalModalServices: React.ForwardRefRenderFunction< GlobalModalServicesModalMethods, any @@ -230,7 +230,15 @@ const GlobalModalServices: React.ForwardRefRenderFunction< const lastModal = stacks.at(-1); if (lastModal) { - const { w, h, thread, zIndex, component: Component, props } = lastModal; + const { + w, + h, + thread, + zIndex, + component: Component, + style, + props, + } = lastModal; const metaProps = { ...props, @@ -254,7 +262,7 @@ const GlobalModalServices: React.ForwardRefRenderFunction< width={w} height={h} key={lastModal.modalId} - style={{ zIndex: zIndex ?? 1000 }} + style={{ ...style, zIndex: zIndex ?? 1000 }} open titleRender={titleRender.bind(this, lastModal, stacks)} > diff --git a/src/pages/GlobalModalServices/modals/ConstructionWaste/components/DisposalSiteInfo/index.css b/src/pages/GlobalModalServices/modals/ConstructionWaste/components/DisposalSiteInfo/index.css new file mode 100644 index 0000000000000000000000000000000000000000..65517a361ecfe36f3e1430f27be98d4186e44123 --- /dev/null +++ b/src/pages/GlobalModalServices/modals/ConstructionWaste/components/DisposalSiteInfo/index.css @@ -0,0 +1,48 @@ +.container { + width: 520px; + height: 345px; + background: rgba(57, 122, 183, 0.2); + border-radius: 20px; +} +.container .title { + color: #cbedff; + font-family: 'DingTalk JinBuTi'; + font-size: 22px; + font-weight: 400; + line-height: 26px; + padding: 20px 0 0 24px; +} +.container .content { + padding: 21px 28px; + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 37px; +} +.container .infoItem .valueWrapper { + display: flex; + align-items: baseline; + gap: 4px; +} +.container .infoItem .valueWrapper .value { + background: linear-gradient(180deg, #AAFFF6 0%, #25BBFF 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + font-family: 'D-DIN'; + font-size: 36px; + font-weight: 700; + line-height: 1; +} +.container .infoItem .valueWrapper .unit { + color: #bccee9; + font-family: '微软雅黑'; + font-size: 20px; + font-weight: 400; +} +.container .infoItem .label { + color: #bccee9; + font-family: '微软雅黑'; + font-size: 20px; + font-weight: 400; + line-height: 26px; + margin-top: 15px; +} diff --git a/src/pages/GlobalModalServices/modals/ConstructionWaste/components/DisposalSiteInfo/index.less b/src/pages/GlobalModalServices/modals/ConstructionWaste/components/DisposalSiteInfo/index.less new file mode 100644 index 0000000000000000000000000000000000000000..f4963b1e1e4a0b338835678d28e0c5f8024d9c8a --- /dev/null +++ b/src/pages/GlobalModalServices/modals/ConstructionWaste/components/DisposalSiteInfo/index.less @@ -0,0 +1,56 @@ +.container { + width: 520px; + height: 345px; + background: rgba(57, 122, 183, 0.2); + border-radius: 20px; + + .title { + color: rgb(203, 237, 255); + font-family: 'DingTalk JinBuTi'; + font-size: 22px; + font-weight: 400; + line-height: 26px; + padding: 20px 0 0 24px; + } + + .content { + padding: 21px 28px; + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 37px; + } + + .infoItem { + .valueWrapper { + display: flex; + align-items: baseline; + gap: 4px; + + .value { + background: linear-gradient(180deg, #AAFFF6 0%, #25BBFF 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + font-family: 'D-DIN'; + font-size: 36px; + font-weight: 700; + line-height: 1; + } + + .unit { + color: rgb(188, 206, 233); + font-family: '微软雅黑'; + font-size: 20px; + font-weight: 400; + } + } + + .label { + color: rgb(188, 206, 233); + font-family: '微软雅黑'; + font-size: 20px; + font-weight: 400; + line-height: 26px; + margin-top: 15px; + } + } +} \ No newline at end of file diff --git a/src/pages/GlobalModalServices/modals/ConstructionWaste/components/DisposalSiteInfo/index.tsx b/src/pages/GlobalModalServices/modals/ConstructionWaste/components/DisposalSiteInfo/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..b68c67ab15c8c8969b85751ab1be20fb2ac22218 --- /dev/null +++ b/src/pages/GlobalModalServices/modals/ConstructionWaste/components/DisposalSiteInfo/index.tsx @@ -0,0 +1,70 @@ +import React from 'react'; +import styles from './index.less'; + +interface InfoItemProps { + value: string | number; + label: string; + unit: string; +} +let isUsingValue = false; +const showValue = (value: number | string) => { + if(isUsingValue){ + return value; + } + return '--'; +} + +const InfoItem: React.FC<InfoItemProps> = ({ value, label, unit }) => ( + <div className={styles.infoItem}> + <div className={styles.valueWrapper}> + <span className={styles.value}>{showValue(value)}</span> + <span className={styles.unit}>{unit}</span> + </div> + <div className={styles.label}>{label}</div> + </div> +); + +interface DisposalSiteInfoProps { + searchTime: { + startTime: string; + endTime: string; + }; +} + +const DisposalSiteInfo: React.FC<DisposalSiteInfoProps> = ({ searchTime }) => { + const infoData = [ + { + value: 482, + label: '固定式建筑垃圾消纳场数量', + unit: '个' + }, + { + value: 482, + label: '临时性建筑垃圾转动调配场数量', + unit: '个' + }, + { + value: 482.21, + label: '总容量', + unit: '万方' + }, + { + value: 482.54, + label: '剩余库容', + unit: '万方' + } + ]; + + return ( + <div className={styles.container}> + <div className={styles.title}>消纳场概况</div> + <div className={styles.content}> + {infoData.map((item, index) => ( + <InfoItem key={index} {...item} /> + ))} + </div> + </div> + ); +}; + +export default DisposalSiteInfo; \ No newline at end of file diff --git a/src/pages/GlobalModalServices/modals/ConstructionWaste/components/DistributionChart/index.css b/src/pages/GlobalModalServices/modals/ConstructionWaste/components/DistributionChart/index.css new file mode 100644 index 0000000000000000000000000000000000000000..6b2131a7962b61be1e3af984e9c388ab3bffd1d7 --- /dev/null +++ b/src/pages/GlobalModalServices/modals/ConstructionWaste/components/DistributionChart/index.css @@ -0,0 +1,43 @@ +.container { + width: 2445px; + height: 334px; + background: rgba(57, 122, 183, 0.2); + border-radius: 20px; +} +.container .tabs { + padding: 20px 24px 0; +} +.container .tabs :global .ant-tabs-nav { + margin: 0; +} +.container .tabs :global .ant-tabs-nav::before { + border-bottom: none; +} +.container .tabs :global .ant-tabs-tab { + padding: 0; + margin-right: 40px; +} +.container .tabs :global .ant-tabs-tab .ant-tabs-tab-btn { + color: #BCCEE9; + font-size: 22px; + font-family: 'DingTalk JinBuTi'; + line-height: 26px; +} +.container .tabs :global .ant-tabs-tab-active .ant-tabs-tab-btn { + color: #CBEDFF; +} +.container .tabs :global .ant-tabs-ink-bar { + background: #CBEDFF; +} +.container .chartWrapper { + height: calc(100% - 66px); + position: relative; + padding: 0 20px; +} +.container .chartWrapper .yAxisLabel { + position: absolute; + left: 24px; + top: 10px; + color: #BCCEE9; + font-size: 16px; +} diff --git a/src/pages/GlobalModalServices/modals/ConstructionWaste/components/DistributionChart/index.less b/src/pages/GlobalModalServices/modals/ConstructionWaste/components/DistributionChart/index.less new file mode 100644 index 0000000000000000000000000000000000000000..253d97d63fa08b63f96249c5930a4f9551351b2e --- /dev/null +++ b/src/pages/GlobalModalServices/modals/ConstructionWaste/components/DistributionChart/index.less @@ -0,0 +1,53 @@ +.container { + width: 2445px; + height: 334px; + background: rgba(57, 122, 183, 0.2); + border-radius: 20px; + + .tabs { + padding: 20px 24px 0; + + :global { + .ant-tabs-nav { + margin: 0; + &::before { + border-bottom: none; + } + } + + .ant-tabs-tab { + padding: 0; + margin-right: 40px; + + .ant-tabs-tab-btn { + color: #BCCEE9; + font-size: 22px; + font-family: 'DingTalk JinBuTi'; + line-height: 26px; + } + } + + .ant-tabs-tab-active .ant-tabs-tab-btn { + color: #CBEDFF; + } + + .ant-tabs-ink-bar { + background: #CBEDFF; + } + } + } + + .chartWrapper { + height: calc(100% - 66px); + position: relative; + padding: 0 20px; + + .yAxisLabel { + position: absolute; + left: 24px; + top: 10px; + color: #BCCEE9; + font-size: 16px; + } + } +} \ No newline at end of file diff --git a/src/pages/GlobalModalServices/modals/ConstructionWaste/components/DistributionChart/index.tsx b/src/pages/GlobalModalServices/modals/ConstructionWaste/components/DistributionChart/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..33376fcb6b2ce6c59389d261f3097868cf78634f --- /dev/null +++ b/src/pages/GlobalModalServices/modals/ConstructionWaste/components/DistributionChart/index.tsx @@ -0,0 +1,164 @@ +import React, { useState, useEffect, useRef } from 'react'; +import * as echarts from 'echarts'; +import styles from './index.less'; +import { Tabs } from 'antd'; + +interface DistributionChartProps { + searchTime: { + startTime: string; + endTime: string; + }; +} + +const DistributionChart: React.FC<DistributionChartProps> = ({ searchTime }) => { + const chartRef = useRef<HTMLDivElement>(null); + const [activeTab, setActiveTab] = useState('1'); + + const tabItems = [ + { + key: '1', + label: '建筑垃圾申报排放量区域分布', + }, + { + key: '2', + label: '疑似违规倾倒点位区域分布', + }, + ]; + + let isUsingValue = false; + + useEffect(() => { + if (!chartRef.current) return; + + const chart = echarts.init(chartRef.current); + + // 模拟数据 + const data = Array(22).fill(0).map(() => ({ + wasteAmount: isUsingValue?Math.floor(Math.random() * 200 + 100):0, + siteCount: isUsingValue?Math.floor(Math.random() * 20 + 10):0, + })); + + const maxValue = 300; // 固定背景柱的长度 + + const option = { + tooltip: { + trigger: 'axis', + backgroundColor: 'rgba(8, 24, 63, 0.9)', + borderColor: '#13659680', + borderWidth: 1, + textStyle: { + color: '#BCCEE9' + } + }, + grid: { + left: '1%', + right: '3%', + bottom: '3%', + top: '20%', + containLabel: true + }, + xAxis: { + type: 'category', + data: ['锦江区', '青羊区', '金牛区', '武侯区', '成华区', '龙泉驿区', '青白江区', '新都区', '温江区', '双流区', '郫都区', '新津区', '简阳市', '都江堰市', '彭州市', '邛崃市', '崇州市', '金堂县', '大邑县', '蒲江县', '新津县'], + axisLine: { + show: false + }, + // axisLine: { + // lineStyle: { + // color: 'rgba(255, 255, 255, 0.1)' + // } + // }, + axisLabel: { + color: '#E4EDFF', + fontSize: 20, + interval: 0, + } + }, + yAxis: { + type: 'value', + max: maxValue, + nameTextStyle: { + color: '#BCCEE9', + fontSize: 16, + padding: [0, 0, 0, 50] + }, + splitLine: { + show: false + }, + axisLine: { + show: false + }, + axisTick: { + show: false + }, + axisLabel: { + show: true, + color: '#E4EDFF', + fontSize: 16, + // interval: 0, + } + }, + series: [ + { + type: 'bar', + barWidth: 20, + z: 1, + barGap: '-100%', + data: data.map(() => ({ + value: maxValue, + itemStyle: { + color: '#33658D', + // color: 'rgba(57, 122, 183, 0.2)', + borderRadius: [15, 15, 15, 15] + } + })) + }, + { + type: 'bar', + barWidth: 20, + z: 2, + barGap: '-100%', + data: data.map(item => ({ + value: activeTab === '1' ? item.wasteAmount : item.siteCount, + itemStyle: { + color: activeTab === '1' ? 'rgba(89, 238, 255, 0.6)' : '#FFB36B', + borderRadius: [15, 15, 15, 15] + } + })), + label: { + show: true, + position: 'top', + color: '#E4EDFF', + fontSize: 20, + formatter: (params: any) => { + return params.value; + } + } + } + ] + }; + + chart.setOption(option); + + return () => { + chart.dispose(); + }; + }, [activeTab]); + + return ( + <div className={styles.container}> + <Tabs + className={styles.tabs} + activeKey={activeTab} + onChange={setActiveTab} + items={tabItems} + /> + <div className={styles.chartWrapper}> + <div className={styles.yAxisLabel}>单位:{activeTab === '1' ? '万方' : '个'}</div> + <div ref={chartRef} style={{ width: '100%', height: '100%' }} /> + </div> + </div> + ); +}; + +export default DistributionChart; \ No newline at end of file diff --git a/src/pages/GlobalModalServices/modals/ConstructionWaste/components/LicenseInfo/index.css b/src/pages/GlobalModalServices/modals/ConstructionWaste/components/LicenseInfo/index.css new file mode 100644 index 0000000000000000000000000000000000000000..c860234b7bd5cc4751ca0030b5ac0cd4983562a6 --- /dev/null +++ b/src/pages/GlobalModalServices/modals/ConstructionWaste/components/LicenseInfo/index.css @@ -0,0 +1,93 @@ +.container { + width: 2445px; + height: 149px; + background: rgba(57, 122, 183, 0.2); + border-radius: 20px; +} +.container .title { + color: #cbedff; + font-family: 'DingTalk JinBuTi'; + font-size: 22px; + font-weight: 400; + line-height: 26px; + padding: 20px 0 0 24px; +} +.container .content { + padding: 21px 28px; +} +.container .card { + width: 274px; + height: 67px; + background: rgba(57, 122, 183, 0.3); + border-radius: 20px; + display: flex; + align-items: center; + justify-content: center; +} +.container .card .content { + padding: 0; + display: flex; + align-items: baseline; +} +.container .card .content .value { + background: linear-gradient(180deg, #AAFFF6 0%, #25BBFF 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + font-family: 'D-DIN'; + font-size: 36px; + font-weight: 700; + line-height: 1; +} +.container .card .content .unit, +.container .card .content .label { + color: #bccee9; + font-family: '微软雅黑'; + font-size: 20px; + font-weight: 400; + line-height: 26px; +} +.container .vehicleContainer { + width: 858px; + height: 67px; + background: rgba(57, 122, 183, 0.3); + border-radius: 20px; + display: flex; + align-items: center; + justify-content: center; +} +.container .vehicleCard { + display: flex; + align-items: flex-start; + gap: 40px; +} +.container .vehicleCard .section { + display: flex; + flex-direction: column; + gap: 0px; +} +.container .vehicleCard .section .row { + display: flex; + align-items: baseline; + gap: 4px; +} +.container .vehicleCard .section .row .value { + color: #59eeff; + font-family: 'D-DIN'; + font-size: 24px; + font-weight: 700; + line-height: 1; +} +.container .vehicleCard .section .row .unit { + color: #cbedff; + font-family: '思源黑体'; + font-size: 20px; + font-weight: 400; + line-height: 29px; +} +.container .vehicleCard .section .label { + color: #cbedff; + font-family: '思源黑体'; + font-size: 20px; + font-weight: 400; + line-height: 29px; +} diff --git a/src/pages/GlobalModalServices/modals/ConstructionWaste/components/LicenseInfo/index.less b/src/pages/GlobalModalServices/modals/ConstructionWaste/components/LicenseInfo/index.less new file mode 100644 index 0000000000000000000000000000000000000000..b98189d436dddcb09dfe510117bfefcb641e4d6e --- /dev/null +++ b/src/pages/GlobalModalServices/modals/ConstructionWaste/components/LicenseInfo/index.less @@ -0,0 +1,108 @@ +.container { + width: 2445px; + height: 149px; + background: rgba(57, 122, 183, 0.2); + border-radius: 20px; + + .title { + color: rgb(203, 237, 255); + font-family: 'DingTalk JinBuTi'; + font-size: 22px; + font-weight: 400; + line-height: 26px; + padding: 20px 0 0 24px; + } + + .content { + padding: 21px 28px; + } + + // 前5个卡片的样式 + .card { + width: 274px; + height: 67px; + background: rgba(57, 122, 183, 0.3); + border-radius: 20px; + display: flex; + align-items: center; + justify-content: center; + + .content { + padding: 0; + display: flex; + align-items: baseline; + + .value { + background: linear-gradient(180deg, #AAFFF6 0%, #25BBFF 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + font-family: 'D-DIN'; + font-size: 36px; + font-weight: 700; + line-height: 1; + } + + .unit, .label { + color: rgb(188, 206, 233); + font-family: '微软雅黑'; + font-size: 20px; + font-weight: 400; + line-height: 26px; + } + } + } + + // 第6个卡片容器 + .vehicleContainer { + width: 858px; + height: 67px; + background: rgba(57, 122, 183, 0.3); + border-radius: 20px; + display: flex; + align-items: center; + justify-content: center; + } + + // 车辆信息卡片 + .vehicleCard { + display: flex; + align-items: flex-start; + gap: 40px; + + .section { + display: flex; + flex-direction: column; + gap: 0px; + + .row { + display: flex; + align-items: baseline; + gap: 4px; + + .value { + color: rgb(89, 238, 255); + font-family: 'D-DIN'; + font-size: 24px; + font-weight: 700; + line-height: 1; + } + + .unit { + color: rgb(203, 237, 255); + font-family: '思源黑体'; + font-size: 20px; + font-weight: 400; + line-height: 29px; + } + } + + .label { + color: rgb(203, 237, 255); + font-family: '思源黑体'; + font-size: 20px; + font-weight: 400; + line-height: 29px; + } + } + } +} \ No newline at end of file diff --git a/src/pages/GlobalModalServices/modals/ConstructionWaste/components/LicenseInfo/index.tsx b/src/pages/GlobalModalServices/modals/ConstructionWaste/components/LicenseInfo/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..5267b1f6019bd8b8df27d767c0015e789d6be0f9 --- /dev/null +++ b/src/pages/GlobalModalServices/modals/ConstructionWaste/components/LicenseInfo/index.tsx @@ -0,0 +1,104 @@ +import React from 'react'; +import { Space } from 'antd'; +import styles from './index.less'; + +interface LicenseCardProps { + value: number | string; + label: string; + unit?: string; +} + +const LicenseCard: React.FC<LicenseCardProps> = ({ value, label, unit = '件' }) => ( + <div className={styles.card}> + <Space size={4} className={styles.content}> + <span className={styles.label}>{label}</span> + <span className={styles.value}>{value}</span> + <span className={styles.unit}>{unit}</span> + </Space> + </div> +); + +interface VehicleCardProps { + total: number | string; + online: number | string; + label: string; +} + +const VehicleCard: React.FC<VehicleCardProps> = ({ total, online, label }) => ( + <div className={styles.vehicleCard}> + <div className={styles.section}> + <div className={styles.row}> + <span className={styles.value}>{total}</span> + <span className={styles.unit}>辆</span> + </div> + <div className={styles.label}>{label}</div> + </div> + <div className={styles.section}> + <div className={styles.row}> + <span className={styles.value}>{online}</span> + <span className={styles.unit}>%</span> + </div> + <div className={styles.label}>在线率</div> + </div> + </div> +); + +interface LicenseInfoProps { + searchTime: { + startTime: string; + endTime: string; + }; +} + +const LicenseInfo: React.FC<LicenseInfoProps> = ({ searchTime }) => { + let isUsingValue = true; + const cardData = isUsingValue + ? [ + { value: '--', label: '办证总量' }, + { value: '--', label: '排放证办理' }, + { value: '--', label: '消纳证办理' }, + { value: '--', label: '临时消纳备案' }, + { value: '--', label: '临时消纳备案' }, + ] + : [ + { value: 1582, label: '办证总量' }, + { value: 482, label: '排放证办理' }, + { value: 22, label: '消纳证办理' }, + { value: 22, label: '临时消纳备案' }, + { value: 22, label: '临时消纳备案' }, + ]; + + const vehicleData = isUsingValue + ? [ + { total: '--', online: '--', label: '运输车辆' }, + { total: '--', online: '--', label: '新能源车辆' }, + { total: '--', online: '--', label: '燃油车辆' }, + ] + : [ + { total: 1562, online: 98.56, label: '运输车辆' }, + { total: 1562, online: 98.56, label: '新能源车辆' }, + { total: 1562, online: 98.56, label: '燃油车辆' }, + ]; + + return ( + <div className={styles.container}> + <div className={styles.title}>办证总览</div> + <div className={styles.content}> + <Space size={30}> + {cardData.map((item, index) => ( + <LicenseCard key={index} {...item} /> + ))} + <div className={styles.vehicleContainer}> + <Space size={100}> + {vehicleData.map((item, index) => ( + <VehicleCard key={index} {...item} /> + ))} + </Space> + </div> + </Space> + </div> + </div> + ); +}; + +export default LicenseInfo; \ No newline at end of file diff --git a/src/pages/GlobalModalServices/modals/ConstructionWaste/components/RecyclingInfo/index.css b/src/pages/GlobalModalServices/modals/ConstructionWaste/components/RecyclingInfo/index.css new file mode 100644 index 0000000000000000000000000000000000000000..67c33540e7e49c62a0c7a6299ec9d90a476687d3 --- /dev/null +++ b/src/pages/GlobalModalServices/modals/ConstructionWaste/components/RecyclingInfo/index.css @@ -0,0 +1,62 @@ +.container { + width: 863px; + display: flex; + flex-direction: column; + gap: 16px; +} +.container .topSection { + height: 162px; + background: rgba(57, 122, 183, 0.2); + border-radius: 20px; +} +.container .bottomSection { + height: 163px; + background: rgba(57, 122, 183, 0.2); + border-radius: 20px; +} +.container .title { + color: #cbedff; + font-family: 'DingTalk JinBuTi'; + font-size: 22px; + font-weight: 400; + line-height: 26px; + padding: 20px 0 0 24px; +} +.container .content { + padding: 21px 28px; + display: flex; + gap: 37px; +} +.container .content1 { + padding: 21px 28px; + display: flex; + gap: 157px; +} +.container .infoItem .valueWrapper { + display: flex; + align-items: baseline; + gap: 4px; +} +.container .infoItem .valueWrapper .value { + background: linear-gradient(180deg, #AAFFF6 0%, #25BBFF 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + font-family: 'D-DIN'; + font-size: 36px; + font-weight: 700; + line-height: 1; +} +.container .infoItem .valueWrapper .unit { + color: #bccee9; + font-family: '微软雅黑'; + font-size: 20px; + font-weight: 400; +} +.container .infoItem .label { + color: #bccee9; + font-family: '微软雅黑'; + font-size: 20px; + font-weight: 400; + line-height: 26px; + margin-top: 15px; +} diff --git a/src/pages/GlobalModalServices/modals/ConstructionWaste/components/RecyclingInfo/index.less b/src/pages/GlobalModalServices/modals/ConstructionWaste/components/RecyclingInfo/index.less new file mode 100644 index 0000000000000000000000000000000000000000..ea65f017d3eda9807bacf2fe23b59f7950086251 --- /dev/null +++ b/src/pages/GlobalModalServices/modals/ConstructionWaste/components/RecyclingInfo/index.less @@ -0,0 +1,73 @@ +.container { + width: 863px; + display: flex; + flex-direction: column; + gap: 16px; + + .topSection { + height: 162px; + background: rgba(57, 122, 183, 0.2); + border-radius: 20px; + } + + .bottomSection { + height: 163px; + background: rgba(57, 122, 183, 0.2); + border-radius: 20px; + } + + .title { + color: rgb(203, 237, 255); + font-family: 'DingTalk JinBuTi'; + font-size: 22px; + font-weight: 400; + line-height: 26px; + padding: 20px 0 0 24px; + } + + .content { + padding: 21px 28px; + display: flex; + gap: 37px; + } + + .content1 { + padding: 21px 28px; + display: flex; + gap: 157px; + } + + .infoItem { + .valueWrapper { + display: flex; + align-items: baseline; + gap: 4px; + + .value { + background: linear-gradient(180deg, #AAFFF6 0%, #25BBFF 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + font-family: 'D-DIN'; + font-size: 36px; + font-weight: 700; + line-height: 1; + } + + .unit { + color: rgb(188, 206, 233); + font-family: '微软雅黑'; + font-size: 20px; + font-weight: 400; + } + } + + .label { + color: rgb(188, 206, 233); + font-family: '微软雅黑'; + font-size: 20px; + font-weight: 400; + line-height: 26px; + margin-top: 15px; + } + } +} \ No newline at end of file diff --git a/src/pages/GlobalModalServices/modals/ConstructionWaste/components/RecyclingInfo/index.tsx b/src/pages/GlobalModalServices/modals/ConstructionWaste/components/RecyclingInfo/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..565dd30d1a7e604a9f22917764d5536f6e460b0d --- /dev/null +++ b/src/pages/GlobalModalServices/modals/ConstructionWaste/components/RecyclingInfo/index.tsx @@ -0,0 +1,88 @@ +import React from 'react'; +import styles from './index.less'; + +interface InfoItemProps { + value: string | number; + label: string; + unit: string; +} + +let isUsingValue = false; +const showValue = (value: number | string) => { + if(isUsingValue){ + return value; + } + return '--'; +} +const InfoItem: React.FC<InfoItemProps> = ({ value, label, unit }) => ( + <div className={styles.infoItem}> + <div className={styles.valueWrapper}> + <span className={styles.value}>{showValue(value)}</span> + <span className={styles.unit}>{unit}</span> + </div> + <div className={styles.label}>{label}</div> + </div> +); + +interface RecyclingInfoProps { + searchTime: { + startTime: string; + endTime: string; + }; +} + +const RecyclingInfo: React.FC<RecyclingInfoProps> = ({ searchTime }) => { + const topData = [ + { + value: 12, + label: '固定式建筑垃圾资源化利用厂', + unit: '个' + }, + { + value: 12, + label: '临时性建筑垃圾资源化利用厂', + unit: '个' + }, + { + value: 1200, + label: '处置能力', + unit: '万吨/年' + } + ]; + + const bottomData = [ + { + value: 112, + label: '综合利用点数量', + unit: '个' + }, + { + value: 12, + label: '综合利用处置量', + unit: '万方' + } + ]; + + return ( + <div className={styles.container}> + <div className={styles.topSection}> + <div className={styles.title}>资源化利用厂概况</div> + <div className={styles.content}> + {topData.map((item, index) => ( + <InfoItem key={index} {...item} /> + ))} + </div> + </div> + <div className={styles.bottomSection}> + <div className={styles.title}>综合利用点概况</div> + <div className={styles.content1}> + {bottomData.map((item, index) => ( + <InfoItem key={index} {...item} /> + ))} + </div> + </div> + </div> + ); +}; + +export default RecyclingInfo; \ No newline at end of file diff --git a/src/pages/GlobalModalServices/modals/ConstructionWaste/components/StatisticsChart/index.css b/src/pages/GlobalModalServices/modals/ConstructionWaste/components/StatisticsChart/index.css new file mode 100644 index 0000000000000000000000000000000000000000..c5c53e2d63bf9b7e6dbd344d332cda4165ad3a01 --- /dev/null +++ b/src/pages/GlobalModalServices/modals/ConstructionWaste/components/StatisticsChart/index.css @@ -0,0 +1,76 @@ +.container { + width: 1023px; + height: 345px; + background: rgba(57, 122, 183, 0.2); + border-radius: 20px; +} +.container .title { + color: #cbedff; + font-family: 'DingTalk JinBuTi'; + font-size: 22px; + font-weight: 400; + line-height: 26px; + padding: 20px 0 0 24px; +} +.container .content { + display: flex; + height: calc(100% - 66px); +} +.container .content .chart { + padding: 56px 28px 0 35px; +} +.container .content .legend { + display: flex; + gap: 15px; + margin-left: -48px; + padding-top: 59px; +} +.container .content .legend .legendColumn { + display: flex; + flex-direction: column; + gap: 19px; +} +.container .content .legend .legendColumn .legendItem { + width: 331px; + height: 38px; + background: rgba(41, 181, 255, 0.12); + border-radius: 7px; + display: flex; + align-items: center; + padding: 0 12px; +} +.container .content .legend .legendColumn .legendItem .dot { + width: 8px; + height: 8px; + border-radius: 50%; + margin-right: 8px; +} +.container .content .legend .legendColumn .legendItem .info { + flex: 1; + display: flex; + align-items: center; + justify-content: space-between; +} +.container .content .legend .legendColumn .legendItem .info .type { + color: #BCCEE9; + font-family: '思源黑体'; + font-size: 16px; + min-width: 80px; +} +.container .content .legend .legendColumn .legendItem .info .value { + color: #FFFFFF; + font-family: 'D-DIN'; + font-size: 16px; + margin: 0 10px; +} +.container .content .legend .legendColumn .legendItem .info .value .unit { + color: #BCCEE9; + font-family: '思源黑体'; + margin-left: 4px; +} +.container .content .legend .legendColumn .legendItem .info .percentage { + color: #BCCEE9; + font-size: 16px; + min-width: 60px; + text-align: right; +} diff --git a/src/pages/GlobalModalServices/modals/ConstructionWaste/components/StatisticsChart/index.less b/src/pages/GlobalModalServices/modals/ConstructionWaste/components/StatisticsChart/index.less new file mode 100644 index 0000000000000000000000000000000000000000..8a181c778ad5ba963fce573656123d7f8d17aa9e --- /dev/null +++ b/src/pages/GlobalModalServices/modals/ConstructionWaste/components/StatisticsChart/index.less @@ -0,0 +1,91 @@ +.container { + width: 1023px; + height: 345px; + background: rgba(57, 122, 183, 0.2); + border-radius: 20px; + + .title { + color: rgb(203, 237, 255); + font-family: 'DingTalk JinBuTi'; + font-size: 22px; + font-weight: 400; + line-height: 26px; + padding: 20px 0 0 24px; + } + + .content { + display: flex; + // padding: 20px; + height: calc(100% - 66px); + + .chart { + padding: 56px 28px 0 35px; + } + + .legend { + // width: 50%; + display: flex; + gap: 15px; + // padding-left: -28px; + margin-left: -48px; + padding-top: 59px; + + .legendColumn { + display: flex; + flex-direction: column; + gap: 19px; + + .legendItem { + width: 331px; + height: 38px; + background: rgba(41, 181, 255, 0.12); + border-radius: 7px; + display: flex; + align-items: center; + padding: 0 12px; + + .dot { + width: 8px; + height: 8px; + border-radius: 50%; + margin-right: 8px; + } + + .info { + flex: 1; + display: flex; + align-items: center; + justify-content: space-between; + + .type { + color: #BCCEE9; + font-family: '思源黑体'; + font-size: 16px; + min-width: 80px; + } + + .value { + color: #FFFFFF; + font-family: 'D-DIN'; + font-size: 16px; + margin: 0 10px; + + .unit { + color: #BCCEE9; + font-family: '思源黑体'; + margin-left: 4px; + } + } + + .percentage { + color: #BCCEE9; + font-size: 16px; + min-width: 60px; + text-align: right; + } + } + } + } + } + } +} \ No newline at end of file diff --git a/src/pages/GlobalModalServices/modals/ConstructionWaste/components/StatisticsChart/index.tsx b/src/pages/GlobalModalServices/modals/ConstructionWaste/components/StatisticsChart/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..beac0539acff52ec90f90e6ea0af5f22014d775a --- /dev/null +++ b/src/pages/GlobalModalServices/modals/ConstructionWaste/components/StatisticsChart/index.tsx @@ -0,0 +1,132 @@ +import React, { useEffect, useRef } from 'react'; +import * as echarts from 'echarts'; +import styles from './index.less'; + +interface StatisticsChartProps { + searchTime: { + startTime: string; + endTime: string; + }; +} + +const StatisticsChart: React.FC<StatisticsChartProps> = ({ searchTime }) => { + const chartRef = useRef<HTMLDivElement>(null); + let isUsingValue = false; + const data = [ + { name: '工程渣土', value: 16.23, percentage: 56.25, color: '#FF9B5D' }, + { name: '工程泥浆', value: 16.23, percentage: 56.25, color: '#FFE335' }, + { name: '装修垃圾', value: 16.23, percentage: 56.25, color: '#35B2FF' }, + { name: '工程垃圾', value: 16.23, percentage: 56.25, color: '#77E67B' }, + { name: '拆除垃圾', value: 16.23, percentage: 56.25, color: '#00FFB3' } + ]; + + const showValue = (value: number | string) => { + if(isUsingValue){ + return value; + } + return '--'; + } + + useEffect(() => { + if (!chartRef.current) return; + + const chart = echarts.init(chartRef.current); + + const option = { + tooltip: { + trigger: 'item', + backgroundColor: 'rgba(8, 24, 63, 0.9)', + borderColor: '#13659680', + borderWidth: 1, + textStyle: { + color: '#BCCEE9' + } + }, + title: { + text: isUsingValue ? '5623.85' : '---.--', + subtext: '共计(万方)', + left: '65px', // 根据需求调整位置 + top: '54px', // 根据需求调整位置 + textStyle: { + color: '#FFFFFF', + fontSize: 24, + fontFamily: 'D-DIN', + lineHeight: 31 + }, + subtextStyle: { + color: '#BCCEE9', + fontSize: 16, + lineHeight: 23 + } + }, + series: [ + { + type: 'pie', + radius: ['50%', '70%'], + center: ['40%', '35%'], // 调整环形图位置 + data: data.map(item => ({ + name: item.name, + value: item.value, + itemStyle: { + color: item.color + } + })), + label: { + show: false + } + } + ] + }; + + chart.setOption(option); + + return () => { + chart.dispose(); + }; + }, []); + + return ( + <div className={styles.container}> + <div className={styles.title}>建筑垃圾申报排放统计</div> + <div className={styles.content}> + <div className={styles.chart}> + <div ref={chartRef} style={{ width: '270px', height: '270px' }} /> + </div> + <div className={styles.legend}> + <div className={styles.legendColumn}> + {data.slice(0, 3).map((item, index) => ( + <div key={index} className={styles.legendItem}> + <div className={styles.dot} style={{ background: item.color }} /> + <div className={styles.info}> + <div className={styles.type}>{item.name}</div> + <div className={styles.value}> + {showValue(item.value)} + <span className={styles.unit}>万方</span> + </div> + <div className={styles.percentage}>{showValue(item.percentage)}%</div> + </div> + </div> + ))} + </div> + <div className={styles.legendColumn}> + {data.slice(3).map((item, index) => ( + <div key={index} className={styles.legendItem}> + <div className={styles.dot} style={{ background: item.color }} /> + <div className={styles.info}> + <div className={styles.type}>{item.name}</div> + <div className={styles.value}> + {showValue(item.value)} + <span className={styles.unit}>万方</span> + </div> + <div className={styles.percentage}>{showValue(item.percentage)}%</div> + </div> + </div> + ))} + </div> + </div> + </div> + </div> + ); +}; + +export default StatisticsChart; \ No newline at end of file diff --git a/src/pages/GlobalModalServices/modals/ConstructionWaste/index.css b/src/pages/GlobalModalServices/modals/ConstructionWaste/index.css new file mode 100644 index 0000000000000000000000000000000000000000..171fb68b3777ee75bcadd3baa481ffaa63f5487e --- /dev/null +++ b/src/pages/GlobalModalServices/modals/ConstructionWaste/index.css @@ -0,0 +1,85 @@ +.modal :global .ant-modal-content { + padding: 0; +} +.modal :global .ant-modal-header { + margin-bottom: 0; +} +.headerWrapper { + display: flex; + align-items: center; + padding: 12px 19px; + line-height: normal; +} +.headerWrapper .title { + background: linear-gradient(180deg, #FFFFFF 0%, #B5E5FF 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + font-family: 'DingTalk JinBuTi'; + font-size: 30px; + font-weight: 400; + line-height: 36px; + white-space: nowrap; +} +.headerWrapper .headerLeft { + display: flex; + align-items: center; + margin-left: 30px; +} +.headerWrapper .headerLeft :global .ant-picker { + background: transparent; + width: 280px; + padding: 4px 11px; +} +.headerWrapper .headerLeft :global .ant-picker:hover { + background: rgba(255, 255, 255, 0.1); +} +.headerWrapper .headerLeft :global .ant-picker .ant-picker-input input { + color: #BCCEE9; + font-family: '微软雅黑'; + font-size: 18px; + text-align: center; +} +.headerWrapper .headerLeft :global .ant-picker .ant-picker-input input::placeholder { + color: #BCCEE9; + opacity: 1; +} +.headerWrapper .headerLeft :global .ant-picker .ant-picker-range-separator { + color: #BCCEE9; +} +.headerWrapper .headerLeft :global .ant-picker .ant-picker-suffix { + color: #BCCEE9; +} +.dateRangePicker :global .ant-picker-panel-container { + background: rgba(8, 24, 63, 0.9); + border: 1px solid rgba(19, 101, 150, 0.5); +} +.dateRangePicker :global .ant-picker-cell { + color: #BCCEE9; +} +.dateRangePicker :global .ant-picker-cell-in-view { + color: #fff; +} +.dateRangePicker :global .ant-picker-header { + border-bottom: 1px solid rgba(255, 255, 255, 0.1); +} +.dateRangePicker :global .ant-picker-header button { + color: #BCCEE9; +} +.dateRangePicker :global .ant-picker-header-view { + color: #BCCEE9; +} +.container { + padding: 0px 0px 30px; +} +.container .topWrap { + margin-bottom: 20px; +} +.container .content { + display: flex; + flex-direction: column; + gap: 20px; +} +.container .content .bottomSection { + display: flex; + gap: 20px 23px; +} diff --git a/src/pages/GlobalModalServices/modals/ConstructionWaste/index.less b/src/pages/GlobalModalServices/modals/ConstructionWaste/index.less new file mode 100644 index 0000000000000000000000000000000000000000..429a7d6d3352abc58e857104fbf98ab12e13a321 --- /dev/null +++ b/src/pages/GlobalModalServices/modals/ConstructionWaste/index.less @@ -0,0 +1,116 @@ +.modal { + :global { + .ant-modal-content { + padding: 0; + } + .ant-modal-header { + margin-bottom: 0; + } + } +} + +.headerWrapper { + display: flex; + align-items: center; + padding: 12px 19px; + line-height: normal; + + .title { + background: linear-gradient(180deg, #FFFFFF 0%, #B5E5FF 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + font-family: 'DingTalk JinBuTi'; + font-size: 30px; + font-weight: 400; + line-height: 36px; + white-space: nowrap; + } + + .headerLeft { + display: flex; + align-items: center; + margin-left: 30px; + + :global { + .ant-picker { + background: transparent; + width: 280px; + padding: 4px 11px; + + &:hover { + background: rgba(255, 255, 255, 0.1); + } + + .ant-picker-input { + input { + color: #BCCEE9; + font-family: '微软雅黑'; + font-size: 18px; + text-align: center; + + &::placeholder { + color: #BCCEE9; + opacity: 1; + } + } + } + + .ant-picker-range-separator { + color: #BCCEE9; + } + + .ant-picker-suffix { + color: #BCCEE9; + } + } + } + } +} + +.dateRangePicker { + :global { + .ant-picker-panel-container { + background: rgba(8, 24, 63, 0.9); + border: 1px solid rgba(19, 101, 150, 0.5); + } + + .ant-picker-cell { + color: #BCCEE9; + } + + .ant-picker-cell-in-view { + color: #fff; + } + + .ant-picker-header { + border-bottom: 1px solid rgba(255, 255, 255, 0.1); + + button { + color: #BCCEE9; + } + } + + .ant-picker-header-view { + color: #BCCEE9; + } + } +} + +.container { + padding: 0px 0px 30px; + + .topWrap { + margin-bottom: 20px; + } + + .content { + display: flex; + flex-direction: column; + gap: 20px; + + .bottomSection { + display: flex; + gap: 20px 23px; + } + } +} \ No newline at end of file diff --git a/src/pages/GlobalModalServices/modals/ConstructionWaste/index.tsx b/src/pages/GlobalModalServices/modals/ConstructionWaste/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..2f10b80e401c4a8f7d05287179f5e88ffd5ef63c --- /dev/null +++ b/src/pages/GlobalModalServices/modals/ConstructionWaste/index.tsx @@ -0,0 +1,63 @@ +import React, { useEffect, useState } from 'react'; +import dayjs from 'dayjs'; +import { DatePicker } from 'antd'; +import { DownOutlined } from '@ant-design/icons'; +import styles from './index.less'; +import LicenseInfo from './components/LicenseInfo'; +import DistributionChart from './components/DistributionChart'; +import StatisticsChart from './components/StatisticsChart'; +import DisposalSiteInfo from './components/DisposalSiteInfo'; +import RecyclingInfo from './components/RecyclingInfo'; + +const { RangePicker } = DatePicker; + +const ConstructionWaste = (props: any) => { + const [searchTime, setSearchTime] = useState({ + startTime: dayjs().startOf('month').format('YYYY-MM-DD'), + endTime: dayjs().endOf('month').format('YYYY-MM-DD'), + }); + + useEffect(() => { + props.modalDispatch.setOptions({ + headerLeft: ( + <div className={styles.headerLeft}> + <RangePicker + // value={[dayjs(searchTime.startTime), dayjs(searchTime.endTime)]} + onChange={(dates) => { + if (dates) { + setSearchTime({ + startTime: dates[0]?.format('YYYY-MM-DD') || '', + endTime: dates[1]?.format('YYYY-MM-DD') || '', + }); + } + }} + suffixIcon={<DownOutlined />} + separator="-" + format="YYYY-MM-DD" + allowClear={false} + placeholder={['开始时间', '结束时间']} + variant="borderless" + popupClassName={styles.dateRangePicker} + getPopupContainer={trigger => trigger.parentElement || document.body} + /> + </div> + ), + }); + }, [searchTime]); + + return ( + <div className={styles.container}> + <div className={styles.content}> + <LicenseInfo searchTime={searchTime} /> + <DistributionChart searchTime={searchTime} /> + <div className={styles.bottomSection}> + <StatisticsChart searchTime={searchTime} /> + <DisposalSiteInfo searchTime={searchTime} /> + <RecyclingInfo searchTime={searchTime} /> + </div> + </div> + </div> + ); +}; + +export default ConstructionWaste; \ No newline at end of file diff --git a/src/pages/GlobalModalServices/modals/PipelinePassage/Overview/index.less b/src/pages/GlobalModalServices/modals/PipelinePassage/Overview/index.less index dc376c8bba77da69d115eb3e44e6c22b3281601b..da0ab7770bf69b3ecb81c12c6cc1bbf1895e9700 100644 --- a/src/pages/GlobalModalServices/modals/PipelinePassage/Overview/index.less +++ b/src/pages/GlobalModalServices/modals/PipelinePassage/Overview/index.less @@ -1,5 +1,3 @@ -.container { -} .tabItem { color: rgb(76, 134, 189); font-family: DingTalk JinBuTi; @@ -13,3 +11,23 @@ font-weight: 400; } + +.container { + margin-top: 10px; +} + +.legendBg { + width: 244px; + height: 67px; + padding: 8px 14px; + border-radius: 7px; + background: rgba(41, 181, 255, 0.12); +} + +.legendContent { + display: flex; + flex-direction: row; + flex-wrap: wrap; + row-gap: 5px; + column-gap: 16px; +} diff --git a/src/pages/GlobalModalServices/modals/PipelinePassage/Overview/index.tsx b/src/pages/GlobalModalServices/modals/PipelinePassage/Overview/index.tsx index 0a6cad4fee9f4b7d87060bfc4290e8d3e812b95a..fc7552c95cda1a9c05805f7bcd684a0b7cea5216 100644 --- a/src/pages/GlobalModalServices/modals/PipelinePassage/Overview/index.tsx +++ b/src/pages/GlobalModalServices/modals/PipelinePassage/Overview/index.tsx @@ -1,16 +1,37 @@ import DescriptionItem from '@/components/DescriptionItem'; -import { Flex } from 'antd'; +import { Badge, Flex } from 'antd'; import classNames from 'classnames'; import EChartsReact from 'echarts-for-react'; import { cloneDeep } from 'lodash'; import React, { memo, useLayoutEffect, useMemo, useRef, useState } from 'react'; import BaseCard from '../components/BaseCard'; import styles from './index.less'; -import option from './option'; +import option, { pieOption } from './option'; /** @name 全市已移交纳入管理综合管廊概况 */ const Overview: React.FC = memo(() => { - const [activeTab, setActiveTab] = useState('urbanManagement'); + const [activeTab, setActiveTab] = useState('1'); + + const [pieData, setPieData] = useState( + [...Array(4)].map((_, i) => { + return { + value: Math.floor(Math.random() * 100), + name: '给水(输水)管道' + i, + }; + }), + ); const chartRef = useRef<any>(); + + const colors = [ + '#5DDDFF', + '#A550FF', + '#F07283', + '#7664EC', + '#77E67B', + '#35B2FF', + '#FFE335', + '#FF9B5D', + ]; + const INFO = useMemo(() => { return [ { @@ -34,12 +55,12 @@ const Overview: React.FC = memo(() => { const tabItems = useMemo( () => [ { - key: 'urbanManagement', - label: '运行态势', + key: '1', + label: '管廊区域分布', }, { - key: 'complaints', - label: '老百姓投诉情况', + key: '2', + label: '管廊类型分布', }, ], [], @@ -65,6 +86,14 @@ const Overview: React.FC = memo(() => { temp.series[0].data = yAxis; return temp; }, []); + + const PieOption = useMemo(() => { + const temp = cloneDeep(pieOption) as any; + temp.color = colors; + temp.series[0].data = pieData; + return temp; + }, []); + return ( <BaseCard w={902} h={394} title="全市已移交纳入管理综合管廊概况"> <Flex gap={100} style={{ marginTop: 20 }} align="center"> @@ -98,16 +127,50 @@ const Overview: React.FC = memo(() => { })} </Flex> - <div> - <div style={{ margin: '10px 0' }}>单位:km</div> - <EChartsReact - ref={chartRef} - style={{ - height: 130, - }} - option={BarOption} - ></EChartsReact> - </div> + {activeTab === '1' ? ( + <div> + <div style={{ margin: '10px 0' }}>单位:km</div> + <EChartsReact + ref={chartRef} + style={{ + height: 130, + }} + option={BarOption} + ></EChartsReact> + </div> + ) : ( + <Flex align="center" gap={60} className={styles.container}> + <div + style={{ + height: 130, + width: 130, + }} + > + <EChartsReact + ref={chartRef} + style={{ + height: 130, + width: 130, + }} + option={PieOption} + ></EChartsReact> + </div> + + <div className={styles.legendContent}> + {pieData.map((item, index) => { + return ( + <Flex key={index} className={styles.legendBg} gap={14}> + <Badge color={colors[index % colors.length]} /> + <div> + <div>{item.name}</div> + <div>{item.value} 条</div> + </div> + </Flex> + ); + })} + </div> + </Flex> + )} </BaseCard> ); }); diff --git a/src/pages/GlobalModalServices/modals/PipelinePassage/Overview/option.ts b/src/pages/GlobalModalServices/modals/PipelinePassage/Overview/option.ts index de188fc95b5e51b92c31b3aa224a00015393cf64..7f8f9c6af54331087f773ac528c19ad69de16121 100644 --- a/src/pages/GlobalModalServices/modals/PipelinePassage/Overview/option.ts +++ b/src/pages/GlobalModalServices/modals/PipelinePassage/Overview/option.ts @@ -16,16 +16,7 @@ const option = { top: '20%', containLabel: true, }, - legend: { - data: ['投诉量'], - icon: 'circle', - top: 10, - itemGap: 50, - textStyle: { - fontSize: '16px', - color: '#E4EDFF', - }, - }, + xAxis: [ { type: 'category', @@ -116,4 +107,33 @@ const option = { ], }; +export const pieOption = { + series: [ + { + name: 'Access From', + type: 'pie', + radius: ['70%', '90%'], + center: ['50%', '50%'], + avoidLabelOverlap: false, + padAngle: 5, + itemStyle: {}, + label: { + show: false, + position: 'center', + }, + emphasis: { + label: { + show: true, + fontSize: 10, + fontWeight: 'bold', + }, + }, + labelLine: { + show: false, + }, + data: [], + }, + ], +}; + export default option; diff --git a/src/pages/GlobalModalServices/modals/PipelinePassage/PipeCorridorSensesTheSituation/index.less b/src/pages/GlobalModalServices/modals/PipelinePassage/PipeCorridorSensesTheSituation/index.less index 485140808b9438d70cc409d91ba4a8d0fe090cde..eba1ef8dc19e0d840d3187ba61c209d2c2e09d5a 100644 --- a/src/pages/GlobalModalServices/modals/PipelinePassage/PipeCorridorSensesTheSituation/index.less +++ b/src/pages/GlobalModalServices/modals/PipelinePassage/PipeCorridorSensesTheSituation/index.less @@ -1,2 +1,18 @@ -.container { +.chartTitle { + margin: 12px 0px; + color: rgb(203, 237, 255); + font-size: 18px; +} +.tabItem { + color: rgb(76, 134, 189); + font-family: DingTalk JinBuTi; + font-size: 18px; + font-weight: 400; + cursor: pointer; +} + +.active { + color: rgb(255, 255, 255); + + font-weight: 400; } diff --git a/src/pages/GlobalModalServices/modals/PipelinePassage/PipeCorridorSensesTheSituation/index.tsx b/src/pages/GlobalModalServices/modals/PipelinePassage/PipeCorridorSensesTheSituation/index.tsx index 39a7bec72e70c7af53139a5338d8e71f7db5d3af..775492c4402f422b3a0f03de1d7848dab41eb60c 100644 --- a/src/pages/GlobalModalServices/modals/PipelinePassage/PipeCorridorSensesTheSituation/index.tsx +++ b/src/pages/GlobalModalServices/modals/PipelinePassage/PipeCorridorSensesTheSituation/index.tsx @@ -1,9 +1,142 @@ -import React from 'react'; +import DescriptionItem from '@/components/DescriptionItem'; +import { Flex } from 'antd'; +import classNames from 'classnames'; +import EChartsReact from 'echarts-for-react'; +import { cloneDeep } from 'lodash'; +import React, { useLayoutEffect, useMemo, useRef, useState } from 'react'; import BaseCard from '../components/BaseCard'; +import styles from './index.less'; +import option from './option'; /** @name 管廊感知态势 */ const PipeCorridorSensesTheSituation: React.FC = () => { - return <BaseCard w={917} h={357} title="管廊感知态势 "></BaseCard>; + const chartRef = useRef<any>(); + const [activeTab, setActiveTab] = useState('1'); + + const tabItems = useMemo( + () => [ + { + key: '1', + label: '各类型设备在线率', + }, + { + key: '2', + label: '各类型设备预警数', + }, + ], + [], + ); + + const INFO = useMemo(() => { + return [ + { + name: '已接入感知设备', + value: 82, + unit: '个', + }, + { + name: '在线', + value: 42, + unit: '个', + }, + { + name: '设备在线率', + value: 40, + unit: '%', + vColor: '#55D355', + }, + ]; + }, []); + + useLayoutEffect(() => { + chartRef.current?.resize(); + }, []); + + const BarOption = useMemo(() => { + const temp = cloneDeep(option) as any; + const xAxis = [ + '液位监测传感器', + '湿度传感器', + '温度传感器', + '硫化氢气体传感器', + '甲坑气体传盛器', + '一氧化碳气体传感器', + '氧气浓度传感器', + ]; + + const yAxis = [1652, 1652, 1652, 1652, 1652, 1652, 1652]; + temp.xAxis[0].data = xAxis; + temp.series[0].data = yAxis; + if (activeTab === '1') { + temp.series[0].itemStyle.color = { + type: 'linear', + x: 0, + y: 0, + x2: 0, + y2: 1, + colorStops: [ + { + offset: 0, + color: '#76FDD2', // 0% 处的颜色 + }, + { + offset: 1, + color: '#02BAFE', // 100% 处的颜色 + }, + ], + global: false, // 缺省为 false + }; + } + return temp; + }, [activeTab]); + + return ( + <BaseCard w={917} h={357} title="管廊感知态势 "> + <Flex gap={100} style={{ marginTop: 20 }} align="center"> + {INFO.map((item) => { + return ( + <DescriptionItem + value={item.value} + direction="horizontal" + unit={item.unit} + valueStyle={{ + margin: '0 12px', + color: item.vColor, + }} + name={item.name} + key={item.name} + /> + ); + })} + </Flex> + <div> + <Flex gap={36} style={{ marginTop: 20 }}> + {tabItems.map((item, index) => { + return ( + <div + key={index} + onClick={() => { + setActiveTab(item.key); + }} + className={classNames(styles.tabItem, { + [styles.active]: activeTab === item.key, + })} + > + {item.label} + </div> + ); + })} + </Flex> + <EChartsReact + ref={chartRef} + style={{ + height: 150, + }} + option={BarOption} + ></EChartsReact> + </div> + </BaseCard> + ); }; export default PipeCorridorSensesTheSituation; diff --git a/src/pages/GlobalModalServices/modals/PipelinePassage/PipeCorridorSensesTheSituation/option.ts b/src/pages/GlobalModalServices/modals/PipelinePassage/PipeCorridorSensesTheSituation/option.ts new file mode 100644 index 0000000000000000000000000000000000000000..5138d457ded7aab871027a4f39b6eb596c8c01bd --- /dev/null +++ b/src/pages/GlobalModalServices/modals/PipelinePassage/PipeCorridorSensesTheSituation/option.ts @@ -0,0 +1,110 @@ +const option = { + color: ['#5F8BFF'], + tooltip: { + trigger: 'axis', + borderWidth: '0', + backgroundColor: 'rgba(73,81,92,.95)', + textStyle: { + color: '#fff', + fontSize: 16, + }, + }, + grid: { + left: '0', + right: '0', + bottom: '2%', + top: '20%', + containLabel: true, + }, + + xAxis: [ + { + type: 'category', + boundaryGap: true, + axisLine: { + show: false, + }, + axisLabel: { + show: true, + interval: 0, + textStyle: { + padding: [2, 0, 0, 0], + color: '#CBEDFF', + fontSize: 14, + }, + }, + axisTick: { + show: false, + }, + axisPointer: { + type: 'shadow', + }, + data: [], + }, + ], + yAxis: [ + { + type: 'value', + name: '件', + min: 0, + interval: 10, + axisLabel: { + show: false, + }, + nameTextStyle: { + align: 'left', + color: '#CBEDFF', + padding: [0, 0, 20, -20], + fontSize: 16, + }, + splitLine: { + show: false, + }, + axisLine: { + show: false, + }, + axisTick: { + show: false, + }, + }, + ], + series: [ + { + // name: '投诉量', + type: 'bar', + barWidth: 20, + data: [], + itemStyle: { + borderRadius: 20, + color: { + type: 'linear', + x: 0, + y: 0, + x2: 0, + y2: 1, + colorStops: [ + { + offset: 0, + color: 'rgb(253, 239, 111)', // 0% 处的颜色 + }, + { + offset: 1, + color: 'rgb(254, 173, 11)', // 100% 处的颜色 + }, + ], + global: false, // 缺省为 false + }, + }, + label: { + show: true, + position: 'top', + distance: 6, + color: '#FFFFFF', + fontSize: 20, + fontWeight: 700, + }, + }, + ], +}; + +export default option; diff --git a/src/pages/GlobalModalServices/modals/PipelinePassage/PipeGalleryMaintenanceStatus/index.less b/src/pages/GlobalModalServices/modals/PipelinePassage/PipeGalleryMaintenanceStatus/index.less index 485140808b9438d70cc409d91ba4a8d0fe090cde..1291f5f9a880a8edb1c836ce33011ddf351547ba 100644 --- a/src/pages/GlobalModalServices/modals/PipelinePassage/PipeGalleryMaintenanceStatus/index.less +++ b/src/pages/GlobalModalServices/modals/PipelinePassage/PipeGalleryMaintenanceStatus/index.less @@ -1,2 +1,7 @@ .container { } + +.time { + color: rgb(203, 237, 255); + font-size: 16px; +} diff --git a/src/pages/GlobalModalServices/modals/PipelinePassage/PipeGalleryMaintenanceStatus/index.tsx b/src/pages/GlobalModalServices/modals/PipelinePassage/PipeGalleryMaintenanceStatus/index.tsx index 88af4a13bddd842945ba09a9af97b0275ef7d4be..ad087729cd47171c38da10a7645af83bba5e66d2 100644 --- a/src/pages/GlobalModalServices/modals/PipelinePassage/PipeGalleryMaintenanceStatus/index.tsx +++ b/src/pages/GlobalModalServices/modals/PipelinePassage/PipeGalleryMaintenanceStatus/index.tsx @@ -1,15 +1,118 @@ -import React from 'react'; +import DescriptionItem from '@/components/DescriptionItem'; +import { Flex } from 'antd'; +import EChartsReact from 'echarts-for-react'; +import { cloneDeep } from 'lodash'; +import React, { useLayoutEffect, useMemo, useRef } from 'react'; import BaseCard from '../components/BaseCard'; +import styles from './index.less'; +import option from './option'; + /** @name 管廊维护情况 */ const PipeGalleryMaintenanceStatus: React.FC = () => { + const chartRef = useRef<any>(); + + const INFO = useMemo(() => { + return [ + { + name: '本体维护保养', + value: 82, + unit: '处', + }, + { + name: '附属设施维护保养', + value: 82, + unit: '个', + vColor: '#FFB05A', + }, + ]; + }, []); + + useLayoutEffect(() => { + chartRef.current?.resize(); + }, []); + + const LineOption = useMemo(() => { + const temp = cloneDeep(option) as any; + const xAxis = [ + '2024年7月', + '2024年8月', + '2024年9月', + '2024年10月', + '2024年11月', + '2024年12月', + ]; + const yAxis = [1652, 1652, 1652, 1652, 1652, 1652, 1652]; + temp.xAxis[0].data = xAxis; + + const lineSeries = [ + { + name: '本体维护保养', + type: 'line', + symbol: 'none', + stack: 'Total', + lineStyle: { + color: '#57efe5', + width: 3, + }, + smooth: true, + data: [120, 132, 101, 134, 90, 230, 210], + }, + { + name: '附属设施维护保养', + type: 'line', + stack: 'Total', + lineStyle: { + color: '#FFB05A', + width: 3, + }, + smooth: true, + + symbol: 'none', + data: [220, 182, 191, 234, 290, 330, 310], + }, + ]; + temp.series = lineSeries; + return temp; + }, []); + return ( <BaseCard w={917} h={342} - headerRight={<div>2024年11月 21日 -2024年12月20日</div>} + headerRight={ + <div className={styles.time}>2024年11月 21日 -2024年12月20日</div> + } title="管廊维护情况" - ></BaseCard> + > + <Flex gap={100} style={{ marginTop: 20 }} align="center"> + {INFO.map((item) => { + return ( + <DescriptionItem + value={item.value} + direction="horizontal" + unit={item.unit} + valueStyle={{ + margin: '0 12px', + color: item.vColor, + }} + name={item.name} + key={item.name} + /> + ); + })} + </Flex> + <div> + <div className={styles.chartTitle}>近6个月维护趋势</div> + <EChartsReact + ref={chartRef} + style={{ + height: 150, + }} + option={LineOption} + ></EChartsReact> + </div> + </BaseCard> ); }; diff --git a/src/pages/GlobalModalServices/modals/PipelinePassage/PipeGalleryMaintenanceStatus/option.ts b/src/pages/GlobalModalServices/modals/PipelinePassage/PipeGalleryMaintenanceStatus/option.ts new file mode 100644 index 0000000000000000000000000000000000000000..d70fc57467e3f76916888c0fcb80ed8210cfac42 --- /dev/null +++ b/src/pages/GlobalModalServices/modals/PipelinePassage/PipeGalleryMaintenanceStatus/option.ts @@ -0,0 +1,83 @@ +const option = { + color: ['#57efe5', '#FFB05A'], + tooltip: { + trigger: 'axis', + borderWidth: '0', + backgroundColor: 'rgba(73,81,92,.95)', + textStyle: { + color: '#CBEDFF', + fontSize: 16, + }, + }, + grid: { + left: '0', + right: '0', + bottom: '2%', + top: '20%', + containLabel: true, + }, + legend: { + data: ['本体维护', '附属设施维护'], + icon: 'roundRect', + top: 10, + itemGap: 50, + textStyle: { + fontSize: '16px', + color: '#E4EDFF', + }, + }, + xAxis: [ + { + type: 'category', + boundaryGap: true, + axisLine: { + show: false, + }, + axisLabel: { + show: true, + interval: 0, + textStyle: { + padding: [2, 0, 0, 0], + color: '#CBEDFF', + fontSize: 14, + }, + }, + axisTick: { + show: false, + }, + axisPointer: { + type: 'shadow', + }, + data: [], + }, + ], + yAxis: [ + { + type: 'value', + name: '件', + min: 0, + interval: 10, + axisLabel: { + show: false, + }, + nameTextStyle: { + align: 'left', + color: '#CBEDFF', + padding: [0, 0, 20, -20], + fontSize: 16, + }, + splitLine: { + show: false, + }, + axisLine: { + show: false, + }, + axisTick: { + show: false, + }, + }, + ], + series: [], +}; + +export default option; diff --git a/src/pages/GlobalModalServices/modals/PipelinePassage/PipeMap/index.less b/src/pages/GlobalModalServices/modals/PipelinePassage/PipeMap/index.less index a8e2242b1055229d583ffa1aa81c1094e8ca8dcc..a0c9e7f1f8ab3fe283fbc7739ad8ee277e5c4759 100644 --- a/src/pages/GlobalModalServices/modals/PipelinePassage/PipeMap/index.less +++ b/src/pages/GlobalModalServices/modals/PipelinePassage/PipeMap/index.less @@ -1,3 +1,5 @@ .container { flex: 1; + border-radius: 20px; + overflow: hidden; } diff --git a/src/pages/GlobalModalServices/modals/PipelinePassage/PipelineSituation/index.tsx b/src/pages/GlobalModalServices/modals/PipelinePassage/PipelineSituation/index.tsx index 59a2c7544860aff3d1ef04363fecdbafaeaad771..cfc04b94ec728d015892a5f3ce3c8b3d66d2df59 100644 --- a/src/pages/GlobalModalServices/modals/PipelinePassage/PipelineSituation/index.tsx +++ b/src/pages/GlobalModalServices/modals/PipelinePassage/PipelineSituation/index.tsx @@ -40,13 +40,11 @@ const PipelineSituation: React.FC = () => { return temp; }, []); - console.log(PieOption); - return ( <BaseCard w={902} h={304} - title="全市入廊管线情况 共 10类管线 共 133 公里" + title="全市入廊投运管线情况 共 10类管线 共 133 公里" > <Flex align="center" gap={60} className={styles.container}> <div diff --git a/src/pages/GlobalModalServices/modals/PipelinePassage/PipelineSituation/option.ts b/src/pages/GlobalModalServices/modals/PipelinePassage/PipelineSituation/option.ts index cb9e01d74dde50605b1dc1eb09d4ac43a1c0b511..fbbe98d5c139d14bf6277021934cbfe7f452e17c 100644 --- a/src/pages/GlobalModalServices/modals/PipelinePassage/PipelineSituation/option.ts +++ b/src/pages/GlobalModalServices/modals/PipelinePassage/PipelineSituation/option.ts @@ -1,7 +1,6 @@ const option = { series: [ { - name: 'Access From', type: 'pie', radius: ['70%', '90%'], center: ['50%', '50%'], diff --git a/src/pages/GlobalModalServices/modals/UrbanLighting/LatestWarning/index.less b/src/pages/GlobalModalServices/modals/UrbanLighting/LatestWarning/index.less new file mode 100644 index 0000000000000000000000000000000000000000..96a05293d4961cb27d0df937a43312d83076b2f0 --- /dev/null +++ b/src/pages/GlobalModalServices/modals/UrbanLighting/LatestWarning/index.less @@ -0,0 +1,67 @@ +.tableBody { + width: 100%; + height: 100%; + overflow: auto; + + .tableRow { + background: linear-gradient( + 90deg, + rgba(189, 189, 189, 0.28), + rgba(179, 179, 179, 0) 100% + ); + padding: 0 10px; + height: 40px; + border-radius: 10px; + margin-bottom: 10px; + + &:last-child { + margin-bottom: 0; + } + } + + .tableRowWarning { + background: linear-gradient( + 90deg, + rgba(162, 89, 77, 0.28), + rgba(255, 161, 161, 0) 100% + ); + } + + .cell { + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + } + + .addressCell { + width: 30%; + font-size: 18px; + + .cell(); + } + + .nameCell { + width: 30%; + font-size: 18px; + font-weight: 700; + .cell(); + } + + .timeCell { + width: 30%; + + .cell(); + } + + .warningTypeCell { + color: rgb(255, 97, 97); + width: 20%; + font-size: 18px; + } + + .successTypeCell { + color: rgb(163, 255, 163); + width: 20%; + font-size: 18px; + } +} diff --git a/src/pages/GlobalModalServices/modals/UrbanLighting/LatestWarning/index.tsx b/src/pages/GlobalModalServices/modals/UrbanLighting/LatestWarning/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..30eac626d78a1b90a048ebba631b2520a575bb3e --- /dev/null +++ b/src/pages/GlobalModalServices/modals/UrbanLighting/LatestWarning/index.tsx @@ -0,0 +1,146 @@ +import { DoubleRightOutlined } from '@ant-design/icons'; +import { useBoolean } from 'ahooks'; +import { Flex, Space } from 'antd'; +import classNames from 'classnames'; +import React, { useEffect, useRef } from 'react'; +import BaseCard from '../components/BaseCard'; +import styles from './index.less'; +const LatestWarning: React.FC = () => { + const [playingStatus, { setTrue, setFalse }] = useBoolean(true); + const eventHtmlRef = useRef<HTMLDivElement>(null); + + const dataSource = [ + { + name: '设备关灯异常告警', + address: '通威国际中心草坪东2....', + time: '2024-09-09 12:20', + type: '告警中', + }, + { + name: '设备关灯异常告警', + address: '通威国际中心草坪东2....', + time: '2024-09-09 12:20', + + type: '告警中', + }, + { + name: '设备关灯异常告警', + address: '通威国际中心草坪东2....', + time: '2024-09-09 12:20', + + type: '关闭', + }, + { + name: '设备关灯异常告警', + address: '通威国际中心草坪东2....', + time: '2024-09-09 12:20', + + type: '关闭', + }, + { + name: '设备关灯异常告警', + address: '通威国际中心草坪东2....', + time: '2024-09-09 12:20', + + type: '关闭', + }, + ]; + + /** 实现翻牌器滚动 */ + useEffect(() => { + let intervalId!: NodeJS.Timeout; + if (!eventHtmlRef.current) { + return; + } + + const viewBoxH = eventHtmlRef.current?.clientHeight; + // 进度条速度 + const speed = 50; + if (playingStatus) { + // 开始计时任务 + intervalId = setInterval(() => { + const top = (eventHtmlRef.current as HTMLDivElement)?.scrollTop; + if (!eventHtmlRef.current) { + clearInterval(intervalId); + } + if ( + (eventHtmlRef.current as HTMLDivElement)?.scrollHeight - viewBoxH <= + top + 10 + ) { + eventHtmlRef.current?.scrollTo({ top: 0, behavior: 'instant' }); + return; + } + eventHtmlRef.current?.scrollTo({ + top: top + speed, + behavior: 'smooth', + }); + }, 2500); + } else { + // 清除定时器 + clearInterval(intervalId); + } + // 在组件卸载时清除定时器 + return () => { + clearInterval(intervalId); + }; + }, [playingStatus]); + + return ( + <BaseCard + w={755} + h={153} + title="最新告警" + headerRight={ + <Space + style={{ + fontSize: 16, + color: 'rgb(179, 214, 247)', + cursor: 'pointer', + }} + > + <span>更多</span> + <DoubleRightOutlined /> + </Space> + } + > + <div + className={styles.tableBody} + ref={eventHtmlRef} + onMouseMove={setFalse} + onMouseLeave={setTrue} + > + {dataSource.map((item, index) => { + return ( + <Flex + key={index} + align="center" + className={classNames(styles.tableRow, { + [styles.tableRowWarning]: item.type === '告警中', + })} + > + <img + src={require('@/assets/images/warn.png')} + style={{ width: 19, height: 19 }} + alt="" + ></img> + <div className={styles.nameCell}>{item.name}</div> + <div className={styles.addressCell}>{item.address}</div> + <div className={styles.timeCell}>{item.time}</div> + <div + className={ + item.type === '告警中' + ? styles.warningTypeCell + : styles.successTypeCell + } + > + {item.type} + </div> + </Flex> + ); + })} + </div> + </BaseCard> + ); +}; + +export default LatestWarning; diff --git a/src/pages/GlobalModalServices/modals/UrbanLighting/LightingMap/RoadList/index.less b/src/pages/GlobalModalServices/modals/UrbanLighting/LightingMap/RoadList/index.less new file mode 100644 index 0000000000000000000000000000000000000000..a9a845d27acbb14eb6f67459543b169f08b3b0b8 --- /dev/null +++ b/src/pages/GlobalModalServices/modals/UrbanLighting/LightingMap/RoadList/index.less @@ -0,0 +1,71 @@ +.listContainer { + position: absolute; + width: 352px; + height: 605px; + top: 90px; + left: 0; + z-index: 100; + + box-sizing: border-box; + + .blurBg { + position: absolute; + z-index: 1; + border-radius: 0px 0 20px 0px; + inset: 0; + -webkit-backdrop-filter: blur(20px); + backdrop-filter: blur(20px); + background: rgba(12, 60, 112, 0.7); + } + + .listTitle { + color: rgb(179, 214, 247); + font-family: DingTalk JinBuTi; + font-size: 22px; + margin-bottom: 20px; + } + + .actionBtn { + width: 40px; + height: 82px; + cursor: pointer; + border-radius: 0 10px 10px 0px; + + background: rgba(12, 60, 112, 0.7); + position: absolute; + top: 0; + right: -40px; + color: rgb(179, 214, 247); + line-height: 1.05; + display: flex; + align-items: center; + justify-content: center; + font-size: 18px; + text-align: center; + } + + .content { + position: relative; + width: 100%; + height: 100%; + padding: 20px; + z-index: 2; + + .title { + color: rgb(255, 255, 255); + + font-size: 22px; + font-family: DingTalk JinBuTi; + } + } + + .headerText { + color: rgb(188, 206, 233); + + font-size: 16px; + } + + .tableBody { + height: 90%; + } +} diff --git a/src/pages/GlobalModalServices/modals/UrbanLighting/LightingMap/RoadList/index.tsx b/src/pages/GlobalModalServices/modals/UrbanLighting/LightingMap/RoadList/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..efdd0645b8d946cb856d6f12211d4f26e9133f6b --- /dev/null +++ b/src/pages/GlobalModalServices/modals/UrbanLighting/LightingMap/RoadList/index.tsx @@ -0,0 +1,71 @@ +import EmptySpace from '@/components/EmptySpace'; +import { DoubleLeftOutlined, DoubleRightOutlined } from '@ant-design/icons'; +import { Flex } from 'antd'; +import gsap from 'gsap'; +import React, { useRef, useState } from 'react'; +import styles from './index.less'; + +/** @name 道路列表 */ +const RoadList: React.FC = () => { + /** 展开状态值 */ + const [expandStatus, setExpandStatus] = useState(true); + /** 道路列表元素 */ + const listRef = useRef<HTMLDivElement>(null); + const expandSlider = () => { + if (expandStatus === true) { + setExpandStatus(false); + gsap.to(listRef.current, { + x: -352, + }); + } else { + setExpandStatus(true); + gsap.to(listRef.current, { + x: 0, + }); + } + }; + return ( + <div className={styles.listContainer} ref={listRef}> + <div className={styles.blurBg} /> + <div className={styles.actionBtn} onClick={expandSlider}> + {expandStatus ? ( + <div + style={{ + textOrientation: 'upright', + writingMode: 'vertical-rl', + }} + > + 收起 + <DoubleLeftOutlined></DoubleLeftOutlined> + </div> + ) : ( + <div + style={{ + textOrientation: 'upright', + writingMode: 'vertical-rl', + }} + > + 展开 + <DoubleRightOutlined></DoubleRightOutlined> + </div> + )} + </div> + <div className={styles.content}> + <div className={styles.title}>道路列表</div> + <Flex className={styles.tableHeader} align="center"> + <div style={{ width: '60%' }} className={styles.headerText}> + 道路名称 + </div> + <div style={{ width: '40%' }} className={styles.headerText}> + 功能照明数量 + </div> + </Flex> + <div className={styles.tableBody}> + <EmptySpace></EmptySpace> + </div> + </div> + </div> + ); +}; + +export default RoadList; diff --git a/src/pages/GlobalModalServices/modals/UrbanLighting/LightingMap/index.less b/src/pages/GlobalModalServices/modals/UrbanLighting/LightingMap/index.less new file mode 100644 index 0000000000000000000000000000000000000000..ace3b778370fb3b43e38eab7c1ff26187bcb9bdf --- /dev/null +++ b/src/pages/GlobalModalServices/modals/UrbanLighting/LightingMap/index.less @@ -0,0 +1,29 @@ +.container { + flex: 1; + border-radius: 20px; + overflow: hidden; + position: relative; +} + +.tabContainer { + position: absolute; + inset: 8px 0 0 8px; + z-index: 2; + + .tabItem { + color: #fff; + font-family: DingTalk JinBuTi; + height: fit-content; + font-size: 18px; + padding: 8px 16px; + font-weight: 400; + background: rgba(30, 107, 180, 0.5); + cursor: pointer; + border-radius: 10px; + } + + .active { + background-color: rgb(30, 107, 180); + font-weight: 400; + } +} diff --git a/src/pages/GlobalModalServices/modals/UrbanLighting/LightingMap/index.tsx b/src/pages/GlobalModalServices/modals/UrbanLighting/LightingMap/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..f08a739fc0a4fcd9f6c3281560c07051cafb5ef8 --- /dev/null +++ b/src/pages/GlobalModalServices/modals/UrbanLighting/LightingMap/index.tsx @@ -0,0 +1,57 @@ +import CooglMap from '@/components/CooglMap'; +import { Flex } from 'antd'; +import classNames from 'classnames'; +import React, { useMemo, useState } from 'react'; +import styles from './index.less'; +import RoadList from './RoadList'; + +const Map: React.FC = () => { + const [activeTab, setActiveTab] = useState('1'); + + const tabItems = useMemo( + () => [ + { + key: '1', + label: '市管功能照明监管网格分布', + }, + { + key: '2', + label: '市管功能照明道路分布', + }, + ], + [], + ); + + return ( + <div className={styles.container}> + <Flex gap={10} className={styles.tabContainer}> + {tabItems.map((item, index) => { + return ( + <div + key={index} + onClick={() => { + setActiveTab(item.key); + }} + className={classNames(styles.tabItem, { + [styles.active]: activeTab === item.key, + })} + > + {item.label} + </div> + ); + })} + </Flex> + { + //道路列表 + activeTab === '2' && <RoadList></RoadList> + } + + <CooglMap.MapView + zoom={8} + center={{ x: 103.96, y: 30.658842 }} + ></CooglMap.MapView> + </div> + ); +}; + +export default Map; diff --git a/src/pages/GlobalModalServices/modals/UrbanLighting/LightingOperationSituation/index.less b/src/pages/GlobalModalServices/modals/UrbanLighting/LightingOperationSituation/index.less new file mode 100644 index 0000000000000000000000000000000000000000..a09d10df4239d3322a04cc29218c3ee7fa187bbc --- /dev/null +++ b/src/pages/GlobalModalServices/modals/UrbanLighting/LightingOperationSituation/index.less @@ -0,0 +1,38 @@ +.container { + margin-top: 10px; +} + +.item { + border-radius: 20px; + background: rgba(57, 122, 183, 20%); + width: 33%; + height: 67px; + + > div:nth-of-type(1) { + color: rgb(203, 237, 255); + font-family: DingTalk JinBuTi; + font-size: 20px; + max-width: 40%; + line-height: 1; + } + + > div:nth-of-type(2) { + color: rgb(89, 238, 255); + font-family: D-DIN; + font-size: 26px; + + font-weight: 700; + margin-left: 15px; + } + > div:nth-of-type(3) { + color: rgb(188, 206, 233); + margin-left: 8px; + font-size: 18px; + } +} + +.chartTitle { + color: rgb(203, 237, 255); + margin: 20px 0; + font-size: 18px; +} diff --git a/src/pages/GlobalModalServices/modals/UrbanLighting/LightingOperationSituation/index.tsx b/src/pages/GlobalModalServices/modals/UrbanLighting/LightingOperationSituation/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..5c37c18bae4c826689ae878251bad3b72b97e3c0 --- /dev/null +++ b/src/pages/GlobalModalServices/modals/UrbanLighting/LightingOperationSituation/index.tsx @@ -0,0 +1,135 @@ +import { Flex } from 'antd'; +import EChartsReact from 'echarts-for-react'; +import { cloneDeep } from 'lodash'; +import React, { useLayoutEffect, useMemo, useRef } from 'react'; +import BaseCard from '../components/BaseCard'; +import styles from './index.less'; +import option from './option'; +/** @name 情况 */ +const LightingOperationSituation: React.FC = () => { + const chartRef = useRef<any>(); + + const INFO = useMemo(() => { + return [ + { + name: '完好率', + value: 98.5, + unit: '%', + }, + { + name: '亮灯率', + value: 82, + unit: '%', + }, + { + name: '故障处置及时率', + value: 98.5, + unit: '%', + }, + ]; + }, []); + + useLayoutEffect(() => { + chartRef.current?.resize(); + }, []); + + const LineOption = useMemo(() => { + const temp = cloneDeep(option) as any; + const xAxis = [ + '2024年7月', + '2024年8月', + '2024年9月', + '2024年10月', + '2024年11月', + '2024年12月', + ]; + const yAxis = [1652, 1652, 1652, 1652, 1652, 1652, 1652]; + temp.xAxis[0].data = xAxis; + + temp.legend.data = INFO.map((v) => v.name); + + const lineSeries = [ + { + name: '完好率', + type: 'line', + symbol: 'none', + stack: 'Total', + lineStyle: { + // color: '#57efe5', + width: 3, + }, + smooth: true, + data: [120, 132, 101, 134, 90, 230, 210], + }, + { + name: '亮灯率', + type: 'line', + stack: 'Total', + lineStyle: { + // color: '#FFB05A', + width: 3, + }, + smooth: true, + + symbol: 'none', + data: [220, 182, 191, 234, 290, 330, 310], + }, + { + name: '故障处置及时率', + type: 'line', + stack: 'Total', + lineStyle: { + // color: '#FFB05A', + width: 3, + }, + smooth: true, + + symbol: 'none', + data: [180, 122, 111, 134, 170, 230, 210], + }, + ]; + temp.series = lineSeries; + return temp; + }, []); + return ( + <BaseCard + w={755} + h={422} + title="市管功能照明运行态势" + headerRight={ + <div style={{ fontSize: 16 }}> + 统计时间范围:2024年11月25日 - 2024年12月24日 + </div> + } + > + <Flex justify="space-between" style={{ marginTop: 20 }} align="center"> + {INFO.map((item) => { + return ( + <Flex + className={styles.item} + align="center" + justify="center" + key={item.name} + > + <div>{item.name}</div> + <div>{item.value}</div> + <div>{item.unit}</div> + </Flex> + ); + })} + </Flex> + <div> + <div className={styles.chartTitle}>近半年运行趋势</div> + <EChartsReact + ref={chartRef} + style={{ + height: 150, + }} + option={LineOption} + ></EChartsReact> + </div> + </BaseCard> + ); +}; + +export default LightingOperationSituation; diff --git a/src/pages/GlobalModalServices/modals/UrbanLighting/LightingOperationSituation/option.ts b/src/pages/GlobalModalServices/modals/UrbanLighting/LightingOperationSituation/option.ts new file mode 100644 index 0000000000000000000000000000000000000000..613de2baaed273d15beeedeeff9659b47e3e0460 --- /dev/null +++ b/src/pages/GlobalModalServices/modals/UrbanLighting/LightingOperationSituation/option.ts @@ -0,0 +1,83 @@ +const option = { + color: ['#FFB05A', '#57EFE5', '#5AFF65'], + tooltip: { + trigger: 'axis', + borderWidth: '0', + backgroundColor: 'rgba(73,81,92,.95)', + textStyle: { + color: '#CBEDFF', + fontSize: 16, + }, + }, + grid: { + left: '0', + right: '0', + bottom: '2%', + top: '20%', + containLabel: true, + }, + legend: { + data: [], + icon: 'roundRect', + top: 10, + itemGap: 50, + textStyle: { + fontSize: '16px', + color: '#E4EDFF', + }, + }, + xAxis: [ + { + type: 'category', + boundaryGap: true, + axisLine: { + show: false, + }, + axisLabel: { + show: true, + interval: 0, + textStyle: { + padding: [2, 0, 0, 0], + color: '#CBEDFF', + fontSize: 14, + }, + }, + axisTick: { + show: false, + }, + axisPointer: { + type: 'shadow', + }, + data: [], + }, + ], + yAxis: [ + { + type: 'value', + name: '件', + min: 0, + interval: 10, + axisLabel: { + show: false, + }, + nameTextStyle: { + align: 'left', + color: '#CBEDFF', + padding: [0, 0, 20, -20], + fontSize: 16, + }, + splitLine: { + show: false, + }, + axisLine: { + show: false, + }, + axisTick: { + show: false, + }, + }, + ], + series: [], +}; + +export default option; diff --git a/src/pages/GlobalModalServices/modals/UrbanLighting/OperationCondition/index.less b/src/pages/GlobalModalServices/modals/UrbanLighting/OperationCondition/index.less new file mode 100644 index 0000000000000000000000000000000000000000..4e9d187bd39fb47c78cc1ac3ff0821616fb6acce --- /dev/null +++ b/src/pages/GlobalModalServices/modals/UrbanLighting/OperationCondition/index.less @@ -0,0 +1,49 @@ +.container { + margin-top: 10px; +} + +.item { + border-radius: 10px; + background: rgba(57, 122, 183, 20%); + width: 32.5%; + padding-left: 15px; + height: 54px; + position: relative; + + > div:nth-of-type(1) { + color: rgb(203, 237, 255); + font-family: DingTalk JinBuTi; + font-size: 18px; + max-width: 50%; + line-height: 1; + } + + > div:nth-of-type(2) { + color: rgb(89, 238, 255); + font-family: D-DIN; + font-size: 24px; + + font-weight: 700; + margin-left: 15px; + } + > div:nth-of-type(3) { + color: rgb(188, 206, 233); + margin-left: 8px; + font-size: 16px; + } + .tag { + position: absolute; + right: 0; + top: 0; + border-radius: 0px 10px 0px 10px; + background: rgba(0, 192, 146, 50%); + padding: 2px 3px; + } +} + +.chartTitle { + color: rgb(203, 237, 255); + margin: 10px 0; + + font-size: 18px; +} diff --git a/src/pages/GlobalModalServices/modals/UrbanLighting/OperationCondition/index.tsx b/src/pages/GlobalModalServices/modals/UrbanLighting/OperationCondition/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..164ffc1db82edd4ab2f354b6805eb20eff2eccbe --- /dev/null +++ b/src/pages/GlobalModalServices/modals/UrbanLighting/OperationCondition/index.tsx @@ -0,0 +1,118 @@ +import { Flex } from 'antd'; +import dayjs from 'dayjs'; +import EChartsReact from 'echarts-for-react'; +import { cloneDeep } from 'lodash'; +import React, { useLayoutEffect, useMemo, useRef } from 'react'; +import BaseCard from '../components/BaseCard'; +import styles from './index.less'; +import option from './option'; +/** @name 情况 */ +const OperationCondition: React.FC = () => { + const chartRef = useRef<any>(); + + const INFO = useMemo(() => { + return [ + { + name: '开灯时间', + value: '08:00', + tag: dayjs().format('MM月DD日'), + }, + { + name: '关灯时间', + value: '02:00', + tag: dayjs().add(1, 'day').format('MM月DD日'), + }, + { + name: '自然光照度', + value: 22122, + unit: 'lux', + tag: '实时', + }, + ]; + }, []); + + useLayoutEffect(() => { + chartRef.current?.resize(); + }, []); + + const LineOption = useMemo(() => { + const temp = cloneDeep(option) as any; + const xAxis = [ + '2024年7月', + '2024年8月', + '2024年9月', + '2024年10月', + '2024年11月', + '2024年12月', + ]; + const yAxis = [1652, 1652, 1652, 1652, 1652, 1652, 1652]; + temp.xAxis[0].data = xAxis; + + temp.legend.data = INFO.map((v) => v.name); + + const lineSeries = [ + { + name: '完好率', + type: 'line', + symbol: 'none', + stack: 'Total', + lineStyle: { + color: '#F0FF69', + width: 3, + }, + smooth: true, + areaStyle: { + color: { + type: 'linear', + x: 0, + y: 0, + x2: 0, + y2: 1, + colorStops: [ + { + offset: 0, + color: 'rgb(240, 255, 105,0.26)', // 0% 处的颜色 + }, + { + offset: 1, + color: 'rgb(240, 255, 105,0)', // 100% 处的颜色 + }, + ], + global: false, // 缺省为 false + }, + }, + data: [120, 132, 101, 134, 90, 230, 210], + }, + ]; + temp.series = lineSeries; + return temp; + }, []); + return ( + <BaseCard w={755} h={303} title="运行情况"> + <Flex justify="space-between" style={{ marginTop: 10 }} align="center"> + {INFO.map((item) => { + return ( + <Flex className={styles.item} align="center" key={item.name}> + <div>{item.name}</div> + <div>{item.value}</div> + <div>{item.unit}</div> + <div className={styles.tag}>{item.tag}</div> + </Flex> + ); + })} + </Flex> + <div> + <div className={styles.chartTitle}>昨日功率趋势</div> + <EChartsReact + ref={chartRef} + style={{ + height: 120, + }} + option={LineOption} + ></EChartsReact> + </div> + </BaseCard> + ); +}; + +export default OperationCondition; diff --git a/src/pages/GlobalModalServices/modals/UrbanLighting/OperationCondition/option.ts b/src/pages/GlobalModalServices/modals/UrbanLighting/OperationCondition/option.ts new file mode 100644 index 0000000000000000000000000000000000000000..a8a02d30dfa45e3e72e3b0f0201b57bdd933d9ef --- /dev/null +++ b/src/pages/GlobalModalServices/modals/UrbanLighting/OperationCondition/option.ts @@ -0,0 +1,83 @@ +const option = { + color: ['#FFB05A', '#57EFE5', '#5AFF65'], + tooltip: { + trigger: 'axis', + borderWidth: '0', + backgroundColor: 'rgba(73,81,92,.95)', + textStyle: { + color: '#CBEDFF', + fontSize: 16, + }, + }, + grid: { + left: '0', + right: '0', + bottom: '2%', + top: '0%', + containLabel: true, + }, + legend: { + data: [], + icon: 'roundRect', + top: 10, + itemGap: 50, + textStyle: { + fontSize: '16px', + color: '#E4EDFF', + }, + }, + xAxis: [ + { + type: 'category', + boundaryGap: true, + axisLine: { + show: false, + }, + axisLabel: { + show: true, + interval: 0, + textStyle: { + padding: [2, 0, 0, 0], + color: '#CBEDFF', + fontSize: 14, + }, + }, + axisTick: { + show: false, + }, + axisPointer: { + type: 'shadow', + }, + data: [], + }, + ], + yAxis: [ + { + type: 'value', + name: '件', + min: 0, + interval: 10, + axisLabel: { + show: false, + }, + nameTextStyle: { + align: 'left', + color: '#CBEDFF', + padding: [0, 0, 20, -20], + fontSize: 16, + }, + splitLine: { + show: false, + }, + axisLine: { + show: false, + }, + axisTick: { + show: false, + }, + }, + ], + series: [], +}; + +export default option; diff --git a/src/pages/GlobalModalServices/modals/UrbanLighting/Overview/index.less b/src/pages/GlobalModalServices/modals/UrbanLighting/Overview/index.less new file mode 100644 index 0000000000000000000000000000000000000000..f1601638072f7cec1fddbef0cceccfe7cda84707 --- /dev/null +++ b/src/pages/GlobalModalServices/modals/UrbanLighting/Overview/index.less @@ -0,0 +1,32 @@ +.tabItem { + color: rgb(76, 134, 189); + font-family: DingTalk JinBuTi; + font-size: 18px; + font-weight: 400; + cursor: pointer; +} + +.active { + color: rgb(255, 255, 255); + + font-weight: 400; +} + +.container { + margin-top: 10px; +} + +.legendBg { + // width: 244px; + height: 38px; + padding: 8px 14px; + border-radius: 7px; + background: rgba(41, 181, 255, 0.12); +} + +.legendContent { + display: flex; + flex-direction: column; + + row-gap: 12px; +} diff --git a/src/pages/GlobalModalServices/modals/UrbanLighting/Overview/index.tsx b/src/pages/GlobalModalServices/modals/UrbanLighting/Overview/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..a4d07a9b1d2109ea93dead23dc58c0e5f3c30851 --- /dev/null +++ b/src/pages/GlobalModalServices/modals/UrbanLighting/Overview/index.tsx @@ -0,0 +1,83 @@ +import { Badge, Flex } from 'antd'; +import EChartsReact from 'echarts-for-react'; +import { cloneDeep } from 'lodash'; +import React, { memo, useLayoutEffect, useMemo, useRef, useState } from 'react'; +import BaseCard from '../components/BaseCard'; +import styles from './index.less'; +import { pieOption } from './option'; +/** @name 全市已移交纳入管理综合管廊概况 */ +const Overview: React.FC = memo(() => { + const [pieData, setPieData] = useState( + [...Array(4)].map((_, i) => { + return { + value: Math.floor(Math.random() * 100), + name: '给水(输水)管道' + i, + }; + }), + ); + const chartRef = useRef<any>(); + + const colors = [ + '#5DDDFF', + '#A550FF', + '#F07283', + '#7664EC', + '#77E67B', + '#35B2FF', + '#FFE335', + '#FF9B5D', + ]; + + useLayoutEffect(() => { + chartRef.current?.resize(); + }, []); + + const PieOption = useMemo(() => { + const temp = cloneDeep(pieOption) as any; + temp.color = colors; + temp.series[0].data = pieData; + return temp; + }, []); + + return ( + <BaseCard + w={755} + h={281} + title="市管功能照明灯盏数 25.58 万盏 功率 23031 千瓦" + > + <Flex align="center" gap={60} className={styles.container}> + <div + style={{ + height: 130, + width: 130, + }} + > + <EChartsReact + ref={chartRef} + style={{ + height: 130, + width: 130, + }} + option={PieOption} + ></EChartsReact> + </div> + + <div className={styles.legendContent}> + {pieData.map((item, index) => { + return ( + <Flex key={index} className={styles.legendBg} gap={20}> + <Badge color={colors[index % colors.length]} /> + + <div>{item.name}</div> + <div>{item.value} 万盏</div> + <div>56.25 %</div> + </Flex> + ); + })} + </div> + </Flex> + </BaseCard> + ); +}); + +export default Overview; diff --git a/src/pages/GlobalModalServices/modals/UrbanLighting/Overview/option.ts b/src/pages/GlobalModalServices/modals/UrbanLighting/Overview/option.ts new file mode 100644 index 0000000000000000000000000000000000000000..7f8f9c6af54331087f773ac528c19ad69de16121 --- /dev/null +++ b/src/pages/GlobalModalServices/modals/UrbanLighting/Overview/option.ts @@ -0,0 +1,139 @@ +const option = { + color: ['#5F8BFF'], + tooltip: { + trigger: 'axis', + borderWidth: '0', + backgroundColor: 'rgba(73,81,92,.95)', + textStyle: { + color: '#fff', + fontSize: 16, + }, + }, + grid: { + left: '0', + right: '0', + bottom: '2%', + top: '20%', + containLabel: true, + }, + + xAxis: [ + { + type: 'category', + boundaryGap: true, + axisLine: { + show: false, + }, + axisLabel: { + show: true, + interval: 0, + textStyle: { + padding: [2, 0, 0, 0], + color: '#CBEDFF', + fontSize: 14, + }, + }, + axisTick: { + show: false, + }, + axisPointer: { + type: 'shadow', + }, + data: [], + }, + ], + yAxis: [ + { + type: 'value', + name: '件', + min: 0, + interval: 10, + axisLabel: { + show: false, + }, + nameTextStyle: { + align: 'left', + color: '#CBEDFF', + padding: [0, 0, 20, -20], + fontSize: 16, + }, + splitLine: { + show: false, + }, + axisLine: { + show: false, + }, + axisTick: { + show: false, + }, + }, + ], + series: [ + { + // name: '投诉量', + type: 'bar', + barWidth: 20, + data: [], + itemStyle: { + borderRadius: 20, + color: { + type: 'linear', + x: 0, + y: 0, + x2: 0, + y2: 1, + colorStops: [ + { + offset: 0, + color: '#5DDDFF', // 0% 处的颜色 + }, + { + offset: 1, + color: '#706BFF', // 100% 处的颜色 + }, + ], + global: false, // 缺省为 false + }, + }, + label: { + show: true, + position: 'top', + distance: 6, + color: '#FFFFFF', + fontSize: 20, + fontWeight: 700, + }, + }, + ], +}; + +export const pieOption = { + series: [ + { + name: 'Access From', + type: 'pie', + radius: ['70%', '90%'], + center: ['50%', '50%'], + avoidLabelOverlap: false, + padAngle: 5, + itemStyle: {}, + label: { + show: false, + position: 'center', + }, + emphasis: { + label: { + show: true, + fontSize: 10, + fontWeight: 'bold', + }, + }, + labelLine: { + show: false, + }, + data: [], + }, + ], +}; + +export default option; diff --git a/src/pages/GlobalModalServices/modals/UrbanLighting/SensingDevice/index.less b/src/pages/GlobalModalServices/modals/UrbanLighting/SensingDevice/index.less new file mode 100644 index 0000000000000000000000000000000000000000..e9f090316ba4d7d444a9f98fed8b68e07e691d32 --- /dev/null +++ b/src/pages/GlobalModalServices/modals/UrbanLighting/SensingDevice/index.less @@ -0,0 +1,27 @@ +.container { + margin-top: 20px; +} + +.legendBg { + width: 244px; + height: 38px; + padding: 0 14px; + border-radius: 7px; + background: rgba(41, 181, 255, 0.12); + display: flex; + align-items: center; +} + +.legendContent { + display: flex; + flex-direction: row; + flex-wrap: wrap; + row-gap: 5px; + column-gap: 10px; +} + +.legendText { + color: rgb(188, 206, 233); + font-size: 18px; + margin: 0 12px; +} diff --git a/src/pages/GlobalModalServices/modals/UrbanLighting/SensingDevice/index.tsx b/src/pages/GlobalModalServices/modals/UrbanLighting/SensingDevice/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..e8ca3c2defacc0708553160faf83be88a19ad0ee --- /dev/null +++ b/src/pages/GlobalModalServices/modals/UrbanLighting/SensingDevice/index.tsx @@ -0,0 +1,78 @@ +import { Badge, Flex } from 'antd'; +import EChartsReact from 'echarts-for-react'; +import { cloneDeep } from 'lodash'; +import React, { useLayoutEffect, useMemo, useRef, useState } from 'react'; +import BaseCard from '../components/BaseCard'; +import styles from './index.less'; +import option from './option'; +/** @name 感知设备 */ +const SensingDevice: React.FC = () => { + const chartRef = useRef<any>(); + + const colors = [ + '#5DDDFF', + '#A550FF', + '#F07283', + '#7664EC', + '#77E67B', + '#35B2FF', + '#FFE335', + '#FF9B5D', + ]; + + useLayoutEffect(() => { + chartRef.current?.resize(); + }, []); + + const [pieData, setPieData] = useState( + [...Array(5)].map((_, i) => { + return { + value: Math.floor(Math.random() * 100), + name: '给水(输水)管道' + i, + }; + }), + ); + + const PieOption = useMemo(() => { + const temp = cloneDeep(option) as any; + temp.color = colors; + temp.series[0].data = pieData; + return temp; + }, []); + + return ( + <BaseCard w={755} h={222} title="感知设备 15.28 万个"> + <Flex align="center" gap={30} className={styles.container}> + <div + style={{ + height: 120, + width: 120, + }} + > + <EChartsReact + ref={chartRef} + style={{ + height: 120, + width: 120, + }} + option={PieOption} + ></EChartsReact> + </div> + + <div className={styles.legendContent}> + {pieData.map((item, index) => { + return ( + <div key={index} className={styles.legendBg}> + <Badge color={colors[index % colors.length]} text={item.name} /> + <div className={styles.legendText}>{item.value}</div> + <div>个</div> + </div> + ); + })} + </div> + </Flex> + </BaseCard> + ); +}; + +export default SensingDevice; diff --git a/src/pages/GlobalModalServices/modals/UrbanLighting/SensingDevice/option.ts b/src/pages/GlobalModalServices/modals/UrbanLighting/SensingDevice/option.ts new file mode 100644 index 0000000000000000000000000000000000000000..fbbe98d5c139d14bf6277021934cbfe7f452e17c --- /dev/null +++ b/src/pages/GlobalModalServices/modals/UrbanLighting/SensingDevice/option.ts @@ -0,0 +1,29 @@ +const option = { + series: [ + { + type: 'pie', + radius: ['70%', '90%'], + center: ['50%', '50%'], + avoidLabelOverlap: false, + padAngle: 5, + itemStyle: {}, + label: { + show: false, + position: 'center', + }, + emphasis: { + label: { + show: true, + fontSize: 10, + fontWeight: 'bold', + }, + }, + labelLine: { + show: false, + }, + data: [], + }, + ], +}; + +export default option; diff --git a/src/pages/GlobalModalServices/modals/UrbanLighting/components/BaseCard/index.less b/src/pages/GlobalModalServices/modals/UrbanLighting/components/BaseCard/index.less new file mode 100644 index 0000000000000000000000000000000000000000..54f75d9512f577763891a412279d0770a103c842 --- /dev/null +++ b/src/pages/GlobalModalServices/modals/UrbanLighting/components/BaseCard/index.less @@ -0,0 +1,19 @@ +.title { + color: rgb(203, 237, 255); + font-family: DingTalk JinBuTi; + font-size: 22px; + font-weight: 400; +} + +.container { + border-radius: 20px; + background: rgba(57, 122, 183, 0.2); + padding: 20px; + display: flex; + flex-direction: column; +} + +.content { + flex: 1; + overflow: hidden; +} diff --git a/src/pages/GlobalModalServices/modals/UrbanLighting/components/BaseCard/index.tsx b/src/pages/GlobalModalServices/modals/UrbanLighting/components/BaseCard/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..562045cf9a487bce499b3a197d36ba830997b5f5 --- /dev/null +++ b/src/pages/GlobalModalServices/modals/UrbanLighting/components/BaseCard/index.tsx @@ -0,0 +1,26 @@ +import { Flex } from 'antd'; +import React, { PropsWithChildren } from 'react'; +import styles from './index.less'; + +interface PropsType { + w?: any; + h?: any; + title?: string; + headerRight?: React.ReactNode; +} + +/** @name 基础卡片 */ +const BaseCard: React.FC<PropsWithChildren<PropsType>> = (props) => { + const { w, h, title, children, headerRight } = props; + return ( + <div className={styles.container} style={{ width: w, height: h }}> + <Flex justify="space-between" className={styles.title}> + {title} + {headerRight} + </Flex> + <div className={styles.content}>{children}</div> + </div> + ); +}; + +export default BaseCard; diff --git a/src/pages/GlobalModalServices/modals/UrbanLighting/index.less b/src/pages/GlobalModalServices/modals/UrbanLighting/index.less new file mode 100644 index 0000000000000000000000000000000000000000..a8e2242b1055229d583ffa1aa81c1094e8ca8dcc --- /dev/null +++ b/src/pages/GlobalModalServices/modals/UrbanLighting/index.less @@ -0,0 +1,3 @@ +.container { + flex: 1; +} diff --git a/src/pages/GlobalModalServices/modals/UrbanLighting/index.tsx b/src/pages/GlobalModalServices/modals/UrbanLighting/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..d6bb7403751491397ee88e5ce113e6d969380d21 --- /dev/null +++ b/src/pages/GlobalModalServices/modals/UrbanLighting/index.tsx @@ -0,0 +1,30 @@ +import { Flex } from 'antd'; +import React from 'react'; +import styles from './index.less'; +import LightingOperationSituation from './LightingOperationSituation'; +import Overview from './Overview'; + +import LatestWarning from './LatestWarning'; +import LightingMap from './LightingMap'; +import OperationCondition from './OperationCondition'; +import SensingDevice from './SensingDevice'; + +/** @name 城市照明 */ +const UrbanLighting: React.FC = () => { + return ( + <Flex className={styles.container} gap={20}> + <Flex vertical gap={20}> + <Overview /> + <LightingOperationSituation /> + </Flex> + <LightingMap></LightingMap> + <Flex vertical gap={20}> + <SensingDevice></SensingDevice> + <OperationCondition></OperationCondition> + <LatestWarning></LatestWarning> + </Flex> + </Flex> + ); +}; + +export default UrbanLighting; diff --git a/src/pages/GlobalModalServices/registry.tsx b/src/pages/GlobalModalServices/registry.tsx index 2515e333c1371c7a5888dcaea7bb68ba6d96b3e5..e63e5f85597c1fa6101451e64b80ea5ad9170a77 100644 --- a/src/pages/GlobalModalServices/registry.tsx +++ b/src/pages/GlobalModalServices/registry.tsx @@ -8,6 +8,7 @@ import AreaSynergyList from './modals/AreaSynergy/AreaSynergyList'; import Category from './modals/Category'; import CgftEvent from './modals/CgftEvent'; import CollectionEvent from './modals/CollectionEvent'; +import ConstructionWaste from './modals/ConstructionWaste'; import DataActivity from './modals/DataActivity'; import DataBase from './modals/DataBase'; import DataGovernance from './modals/DataGovernance'; @@ -29,6 +30,7 @@ import SanitationEvent from './modals/SanitationEvent'; import SanitationResource from './modals/SanitationResource'; import SignModel from './modals/SignModel'; import ToDisposed from './modals/ToDisposed'; +import UrbanLighting from './modals/UrbanLighting'; import UrbanOperation from './modals/UrbanOperation'; import { ModalMapping } from './type'; @@ -399,6 +401,35 @@ export default class Registry { defaultProps: {}, modal: PipelinePassage, }, + + /** + * 城市照明2级弹窗 + * @module IndustryOperationNew + * @see IndustryOperationNew.CityLighting + */ + UrbanLighting: { + defaultConfig: { + w: 2957, + h: 858, + title: '城市照明', + }, + defaultProps: {}, + modal: UrbanLighting, + }, + + /** + * 固废处置2级弹窗 + * @module ConstructionWaste + */ + ConstructionWaste: { + defaultConfig: { + w: 2501, + h: 1004, + title: '建筑垃圾' + }, + defaultProps: {}, + modal: ConstructionWaste + }, }; static get(modalKey: ModalKey) { diff --git a/src/pages/GlobalModalServices/type.ts b/src/pages/GlobalModalServices/type.ts index 2c845de492a053933cf436217fa0ee4b40d3d40a..3df2c3d004cba3176bec7953aa18476ed22ac35e 100644 --- a/src/pages/GlobalModalServices/type.ts +++ b/src/pages/GlobalModalServices/type.ts @@ -1,3 +1,4 @@ +import { CSSProperties } from 'react'; import { ModalKey } from './registry'; export interface GlobalModalConfig<T = any> { @@ -20,7 +21,10 @@ export interface GlobalModalConfig<T = any> { component?: React.FC<any> | React.ReactElement; // 是否保持弹窗状态,默认为false,弹窗关闭后会自动销毁,目前无用 keepalive?: boolean; + props?: T; + /** 会附加到弹窗的 */ + style?: CSSProperties; } export type ModalMapping = { @@ -63,11 +67,6 @@ export type GlobalModalServicesModalMethods = { clear: () => void; /** 设置弹窗基础信息 */ setOptionsById?: (modalId: string, config: GlobalModalConfig) => void; - /** - * 设置弹窗参数 - * 仅限定 弹窗内调用 - * */ - setOptions?(options: Partial<GlobalModalConfig>): void; }; export interface ChildrenModalMethods extends GlobalModalServicesModalMethods { diff --git a/src/pages/NewHome/NewLeftSidebar/CitySecurityInfo/index.tsx b/src/pages/NewHome/NewLeftSidebar/CitySecurityInfo/index.tsx index 7ffb76d462d752648255cf5e85f99aface2e2953..4b388366955ed54592eb380f1a74c15a0328618a 100644 --- a/src/pages/NewHome/NewLeftSidebar/CitySecurityInfo/index.tsx +++ b/src/pages/NewHome/NewLeftSidebar/CitySecurityInfo/index.tsx @@ -6,7 +6,7 @@ import Modal from '@/components/HncyModal'; import RiskEvents from '@/pages/Common/Event/RiskEvents'; import services from '@/services'; import { useRequest } from 'ahooks'; -import { useEffect, useMemo, useState } from 'react'; +import { useMemo, useState } from 'react'; import styles from './index.less'; const CitySecurityInfo = () => { @@ -20,6 +20,7 @@ const CitySecurityInfo = () => { type: '', }); + const [pipeGalleryVisible, setPipeGalleryVisible] = useState(false); //预警数 const { data: warnCoutnData } = useRequest(() => @@ -34,36 +35,40 @@ const CitySecurityInfo = () => { { type: '红色风险', label: '红色风险', - value: warnCoutnData?.data?.data?.records?.[0]?.stat?.find( - (item) => item?.risklevel === '红色预警', - )?.num || '--', + value: + warnCoutnData?.data?.data?.records?.[0]?.stat?.find( + (item) => item?.risklevel === '红色预警', + )?.num || '--', icon: risk1, color: 'linear-gradient(180deg, rgb(255, 138, 138), rgb(208, 62, 62))', }, { type: '橙色风险', label: '橙色风险', - value: warnCoutnData?.data?.data?.records?.[0]?.stat?.find( - (item) => item?.risklevel === '橙色预警', - )?.num || '--', + value: + warnCoutnData?.data?.data?.records?.[0]?.stat?.find( + (item) => item?.risklevel === '橙色预警', + )?.num || '--', icon: risk4, color: 'linear-gradient(180deg, rgb(255, 176, 121), rgb(238, 126, 48))', }, { type: '黄色风险', label: '黄色风险', - value: warnCoutnData?.data?.data?.records?.[0]?.stat?.find( - (item) => item?.risklevel === '黄色预警', - )?.num || '--', + value: + warnCoutnData?.data?.data?.records?.[0]?.stat?.find( + (item) => item?.risklevel === '黄色预警', + )?.num || '--', icon: risk3, color: 'linear-gradient(180deg, rgb(255, 228, 155), rgb(231, 182, 55))', }, { type: '一般风险', label: '一般风险', - value: warnCoutnData?.data?.data?.records?.[0]?.stat?.find( - (item) => item?.risklevel === '一般预警', - )?.num || '--', + value: + warnCoutnData?.data?.data?.records?.[0]?.stat?.find( + (item) => item?.risklevel === '一般预警', + )?.num || '--', icon: risk2, color: 'linear-gradient(to right, rgb(122, 177, 255), rgb(37, 128, 255))', @@ -71,11 +76,12 @@ const CitySecurityInfo = () => { ]; }, [warnCoutnData]); - - return ( <div className={styles.container}> - <div className={styles.header}> + <div + className={styles.header} + onClick={() => setPipeGalleryVisible(true)} + > <span className={styles.title}>城市安全</span> <div className={styles.riskList}> {riskData.map((item) => ( @@ -115,7 +121,7 @@ const CitySecurityInfo = () => { height={846} > <RiskEvents - statisticsData={ warnCoutnData?.data?.data?.records?.[0]} + statisticsData={warnCoutnData?.data?.data?.records?.[0]} defaultCategory={modalOpt?.type} /> </Modal> diff --git a/src/pages/NewHome/NewRightContent/IndustryOperationNew/components/CityLighting/index.css b/src/pages/NewHome/NewRightContent/IndustryOperationNew/components/CityLighting/index.css deleted file mode 100644 index 1cc6b5c965c614b4d70135bc525c972187ccfbd2..0000000000000000000000000000000000000000 --- a/src/pages/NewHome/NewRightContent/IndustryOperationNew/components/CityLighting/index.css +++ /dev/null @@ -1,3 +0,0 @@ -.container { - padding: 10px 20px 20px 20px; -} diff --git a/src/pages/NewHome/NewRightContent/IndustryOperationNew/components/CityLighting/index.tsx b/src/pages/NewHome/NewRightContent/IndustryOperationNew/components/CityLighting/index.tsx index d0d129a139e42ac026bd3f21258863b8f41e8968..5fee31389b1ed82d06add5b4861af8a4650de027 100644 --- a/src/pages/NewHome/NewRightContent/IndustryOperationNew/components/CityLighting/index.tsx +++ b/src/pages/NewHome/NewRightContent/IndustryOperationNew/components/CityLighting/index.tsx @@ -1,9 +1,11 @@ import DescriptionItem from '@/components/DescriptionItem'; +import { useGlobalModalServices } from '@/pages/GlobalModalServices/provider'; import { Flex } from 'antd'; import React from 'react'; import styles from './index.less'; const CityLighting: React.FC = () => { + const { dispatch } = useGlobalModalServices(); const commonValueStyle = { background: 'linear-gradient(180deg, #AAFFF6 0%, #25BBFF 100%)', WebkitBackgroundClip: 'text', @@ -14,19 +16,12 @@ const CityLighting: React.FC = () => { lineHeight: 1.1, }; - // const valueStyle = { - // ...commonValueStyle, - // marginTop: '120px !important', - // }; - const commonLabelStyle = { color: '#BCCEE9', - // fontFamily: '微软雅黑', + fontSize: '20px', fontWeight: 400, lineHeight: 1.1, - - // marginTop: '-10px', }; const labelStyle = { @@ -36,7 +31,6 @@ const CityLighting: React.FC = () => { const commonUnitStyle = { color: '#BCCEE9', - // fontFamily: '微软雅黑', fontSize: '20px', fontWeight: 400, lineHeight: 1.1, @@ -49,6 +43,9 @@ const CityLighting: React.FC = () => { value={25.23} name="市管照明灯盏数" unit="万盏" + onClick={() => { + dispatch.push('UrbanLighting'); + }} valueStyle={commonValueStyle} labelStyle={commonLabelStyle} unitStyle={commonUnitStyle} diff --git a/src/pages/NewHome/NewRightContent/IndustryOperationNew/components/MunicipalFacilities/index.tsx b/src/pages/NewHome/NewRightContent/IndustryOperationNew/components/MunicipalFacilities/index.tsx index 0169a70fad33ed42e094512e60cd9bddba3a6e29..fd155797314496ddccc1d8cb8a468a470653f90d 100644 --- a/src/pages/NewHome/NewRightContent/IndustryOperationNew/components/MunicipalFacilities/index.tsx +++ b/src/pages/NewHome/NewRightContent/IndustryOperationNew/components/MunicipalFacilities/index.tsx @@ -67,9 +67,9 @@ const MunicipalFacilities: React.FC = () => { <DescriptionItem value={523} name="本月完成病害维护整治" - // onClick={() => { - // dispatch.push('PipelinePassage'); - // }} + onClick={() => { + dispatch.push('PipelinePassage'); + }} unit="条" valueStyle={commonValueStyle} labelStyle={commonLabelStyle} diff --git a/src/pages/NewHome/NewRightContent/IndustryOperationNew/components/WasteDisposal/index.tsx b/src/pages/NewHome/NewRightContent/IndustryOperationNew/components/WasteDisposal/index.tsx index cfe32e0f754d6b0d2328fd7e8f07321b10cfabe3..4e26adefde33f67ca812e20f63dc9c278bba014e 100644 --- a/src/pages/NewHome/NewRightContent/IndustryOperationNew/components/WasteDisposal/index.tsx +++ b/src/pages/NewHome/NewRightContent/IndustryOperationNew/components/WasteDisposal/index.tsx @@ -1,9 +1,12 @@ import DescriptionItem from '@/components/DescriptionItem'; +import { useGlobalModalServices } from '@/pages/GlobalModalServices/provider'; import { Flex } from 'antd'; import React from 'react'; import styles from './index.less'; const WasteDisposal: React.FC = () => { + const { dispatch } = useGlobalModalServices(); + const commonValueStyle = { background: 'linear-gradient(180deg, #AAFFF6 0%, #25BBFF 100%)', WebkitBackgroundClip: 'text', @@ -30,6 +33,14 @@ const WasteDisposal: React.FC = () => { lineHeight: 1.1, }; + const handleClick = () => { + dispatch.push('ConstructionWaste', { + style: { + top: 30, + }, + }); + }; + return ( <div className={styles.container}> <Flex vertical gap={0}> @@ -82,6 +93,7 @@ const WasteDisposal: React.FC = () => { labelStyle={commonLabelStyle} unitStyle={commonUnitStyle} decimals={2} + onClick={handleClick} /> </div> </Flex> diff --git a/src/pages/OverviewHome/index.less b/src/pages/OverviewHome/index.less index 19c378ff1c0937636f84956045241c9720daa7ef..01d65a5d98896b2b65e89e3af61dbc27c62ca8ba 100644 --- a/src/pages/OverviewHome/index.less +++ b/src/pages/OverviewHome/index.less @@ -1,8 +1,6 @@ .container { width: 100%; height: 100%; - // width: 100vw; - // height: 100vh; background-image: url('@/assets/images/newMain/BG.png'); background-size: 100% 100%; box-sizing: border-box; @@ -12,29 +10,11 @@ .content { display: flex; padding: 0px 30px; - // padding: 12px 30px; gap: 30px; - > div:nth-of-type(1) { - width: 1128px; - } - .mapContainer { - flex: 1; - height: 100%; - margin-top: 20px; - } - // > div:nth-of-type(2) { - // width: 2235px; - // height: 100%; - // border-radius: 50px; - // background-image: url("@/assets/images/common/pageBg.png"); - // background-size: 100% 100%; - // overflow: hidden; - // } - - > div:nth-of-type(3) { - width: 1128px; + width: calc(100% - 2316px); + height: 936px; } } } diff --git a/src/pages/SecurityServiceOverview/components/MapCantainer/DistrictMap/index.less b/src/pages/SecurityServiceOverview/components/MapCantainer/DistrictMap/index.less index 29905e4f2c6829a9502f781e245b6780c3fae8aa..02da3b49224c96cad955a622fd929b427083c6b7 100644 --- a/src/pages/SecurityServiceOverview/components/MapCantainer/DistrictMap/index.less +++ b/src/pages/SecurityServiceOverview/components/MapCantainer/DistrictMap/index.less @@ -1,9 +1,8 @@ .container { - background-color: #005a8f; position: relative; - background-size: 100% 100%; overflow: hidden; - height: 936px; + width: 100%; + height: 100%; border-radius: 20px; } diff --git a/src/pages/SecurityServiceOverview/components/MapCantainer/DistrictMap/index.tsx b/src/pages/SecurityServiceOverview/components/MapCantainer/DistrictMap/index.tsx index f2b9c803bad72c9d8e6b23e5c4b7db7a4041703d..97b7674895ce177ffb30503af7750f4ebd834702 100644 --- a/src/pages/SecurityServiceOverview/components/MapCantainer/DistrictMap/index.tsx +++ b/src/pages/SecurityServiceOverview/components/MapCantainer/DistrictMap/index.tsx @@ -132,7 +132,6 @@ const DistrictMap: React.FC = () => { const viewBoxH = eventHtmlRef.current?.clientHeight; const childrenMaxH = (eventHtmlRef.current?.firstChild as HTMLImageElement) ?.clientHeight; - console.log(viewBoxH, childrenMaxH); // 进度条速度 const speed = 30; @@ -297,18 +296,21 @@ const DistrictMap: React.FC = () => { <div className={styles.eventWarp}> <div className={styles.title}>最新事件</div> - <div className={styles.listWarp} ref={eventHtmlRef}> + <div + className={styles.listWarp} + ref={eventHtmlRef} + onMouseMove={() => { + setPlayingStatus(false); + }} + onMouseLeave={() => { + setPlayingStatus(true); + }} + > {eventData?.map((item, index) => { return ( <div key={'event_' + item?.eventId} className={styles.items} - onMouseMove={() => { - setPlayingStatus(false); - }} - onMouseLeave={() => { - setPlayingStatus(true); - }} onClick={() => { dispatch.push('EventDetail', { title: '事件详情', diff --git a/src/pages/SecurityServiceOverview/components/MapCantainer/index.less b/src/pages/SecurityServiceOverview/components/MapCantainer/index.less index ee20fa222f4e88f0e1e000d4efa304ef91d33a9c..cf09ad65ef2e1812fc1a2fd05bce01f6658aad7a 100644 --- a/src/pages/SecurityServiceOverview/components/MapCantainer/index.less +++ b/src/pages/SecurityServiceOverview/components/MapCantainer/index.less @@ -20,6 +20,6 @@ } .mapContent { width: 100%; - height: 936px; + height: 100%; } } diff --git a/src/utils/loginUtil/SSO.ts b/src/utils/loginUtil/SSO.ts index 3b6595cc79d2e3a9efa41c9b453cbfd6b5b76950..13576d854696609e42159c11b2fc2f002ac67da4 100644 --- a/src/utils/loginUtil/SSO.ts +++ b/src/utils/loginUtil/SSO.ts @@ -124,12 +124,15 @@ export const checkBeforeLogin = async ( Request = getUrlParams(); console.log('Request', Request); const code = Request['code']; + console.log('code', code); // 如果没有token 和 code 就去登录 - if (!token && !code) { + if (token && !code) { sessionStorage.clear(); + console.log('getSSOUrl', getSSOUrl()); window.location.replace(getSSOUrl()); return; } + console.log('token', token); // 如果有code就去换token if (!token && code) { const authToken = await getTokenByUrlCode(code); @@ -138,5 +141,6 @@ export const checkBeforeLogin = async ( location.href = window.location.origin + INDEX_ROUTE; } } + console.log('cb'); cb(); };