diff --git a/src/hooks/useGenericData.ts b/src/hooks/useGenericData.ts new file mode 100644 index 0000000000000000000000000000000000000000..929391f168ab76432b513f5dbddc88113aec6cae --- /dev/null +++ b/src/hooks/useGenericData.ts @@ -0,0 +1,156 @@ +import { useState, useEffect } from 'react'; +import { message } from 'antd'; +import { getGenericDataPage, createGenericData, updateGenericData, deleteGenericData } from '@/services/GenericData'; + +export interface UseGenericDataOptions { + module: string; + type: string; + defaultParams?: Record; + transform?: (data: any) => any; + onError?: (error: any) => void; +} + +export function useGenericData(options: UseGenericDataOptions) { + const { module, type, defaultParams = {}, transform, onError } = options; + + const [loading, setLoading] = useState(false); + const [dataSource, setDataSource] = useState([]); + const [total, setTotal] = useState(0); + const [currentPage, setCurrentPage] = useState(1); + const [pageSize, setPageSize] = useState(10); + + const fetchData = async (params: any = {}) => { + // console.log('Fetching data with params:', params); + setLoading(true); + try { + const response = await getGenericDataPage(module, type, { + page: params.page || currentPage, + size: params.size || pageSize, + ...defaultParams, + ...params + }); + + // console.log('API Response:', response); + + if (response.success) { + const { items, total } = response.data; + const itemsArray = Array.isArray(items) ? items : []; + // console.log('Raw items:', itemsArray); + + const transformedData = itemsArray.map(item => ({ + ...item.data, + _docId: item.id + })); + + console.log('Transformed data:', transformedData); + + setDataSource(transformedData); + // console.log('DataSource after setState:', transformedData); + setTotal(total); + } + } catch (error) { + console.error('获取数据失败:', error); + message.error('获取数据失败'); + onError?.(error); + } finally { + setLoading(false); + } + }; + + const handleUpdate = async (record: any) => { + // console.log('Updating record:', record); + try { + const docId = record._docId; + if (!docId) { + message.error('更新失败:找不到对应的记录'); + return; + } + const response = await updateGenericData(module, type, docId, record); + if (response.success) { + message.success('更新成功'); + // 立即重新获取数据 + await fetchData(); + // console.log('Data refreshed after update'); + } + } catch (error) { + console.error('更新失败:', error); + message.error('更新失败'); + onError?.(error); + } + }; + + const handleDelete = async (id: string) => { + // console.log('Deleting record:', id); + // console.log('dataSource', dataSource); + try { + // const record = dataSource.find(item => item.id?.toString() === id?.toString()); + // // const record = dataSource.find(item => item.id.toString() === id); + // console.log('Found record to delete:', record); + + // if (!record?._docId) { + // message.error('删除失败:找不到对应的记录'); + // return; + // } + const response = await deleteGenericData(module, type, id); + if (response.success) { + message.success('删除成功'); + // 立即重新获取数据 + await fetchData(); + // console.log('Data refreshed after delete'); + } + } catch (error) { + console.error('删除失败:', error); + message.error('删除失败'); + onError?.(error); + } + }; + + const handleAdd = async (data: any) => { + // console.log('Adding new record:', data); + try { + const response = await createGenericData(module, type, data); + if (response.success) { + message.success('添加成功'); + // 立即重新获取数据 + await fetchData(); + // console.log('Data refreshed after add'); + } + } catch (error) { + console.error('添加失败:', error); + message.error('添加失败'); + onError?.(error); + } + }; + + const checkDataExists = async () => { + try { + const response = await getGenericDataPage(module, type, { + page: 1, + size: 1 + }); + return response.data.total > 0; + } catch (error) { + return false; + } + }; + + // 添加一个effect来监听dataSource的变化 + // useEffect(() => { + // console.log('DataSource changed:', dataSource); + // }, [dataSource]); + + return { + loading, + dataSource, + total, + currentPage, + pageSize, + setCurrentPage, + setPageSize, + fetchData, + handleAdd, + handleUpdate, + handleDelete, + checkDataExists + }; +} \ No newline at end of file diff --git a/src/pages/SolidWaste/components/CleanRangeModal/components/Cleanliness/index.tsx b/src/pages/SolidWaste/components/CleanRangeModal/components/Cleanliness/index.tsx index 392ef880639a0c5b4134714ca60d1bcf04f06d8b..73df3f45ab80b141ef4c03ecc0a8b9328161e0d4 100644 --- a/src/pages/SolidWaste/components/CleanRangeModal/components/Cleanliness/index.tsx +++ b/src/pages/SolidWaste/components/CleanRangeModal/components/Cleanliness/index.tsx @@ -3,29 +3,21 @@ import styles from "./index.less"; import { Circle } from "rc-progress"; import { Flex } from "antd"; -const Cleanliness: React.FC = () => { - const data = [ - { - name: "一级道路", - value: 18, - total: 22, - }, - { - name: "二级道路", - value: 18, - total: 22, - }, - { - name: "三级道路", - value: 18, - total: 22, - }, - { - name: "四级道路", - value: 18, - total: 22, - }, - ]; +interface CleanlinessProps { + data: { + roadCount: number; // 道路条数 + shouldSweepCount: number; // 应清扫遍数 + sweptCount: number; // 今日已清扫遍数 + roads: Array<{ + name: string; + value: number; + total: number; + }>; + }; +} + +const Cleanliness: React.FC = ({ data }) => { + console.log(data); return (
@@ -33,7 +25,7 @@ const Cleanliness: React.FC = () => {
道路条数
- 22条 + {data.roadCount}
@@ -41,7 +33,7 @@ const Cleanliness: React.FC = () => {
应清扫遍数
- 22遍 + {data.shouldSweepCount}
@@ -49,14 +41,14 @@ const Cleanliness: React.FC = () => {
今日已清扫遍数
- 22遍 + {data.sweptCount}
各级道路清扫遍数
- {data.map((item, index) => { + {data.roads.map((item, index) => { return (
diff --git a/src/pages/SolidWaste/components/CleanRangeModal/components/TodayEvent/index.tsx b/src/pages/SolidWaste/components/CleanRangeModal/components/TodayEvent/index.tsx index 9b4b4522513be17d0982ed8a6b9b1ddb993d042d..bf7f4db4761c018da8c2cb3e1c6fd48874088136 100644 --- a/src/pages/SolidWaste/components/CleanRangeModal/components/TodayEvent/index.tsx +++ b/src/pages/SolidWaste/components/CleanRangeModal/components/TodayEvent/index.tsx @@ -3,13 +3,20 @@ import styles from "./index.less"; import { Flex, Image, Space } from "antd"; import { ClockCircleFilled, EnvironmentFilled } from "@ant-design/icons"; -const TodayEvent: React.FC = () => { - const eventList = [...Array(6)].map(() => ({ - title: "这里是清扫保洁事件类型", - time: "2024-10-20 10:20:20", - address: "天府新区华阳街道水杉街151号", - })); +interface TodayEventProps { + data: { + reported: number; // 上报数量 + pending: number; // 待处置数量 + events: Array<{ + title: string; + time: string; + address: string; + image: string; // 事件图片URL + }>; + }; +} +const TodayEvent: React.FC = ({ data }) => { return (
@@ -17,7 +24,7 @@ const TodayEvent: React.FC = () => {
上报
- 22条 + {data.reported}
@@ -25,14 +32,14 @@ const TodayEvent: React.FC = () => {
待处置
- 22遍 + {data.pending}
最新事件
- {eventList.map((item, index) => { + {data.events.map((item, index) => { return (
@@ -40,8 +47,8 @@ const TodayEvent: React.FC = () => { width={86} height={86} preview={false} - src="error" - fallback={require("@/assets/images/common/imgEmpty.png")} + src={item.image} + fallback="https://example.com/fallback-image.jpg" // 替换为实际的fallback图片URL >
{item.title}
diff --git a/src/pages/SolidWaste/components/CleanRangeModal/index.tsx b/src/pages/SolidWaste/components/CleanRangeModal/index.tsx index 918a16ae984db8a916ae6470f2bd26cff4f47385..8608d2fd6b9fb4f0e13b824369d5a386df9a1a5e 100644 --- a/src/pages/SolidWaste/components/CleanRangeModal/index.tsx +++ b/src/pages/SolidWaste/components/CleanRangeModal/index.tsx @@ -1,125 +1,129 @@ -import React, { - CSSProperties, - forwardRef, - PropsWithChildren, - Ref, - useImperativeHandle, -} from "react"; -import styles from "./index.less"; -import BaseModal from "@/components/BaseModal"; -import { Flex, Space } from "antd"; -import classNames from "classnames"; -import BaseDesc from "@/components/BaseDesc"; -import { useBoolean } from "ahooks"; -import Cleanliness from "./components/Cleanliness"; -import TodayEvent from "./components/TodayEvent"; - -interface CardProps { - title: string; - w: number; - h: number; - style?: CSSProperties; - className?: string; -} -const Card: React.FC> = (props) => { - const { title, children, w, h, style, className } = props; - return ( -
-
{title}
-
{children}
-
- ); -}; - -export type CleanRangeModalMethod = { - show: () => void; - hide: () => void; -}; -const CleanRangeModal = ({}, ref: Ref) => { - const [visible, action] = useBoolean(false); - - useImperativeHandle(ref, () => { - return { - show: action.setTrue, - hide: action.setFalse, + // Start of Selection + import React, { + CSSProperties, + forwardRef, + PropsWithChildren, + Ref, + useImperativeHandle, + } from "react"; + import styles from "./index.less"; + import BaseModal from "@/components/BaseModal"; + import { Flex, Space } from "antd"; + import classNames from "classnames"; + import BaseDesc from "@/components/BaseDesc"; + import { useBoolean } from "ahooks"; + import Cleanliness from "./components/Cleanliness"; + import TodayEvent from "./components/TodayEvent"; + import { useGenericData } from '@/hooks/useGenericData'; + + interface CardProps { + title: string; + w: number; + h: number; + style?: CSSProperties; + className?: string; + } + const Card: React.FC> = (props) => { + const { title, children, w, h, style, className } = props; + return ( +
+
{title}
+
{children}
+
+ ); }; - }); - return ( -
- -
- -
- - - -
- -
-
- -
-
-
- - -
- -
-
- -
-
- -
-
+ + export type CleanRangeModalMethod = { + show: () => void; + hide: () => void; + }; + + interface CleanRangeModalProps { + data?: any; + } + + const CleanRangeModal = forwardRef(({ data }, ref) => { + const [visible, action] = useBoolean(false); + + useImperativeHandle(ref, () => ({ + show: action.setTrue, + hide: action.setFalse, + })); + + return ( + +
+ +
+ + + +
+ +
+
+ +
+
+
+ + +
+ +
+
+ +
+
+ +
+
+
+
+ + - - - +
+ + -
- - - -
-
- -
- ); -}; - -export default forwardRef(CleanRangeModal); + +
+ + ); + }); + + export default CleanRangeModal; diff --git a/src/pages/SolidWaste/components/DomainEventSituationDistribution/index.tsx b/src/pages/SolidWaste/components/DomainEventSituationDistribution/index.tsx index adb2bbe77d932c27a5c3745b361d9fb22a4533ab..177db645267a046f0272ba6721e08b6d2fbded96 100644 --- a/src/pages/SolidWaste/components/DomainEventSituationDistribution/index.tsx +++ b/src/pages/SolidWaste/components/DomainEventSituationDistribution/index.tsx @@ -9,18 +9,28 @@ import RefuseDisposalModal from "../RefuseDisposalModal"; import PantryRubbishModal from "../PantryRubbishModal"; import RaiseDustModal from "../RaiseDustModal"; +interface DomainEventSituationDistributionProps { + data?: any; + loading?: boolean; +} + /** @name 领域事件态势分布 */ -const DomainEventSituationDistribution: React.FC = () => { +const DomainEventSituationDistribution: React.FC = ({ + data, + loading +}) => { const [curLocation, setCurLocation] = useState<"today">("today"); const CleanRef = useRef(null); const disposalRef = useRef(null); const antryRubbishRef = useRef(null); - const raiseDustRef= useRef(null); + const raiseDustRef = useRef(null); + + // 菜单配置 const menu = [ { name: "清扫保洁", - value: 986, + value: data?.cleanSweep?.count || 0, icon: require("@/assets/images/solidWaste/qingshao.png"), onClick: () => { CleanRef.current?.show(); @@ -28,7 +38,7 @@ const DomainEventSituationDistribution: React.FC = () => { }, { name: "垃圾处置", - value: 986, + value: data?.refuseDisposal?.count || 0, icon: require("@/assets/images/solidWaste/lajichuzhi.png"), onClick: () => { disposalRef.current?.show(); @@ -36,7 +46,7 @@ const DomainEventSituationDistribution: React.FC = () => { }, { name: "餐厨垃圾", - value: 986, + value: data?.kitchenWaste?.count || 0, icon: require("@/assets/images/solidWaste/canculaji.png"), onClick: () => { antryRubbishRef.current?.show(); @@ -44,7 +54,7 @@ const DomainEventSituationDistribution: React.FC = () => { }, { name: "扬尘监管", - value: 986, + value: data?.dustControl?.count || 0, icon: require("@/assets/images/solidWaste/yangchenjianguan.png"), onClick: () => { raiseDustRef.current?.show(); @@ -54,10 +64,11 @@ const DomainEventSituationDistribution: React.FC = () => { return (
- - - - + + + + +
领域事件态势分布
@@ -72,29 +83,26 @@ const DomainEventSituationDistribution: React.FC = () => {
+ - {menu.map((item, index) => { - return ( -
{ - item.onClick ? item.onClick() : message.warning("页面待开发"); - }} - > -
- -
{item.value}
-
-
-
{item.name}
-
- -
+ {menu.map((item, index) => ( +
+
+ +
{item.value}
+
+
+
{item.name}
+
+
- ); - })} +
+ ))}
); diff --git a/src/pages/SolidWaste/components/PantryRubbishModal/index.tsx b/src/pages/SolidWaste/components/PantryRubbishModal/index.tsx index 85c397919111b2c984dcf6a96fa70ab9e6824e68..81ceafedc5b10f68194583562c8c708f1de0919a 100644 --- a/src/pages/SolidWaste/components/PantryRubbishModal/index.tsx +++ b/src/pages/SolidWaste/components/PantryRubbishModal/index.tsx @@ -1,11 +1,4 @@ -import React, { - CSSProperties, - forwardRef, - PropsWithChildren, - Ref, - useImperativeHandle, - useMemo, -} from "react"; +import React, { forwardRef, Ref, useImperativeHandle } from "react"; import styles from "./index.less"; import BaseModal from "@/components/BaseModal"; import { Flex, Space } from "antd"; @@ -14,15 +7,16 @@ import { useBoolean } from "ahooks"; import TodayEvent from "../CleanRangeModal/components/TodayEvent"; import PieChart from "@/components/PieChart"; - interface CardProps { - title: string; + title: React.ReactNode; w: number; h: number; - style?: CSSProperties; + style?: React.CSSProperties; className?: string; + children?: React.ReactNode; } -const Card: React.FC> = (props) => { + +const Card: React.FC = (props) => { const { title, children, w, h, style, className } = props; return (
void; hide: () => void; }; -const PantryRubbishModal = ({}, ref: Ref) => { + +interface PantryRubbishModalProps { + data?: any; +} + +const PantryRubbishModal = forwardRef(({ data }, ref) => { const [visible, action] = useBoolean(false); - useImperativeHandle(ref, () => { - return { - show: action.setTrue, - hide: action.setFalse, - }; - }); + useImperativeHandle(ref, () => ({ + show: action.setTrue, + hide: action.setFalse, + })); + return (
) => { onCancel={action.setFalse} width={1524} > -
- -
- - 昨日生活垃圾末端处置量 - - 6 - - +
+ +
+ + 昨日生活垃圾末端处置量 + + {data?.facilitiesCount || 0} + + +
+ } + w={881} + h={389} + > + {/* ... 处置设施信息展示 */} +
+ +
+
+ {data?.yesterdayInfo1?.name}
- } - w={881} - h={389} - > -
- -
-
- 中心城区餐厨垃圾无害化处理项目一期 -
-
- 长安垃圾填埋场位于成都市龙泉区洛带镇万兴乡,全称为成都市固体废弃物卫生处置场。1992年12月建成,1993年正式投入使用。是成都市生活垃圾处理的主要场所。 -
+
+ {data?.yesterdayInfo1?.description}
-
- -
-
- 中心城区餐厨垃圾无害化处理项目一期 -
-
- 长安垃圾填埋场位于成都市龙泉区洛带镇万兴乡,全称为成都市固体废弃物卫生处置场。1992年12月建成,1993年正式投入使用。是成都市生活垃圾处理的主要场所。 -
+
+ +
+ +
+
+ {data?.yesterdayInfo2?.name} +
+
+ {data?.yesterdayInfo2?.description}
- - - - -
- - +
- + + + +
+ + + +
); -}; +}); -export default forwardRef(PantryRubbishModal); +export default PantryRubbishModal; diff --git a/src/pages/SolidWaste/components/ProblemOverview/index.tsx b/src/pages/SolidWaste/components/ProblemOverview/index.tsx index 991b04c20c9b19b9deea8bcf6beb0ffb7f4cff14..4a2fd2a761a2fa591d73165b2be711c1e8c790bc 100644 --- a/src/pages/SolidWaste/components/ProblemOverview/index.tsx +++ b/src/pages/SolidWaste/components/ProblemOverview/index.tsx @@ -1,16 +1,40 @@ -import React, { useState } from "react"; +import React, { useState, useMemo } from "react"; import styles from "./index.less"; import { Flex, Space } from "antd"; import classNames from "classnames"; - import BaseDesc from "@/components/BaseDesc"; import ReactECharts from "echarts-for-react"; import { lineOption } from "./option"; +import { cloneDeep } from 'lodash'; + +interface ProblemOverviewProps { + data?: any; + loading?: boolean; +} /** @name 问题概况 */ -const ProblemOverview: React.FC = () => { +const ProblemOverview: React.FC = ({ data, loading }) => { const [curLocation, setCurLocation] = useState<"today">("today"); + const newLineOption = useMemo(() => { + console.log('Current problemData:', data); + + if (!data?.trend) { + return lineOption; + } + + const trendData = data.trend; + const temp = cloneDeep(lineOption); + + // 设置x轴数据 + (temp.xAxis as any)[0].data = trendData.map((item: any) => item.date); + + // 设置折线数据 + (temp.series as any)[0].data = trendData.map((item: any) => item.value); + + return temp; + }, [data]); + return (
@@ -30,34 +54,35 @@ const ProblemOverview: React.FC = () => {
+ />
+ />
+ />
+ // loading={loading} + />
); diff --git a/src/pages/SolidWaste/components/RaiseDustModal/index.tsx b/src/pages/SolidWaste/components/RaiseDustModal/index.tsx index f8961dd8cb7278f4314daab379623ed44d9a1146..47da348e34529eff810d46174f7846d3d294bdfe 100644 --- a/src/pages/SolidWaste/components/RaiseDustModal/index.tsx +++ b/src/pages/SolidWaste/components/RaiseDustModal/index.tsx @@ -1,27 +1,20 @@ -import React, { - CSSProperties, - forwardRef, - PropsWithChildren, - Ref, - useImperativeHandle, - useMemo, -} from "react"; +import React, { forwardRef, Ref, useImperativeHandle } from "react"; import styles from "./index.less"; import BaseModal from "@/components/BaseModal"; -import { Flex, Space } from "antd"; +import { Flex, Space, Descriptions } from "antd"; import classNames from "classnames"; import { useBoolean } from "ahooks"; -import { Descriptions, Divider } from "antd/es"; - interface CardProps { - title: string; + title: string | React.ReactNode; w: number; h: number; - style?: CSSProperties; + style?: React.CSSProperties; className?: string; + children: React.ReactNode; } -const Card: React.FC> = (props) => { + +const Card: React.FC = (props) => { const { title, children, w, h, style, className } = props; return (
void; hide: () => void; }; -const RaiseDustModal = ({}, ref: Ref) => { + +interface RaiseDustModalProps { + data?: any; +} + +const RaiseDustModal = forwardRef(({ data }, ref) => { const [visible, action] = useBoolean(false); - useImperativeHandle(ref, () => { - return { - show: action.setTrue, - hide: action.setFalse, - }; - }); + useImperativeHandle(ref, () => ({ + show: action.setTrue, + hide: action.setFalse, + })); + return (
) => { onCancel={action.setFalse} width={1524} > -
- -
- -
-
-
- 成都市 - - 实时空气质量指数(AQI) - -
-
- 41 - -
+
+ +
+ +
+
+
+ {data?.cityName || '成都市'} + + 实时空气质量指数(AQI) +
+
+ {data?.aqi || 0} + {data?.aqiLevel || '优'} +
+
-
-
主要污染物
-
-
-
- 22 - mg/3 -
-
PM2.5
-
-
+
+
主要污染物
+
+ {data?.pollutants?.map((item: any, index: number) => ( +
- 22 - mg/3 + {item.value} + {item.unit}
-
PM2.5
+
{item.name}
-
+ ))}
- - - 排放监管情况 - 近一周 -
- } - style={{ marginTop: 20 }} - w={879} - h={560} - > -
- {Array.from({ length: 40 }).map((item, index) => { - return ( -
- 1 -
频繁告警工地
-
- ); - })} -
- -
- -
- -
- 成都市轨道交能13号线一期公园大道站项目 -
-
- +
+ + + 排放监管情况 + 近一周
+ } + style={{ marginTop: 20 }} + w={879} + h={560} + > +
+ {(data?.dischargeStats || []).map((item: any, index: number) => ( +
+ {item.value} +
{item.name}
+
+ ))}
- +
+ +
+ +
+ {data?.keyArea?.name || '成都市轨道交能13号线一期公园大道站项目'} +
+
+ +
+
+
+
); -}; +}); -export default forwardRef(RaiseDustModal); +export default RaiseDustModal; diff --git a/src/pages/SolidWaste/components/RefuseDisposalModal/index.tsx b/src/pages/SolidWaste/components/RefuseDisposalModal/index.tsx index f55308a789c8140973e046917542a638c66cf083..4a863980290c88cd19d666b851f0703f31221069 100644 --- a/src/pages/SolidWaste/components/RefuseDisposalModal/index.tsx +++ b/src/pages/SolidWaste/components/RefuseDisposalModal/index.tsx @@ -1,11 +1,4 @@ -import React, { - CSSProperties, - forwardRef, - PropsWithChildren, - Ref, - useImperativeHandle, - useMemo, -} from "react"; +import React, { CSSProperties, forwardRef, Ref, useImperativeHandle, useMemo } from "react"; import styles from "./index.less"; import BaseModal from "@/components/BaseModal"; import { Flex, Space } from "antd"; @@ -14,16 +7,19 @@ import { useBoolean } from "ahooks"; import TodayEvent from "../CleanRangeModal/components/TodayEvent"; import PieChart from "@/components/PieChart"; import ReactECharts from "echarts-for-react"; -import { getColorByIndex } from "@/utils/ui"; -import { gaugeOption, barOption } from "./option"; +import { barOption } from "./option"; +import { cloneDeep } from "lodash"; + interface CardProps { title: string; w: number; h: number; style?: CSSProperties; className?: string; + children: React.ReactNode; } -const Card: React.FC> = (props) => { + +const Card: React.FC = (props) => { const { title, children, w, h, style, className } = props; return (
void; hide: () => void; }; -const RefuseDisposalModal = ({}, ref: Ref) => { + +interface RefuseDisposalModalProps { + data?: any; +} + +const RefuseDisposalModal = forwardRef(({ data }, ref) => { const [visible, action] = useBoolean(false); - const dataSource = [...Array(20)].map((_, i) => { - return { - value: Math.floor(Math.random() * 100), - name: "xx区" + i, - }; - }); + + useImperativeHandle(ref, () => ({ + show: action.setTrue, + hide: action.setFalse, + })); const newBarOption = useMemo(() => { - // expensive calculation - const xAxisData = dataSource.map((item) => item.name); - const seriesData = dataSource.map((item) => ({ - ...item, - + if (!data?.incinerationData) return barOption; + + const xAxisData = data.incinerationData.map((item: any) => item.name); + const seriesData = data.incinerationData.map((item: any) => ({ + value: item.value, + name: item.name })); - (barOption.series as echarts.SeriesOption[])[0].data = seriesData; - (barOption.xAxis as any[])[0].data = xAxisData; - return barOption; - }, []); - useImperativeHandle(ref, () => { - return { - show: action.setTrue, - hide: action.setFalse, - }; - }); + + const temp = cloneDeep(barOption); + (temp.series as any)[0].data = seriesData; + (temp.xAxis as any)[0].data = xAxisData; + return temp; + }, [data]); + return (
) => { onCancel={action.setFalse} width={1524} > -
- -
- - - + +
+ + + - - -
- + }, + }} + style={{ width: "100%" }} + chartStyle={{ width: 118, height: 114 }} + vertical + labelClassName={styles.labelClassName} + data={[ + { + name: "填埋量", + value: data?.landfillAmount || 0, + percent: data?.landfillPercent || "0", + type: 1, + }, + { + name: "焚烧量", + value: data?.incinerationAmount || 0, + percent: data?.incinerationPercent || "0", + type: 2, + }, + ]} + /> + + + {/* ... 填埋场信息展示 */} +
+
- 长安垃圾填埋场位于成都市龙泉区洛带镇万兴乡,全称为成都市固体废弃物卫生处置场。1992年12月建成,1993年正式投入使用。是成都市生活垃圾处理的主要场所。 + {data?.landfillInfo?.description}
@@ -125,26 +124,27 @@ const RefuseDisposalModal = ({}, ref: Ref) => {
昨日生活垃圾填埋量
- 22吨 + {data?.landfillInfo?.dailyAmount || 0}
-
- - -
-
+ + + +
+ {/* ... 焚烧厂信息展示 */} +
生活垃圾焚烧发电厂
- 22个 + {data?.factoryAmount || 0}
@@ -153,7 +153,7 @@ const RefuseDisposalModal = ({}, ref: Ref) => {
昨日焚烧量
- 22吨 + {data?.yesterdayBurnAmount || 0}
@@ -168,21 +168,21 @@ const RefuseDisposalModal = ({}, ref: Ref) => { 生活垃圾焚烧分厂处置量
- -
- -
- - + +
-
+
+ + + +
); -}; +}); -export default forwardRef(RefuseDisposalModal); +export default RefuseDisposalModal; diff --git a/src/pages/SolidWaste/components/SituationOverview/index.tsx b/src/pages/SolidWaste/components/SituationOverview/index.tsx index 06f1da021871982b93486c1179334c36ad36b406..70e66d7c01fa80046622b75d867dab36dacf870c 100644 --- a/src/pages/SolidWaste/components/SituationOverview/index.tsx +++ b/src/pages/SolidWaste/components/SituationOverview/index.tsx @@ -1,4 +1,4 @@ -import { useEffect, useMemo, useState } from "react"; +import { useEffect, useMemo } from "react"; import ReactECharts from "echarts-for-react"; import * as echarts from "echarts"; @@ -6,68 +6,82 @@ import styles from "./index.less"; import { Flex } from "antd"; import { gaugeOption, barOption } from "./option"; import { getColorByIndex } from "@/utils/ui"; -import services from "@/services"; +import { useGenericData } from '@/hooks/useGenericData'; +import { initializeGenericData } from '@/services/GenericData'; +import { solidWasteMockData } from '../../mockData'; import { cloneDeep } from "lodash"; -/** @name 成都市环卫固废态势总览 */ -const SituationOverview = () => { - const [cqiDataSource, setCQIDataSource] = useState(); +interface SituationOverviewProps { + data?: any; + loading?: boolean; +} - const [areaDataSource, setAreaDataSource] = useState([]); +/** @name 成都市环卫固废态势总览 */ +const SituationOverview: React.FC = ({ data, loading }) => { + // 使用通用数据服务 + const { + dataSource, + fetchData + } = useGenericData({ + module: 'solid-waste', + type: 'overview', + onError: (error) => { + console.error('获取数据失败:', error); + } + }); + // 初始化数据 useEffect(() => { - services.overall - .getComparisonIndexInstance({ - physicalSignType: 1, - indexType: 0, - indexHierarchy: 2, - objectId: 1, - indexId: 3, - }) - .then((res) => { - if (res.code === 200) { - setCQIDataSource(res.data); + const initData = async () => { + try { + // 检查是否已有数据 + const response = await fetchData(); + if (!(response as any)?.data?.items?.length) { + // 如果没有数据,则初始化 + await initializeGenericData('solid-waste', 'overview', solidWasteMockData as any); + fetchData(); } - }); - - services.overall.getSolidWasteAreaIndex().then((res) => { - if (res.code === 200) { - setAreaDataSource(res.data); + } catch (error) { + console.error('初始化数据失败:', error); } - }); + }; + initData(); }, []); + // 从dataSource中获取数据 - 注意这里的数据结构 + const situationData = (dataSource as any)?.[0]?.situationOverview; + const newGaugeOption = useMemo(() => { - const value = cqiDataSource?.currentIndex?.cqi ?? 0; + if (!situationData) return gaugeOption; + + const value = situationData.currentIndex?.cqi ?? 0; const temp = cloneDeep(gaugeOption) as any; - temp.series[0].data[0].value = Number(value); return temp; - }, [cqiDataSource]); + }, [situationData]); const newBarOption = useMemo(() => { - const xAxisData = areaDataSource.map((item) => item.objectName); - const seriesData = areaDataSource.map((item) => ({ + const areaData = situationData?.areaIndexes || []; + const xAxisData = areaData.map((item: any) => item.objectName); + const seriesData = areaData.map((item: any) => ({ value: Number(item.cqi), name: item.objectName, itemStyle: { - color: getColorByIndex(Number(item.cqi)), - }, + color: getColorByIndex(Number(item.cqi)) + } })); const temp = cloneDeep(barOption); - (temp.series as echarts.SeriesOption[])[0].data = seriesData; (temp.xAxis as any[])[0].data = xAxisData; - // console.log("temp", temp); return temp; - }, [areaDataSource]); + }, [situationData]); return (
成都市环卫固废态势总览
- 更新时间 {cqiDataSource?.currentIndex?.time} + 更新时间 {situationData?.currentIndex?.time}
@@ -76,7 +90,7 @@ const SituationOverview = () => { option={newGaugeOption} />
- {cqiDataSource?.currentIndex.status} + {situationData?.currentIndex.status}
环卫固废今日体征指数
diff --git a/src/pages/SolidWaste/index.tsx b/src/pages/SolidWaste/index.tsx index 3a7faf75e9be90842777efeaaf33a0d2d8776c83..8aa9647045fb183fd5dec69dad736a73c4cff562 100644 --- a/src/pages/SolidWaste/index.tsx +++ b/src/pages/SolidWaste/index.tsx @@ -1,16 +1,54 @@ -import React, { useMemo } from "react"; +import React, { useEffect } from "react"; import styles from "./index.less"; import SituationOverview from "./components/SituationOverview"; import ProblemOverview from "./components/ProblemOverview"; import DomainEventSituationDistribution from "./components/DomainEventSituationDistribution"; +import { useGenericData } from '@/hooks/useGenericData'; +import { initializeGenericData } from '@/services/GenericData'; +import { solidWasteMockData } from './mockData'; /** @name 总览 */ const SolidWaste: React.FC = () => { + const { + dataSource, + fetchData, + loading + } = useGenericData({ + module: 'solid-waste', + type: 'overview', + onError: (error) => { + console.error('获取数据失败:', error); + } + }); + + // 初始化数据 + useEffect(() => { + const initData = async () => { + try { + // 检查是否已有数据 + const response = await fetchData(); + if (!(response as any)?.data?.items?.length) { + // 如果没有数据,则初始化 + await initializeGenericData('solid-waste', 'overview', solidWasteMockData as any); + fetchData(); + } + } catch (error) { + console.error('初始化数据失败:', error); + } + }; + initData(); + }, []); + + // 获取第一条数据 + const data = (dataSource as any)?.[0]; + // console.log(dataSource); + // console.log(data); + return (
- - - + + +
); }; diff --git a/src/pages/SolidWaste/mockData copy.ts b/src/pages/SolidWaste/mockData copy.ts new file mode 100644 index 0000000000000000000000000000000000000000..333a760236628c401c48f949dad5da0bb6e6d3eb --- /dev/null +++ b/src/pages/SolidWaste/mockData copy.ts @@ -0,0 +1,146 @@ +// 环卫固废页面的完整mock数据 +export const solidWasteMockData = { + // 态势总览数据 + situationOverview: { + currentIndex: { + cqi: 95.7, // 当前指数 + time: "2024-01-18 10:00:00", // 更新时间 + status: "优" // 状态 + }, + areaIndexes: [ + { objectName: "锦江区", cqi: 95 }, + { objectName: "青羊区", cqi: 92 }, + { objectName: "金牛区", cqi: 88 }, + { objectName: "武侯区", cqi: 91 }, + { objectName: "成华区", cqi: 89 }, + { objectName: "高新区", cqi: 93 } + ] + }, + + // 问题概况数据 + problemOverview: { + total: 262, // 问题总数 + pending: 22, // 待处置 + rate: 89.2, // 处置率 + trend: [ // 近1月趋势 + { date: "08.15", value: 180 }, + { date: "08.23", value: 200 }, + { date: "09.01", value: 100 }, + { date: "09.07", value: 250 }, + { date: "09.15", value: 300 } + ] + }, + + // 领域事件态势分布 + domainEvents: { + cleanSweep: { + count: 986, + details: { + workers: 22, + vehicles: 22, + cleanArea: { + total: 22, + mechanical: 22, + manual: 22 + }, + // 更新清洁程度数据结构 + cleanliness: { + roadCount: 86, + shouldSweepCount: 120, + sweptCount: 98, + roads: [ + { name: "一级道路", value: 18, total: 22 }, + { name: "二级道路", value: 18, total: 22 }, + { name: "三级道路", value: 18, total: 22 }, + { name: "四级道路", value: 18, total: 22 } + ] + }, + // 更新今日事件数据结构 + todayEvents: { + reported: 35, + pending: 8, + events: [ + { + title: "这里是清扫保洁事件类型", + time: "2024-10-20 10:20:20", + address: "天府新区华阳街道水杉街151号", + image: "https://example.com/event-image-1.jpg" + }, + // ... 更多事件 + ] + } + } + }, + // 垃圾处置数据 + refuseDisposal: { + count: 756, + details: { + totalDisposal: 316, + landfillAmount: 186, + landfillPercent: "58.9", + incinerationAmount: 130, + incinerationPercent: "41.1", + landfillInfo: { + name: "长安垃圾填埋场", + description: "长安垃圾填埋场位于成都市龙泉区洛带镇万兴乡...", + image: "https://example.com/landfill-image.jpg", + dailyAmount: 22 + }, + incinerationData: [ + { name: "焚烧厂A", value: 45 }, + { name: "焚烧厂B", value: 35 }, + // ... 更多数据 + ] + } + }, + // 餐厨垃圾数据 + kitchenWaste: { + count: 432, + details: { + facilitiesCount: 6, + totalProcessing: 316, + processingData: [ + { + name: "中心城区餐厨垃圾无害化处理项目一期", + value: 38, + percent: "80", + type: 1 + }, + { + name: "中心城区餐厨垃圾无害化处理项目二期", + value: 30, + percent: "80", + type: 2 + } + ] + } + }, + // 扬尘监管数据 + dustControl: { + count: 245, + details: { + cityName: "成都市", + aqi: 41, + aqiLevel: "优", + pollutants: [ + { name: "PM2.5", value: 22, unit: "mg/3" }, + { name: "PM10", value: 22, unit: "mg/3" } + ], + dischargeStats: Array.from({ length: 40 }, (_, i) => ({ + name: "频繁告警工地", + value: Math.floor(Math.random() * 10) + 1 + })), + keyArea: { + name: "成都市轨道交能13号线一期公园大道站项目", + image: "https://example.com/construction-site.jpg", + inspectionTime: "2024-05-28 10:20:20 -2024-05-28 10:20:20", + inspector: "黄林(副主任)", + pm10: 58, + pm25: 58, + aqi: 58, + qualified: true + } + } + } + } +}; \ No newline at end of file diff --git a/src/pages/SolidWaste/mockData.ts b/src/pages/SolidWaste/mockData.ts new file mode 100644 index 0000000000000000000000000000000000000000..333a760236628c401c48f949dad5da0bb6e6d3eb --- /dev/null +++ b/src/pages/SolidWaste/mockData.ts @@ -0,0 +1,146 @@ +// 环卫固废页面的完整mock数据 +export const solidWasteMockData = { + // 态势总览数据 + situationOverview: { + currentIndex: { + cqi: 95.7, // 当前指数 + time: "2024-01-18 10:00:00", // 更新时间 + status: "优" // 状态 + }, + areaIndexes: [ + { objectName: "锦江区", cqi: 95 }, + { objectName: "青羊区", cqi: 92 }, + { objectName: "金牛区", cqi: 88 }, + { objectName: "武侯区", cqi: 91 }, + { objectName: "成华区", cqi: 89 }, + { objectName: "高新区", cqi: 93 } + ] + }, + + // 问题概况数据 + problemOverview: { + total: 262, // 问题总数 + pending: 22, // 待处置 + rate: 89.2, // 处置率 + trend: [ // 近1月趋势 + { date: "08.15", value: 180 }, + { date: "08.23", value: 200 }, + { date: "09.01", value: 100 }, + { date: "09.07", value: 250 }, + { date: "09.15", value: 300 } + ] + }, + + // 领域事件态势分布 + domainEvents: { + cleanSweep: { + count: 986, + details: { + workers: 22, + vehicles: 22, + cleanArea: { + total: 22, + mechanical: 22, + manual: 22 + }, + // 更新清洁程度数据结构 + cleanliness: { + roadCount: 86, + shouldSweepCount: 120, + sweptCount: 98, + roads: [ + { name: "一级道路", value: 18, total: 22 }, + { name: "二级道路", value: 18, total: 22 }, + { name: "三级道路", value: 18, total: 22 }, + { name: "四级道路", value: 18, total: 22 } + ] + }, + // 更新今日事件数据结构 + todayEvents: { + reported: 35, + pending: 8, + events: [ + { + title: "这里是清扫保洁事件类型", + time: "2024-10-20 10:20:20", + address: "天府新区华阳街道水杉街151号", + image: "https://example.com/event-image-1.jpg" + }, + // ... 更多事件 + ] + } + } + }, + // 垃圾处置数据 + refuseDisposal: { + count: 756, + details: { + totalDisposal: 316, + landfillAmount: 186, + landfillPercent: "58.9", + incinerationAmount: 130, + incinerationPercent: "41.1", + landfillInfo: { + name: "长安垃圾填埋场", + description: "长安垃圾填埋场位于成都市龙泉区洛带镇万兴乡...", + image: "https://example.com/landfill-image.jpg", + dailyAmount: 22 + }, + incinerationData: [ + { name: "焚烧厂A", value: 45 }, + { name: "焚烧厂B", value: 35 }, + // ... 更多数据 + ] + } + }, + // 餐厨垃圾数据 + kitchenWaste: { + count: 432, + details: { + facilitiesCount: 6, + totalProcessing: 316, + processingData: [ + { + name: "中心城区餐厨垃圾无害化处理项目一期", + value: 38, + percent: "80", + type: 1 + }, + { + name: "中心城区餐厨垃圾无害化处理项目二期", + value: 30, + percent: "80", + type: 2 + } + ] + } + }, + // 扬尘监管数据 + dustControl: { + count: 245, + details: { + cityName: "成都市", + aqi: 41, + aqiLevel: "优", + pollutants: [ + { name: "PM2.5", value: 22, unit: "mg/3" }, + { name: "PM10", value: 22, unit: "mg/3" } + ], + dischargeStats: Array.from({ length: 40 }, (_, i) => ({ + name: "频繁告警工地", + value: Math.floor(Math.random() * 10) + 1 + })), + keyArea: { + name: "成都市轨道交能13号线一期公园大道站项目", + image: "https://example.com/construction-site.jpg", + inspectionTime: "2024-05-28 10:20:20 -2024-05-28 10:20:20", + inspector: "黄林(副主任)", + pm10: 58, + pm25: 58, + aqi: 58, + qualified: true + } + } + } + } +}; \ No newline at end of file diff --git a/src/services/GenericData.ts b/src/services/GenericData.ts new file mode 100644 index 0000000000000000000000000000000000000000..f6855bdb95e0bb10f4686316f5ec52e1664e2b76 --- /dev/null +++ b/src/services/GenericData.ts @@ -0,0 +1,90 @@ +// import { OptionsDto } from '@/components/TabSwitch'; +import { request } from '@umijs/max'; + +/** + * + * @param url 接口地址 + * @returns 首页体征physicalsignindex + */ +const IS_PROD = process.env.NODE_ENV === 'production' ? true : false; +export const reqBaseUrl = IS_PROD ? '/generic/apis' : '/generic/apis'; +const urlProxyApis = (url: string) => { + return `${reqBaseUrl}${url}`; +}; + +// export async function pagePhysicalSignIndex( +// params: PhysicalsignConfigApi.PagePhysicalSignIndexParams +// ): Promise> { +// const { page, count, hierarchy, indexType } = params; +// // 将 page 和 count 拼接到 URL 中 +// const url = urlProxyApis(`/physicalsignindex/physicalSignIndex/pagePhysicalSignIndex?page=${page}&count=${count}`); +// return request(url, { +// method: 'POST', +// data: { +// hierarchy, +// indexType, +// }, +// }); +// } + +// 通用数据服务API +export async function getGenericDataPage( + module: string, + type: string, + params: PhysicalsignConfigWithGenericDataApi.PageParams +): Promise> { + const { page, size, ...searchParams } = params; + return request(urlProxyApis(`/generic/dataservice/${module}/${type}/page`), { + method: 'POST', + params: { + page, + size + }, + data: searchParams + }); +} + +export async function createGenericData( + module: string, + type: string, + data: any +): Promise> { + return request(urlProxyApis(`/generic/dataservice/${module}/${type}`), { + method: 'POST', + data + }); +} + +export async function updateGenericData( + module: string, + type: string, + id: string, + data: any +): Promise> { + return request(urlProxyApis(`/generic/dataservice/${module}/${type}/${id}`), { + method: 'PUT', + data + }); +} + +export async function deleteGenericData( + module: string, + type: string, + id: string +): Promise> { + return request(urlProxyApis(`/generic/dataservice/${module}/${type}/${id}`), { + method: 'DELETE' + }); +} + +// 添加初始化数据的方法 +export async function initializeGenericData( + module: string, + type: string, + initialData: any[] +): Promise> { + return request(urlProxyApis(`/generic/dataservice/${module}/${type}/init`), { + method: 'POST', + data: initialData + }); +} diff --git a/src/services/core/GenericData.d.ts b/src/services/core/GenericData.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..4bf00ac2b0c750307eb4e91a0599124f3e8516b6 --- /dev/null +++ b/src/services/core/GenericData.d.ts @@ -0,0 +1,31 @@ +declare namespace PhysicalsignConfigWithGenericDataApi { + interface Result { + code: number; + msg: string; + data: { + total: number; + items: T[]; + page: number; + size: number; + }; + success: boolean; + } + + interface GenericDocument { + id: string; + type: string; + module: string; + data: any; + createTime: number; + updateTime: number; + } + + interface PageParams { + page: number; + size: number; + sortField?: string; + sortOrder?: 'asc' | 'desc'; + [key: string]: any; + } +} +