import React, { useCallback, useEffect, useMemo, useState } from 'react';
import DriverBack from '~/pages/Container/Driver/components/DriverBack';
import { tools } from "@cqsjjb/jjb-common-lib";
import EnterpriseTypeChart from './components/EnterpriseTypeChart';
import ProjectTypeChart from './components/ProjectTypeChart';
import ProjectCompletionTable from './components/ProjectCompletionTable';
import './index.css';
import {
STATISTIC_CARDS,
} from './mockData';
import {
fetchProjectNodeStats,
fetchNotices,
fetchIndustryStat,
fetchEvalTypeRatio,
fetchProjectExecution,
} from '~/api/institution';
// ==================== 骨架占位 ====================
function Skeleton({ width = '100%', height = 14, radius = 4, className = '' }) {
return (
);
}
// ==================== 子组件 ====================
function StatusCard({ item, loading }) {
return (
{item.char}
{item.title}
{loading ? : {item.value}}
);
}
function ReminderCard({ item, loading }) {
return (
{item.char}
{item.title}
{loading ? : {item.value}}
);
}
// ==================== 主组件 ====================
export default function InstitutionDashboard() {
const handleReminderClick = useCallback(() => {}, []);
// 各 API 的原始返回数据(null 表示接口未成功,走 mock)
const [loading, setLoading] = useState(true);
const [nodeStatsApi, setNodeStatsApi] = useState(null);
const [noticesApi, setNoticesApi] = useState(null);
const [industryStatApi, setIndustryStatApi] = useState(null);
const [evalTypeRatioApi, setEvalTypeRatioApi] = useState(null);
const [projectExecutionApi, setProjectExecutionApi] = useState(null);
useEffect(() => {
const tasks = [
fetchProjectNodeStats().then(setNodeStatsApi).catch(() => {}),
fetchNotices().then(setNoticesApi).catch(() => {}),
fetchIndustryStat().then(setIndustryStatApi).catch(() => {}),
fetchEvalTypeRatio().then(setEvalTypeRatioApi).catch(() => {}),
fetchProjectExecution().then(setProjectExecutionApi).catch(() => {}),
];
Promise.all(tasks).finally(() => setLoading(false));
}, []);
// 衍生展示数据:始终渲染固定卡片集合(8 个节点 + 已归档 + 项目延期),
// 仅用 API 数据覆盖对应数值,保证无论接口返回多少节点,卡片项数都不减少。
const statusCards = useMemo(() => {
if (!nodeStatsApi) return STATISTIC_CARDS;
const { nodeStats = [], archivedProjectCount = 0, delayedProjectCount = 0 } = nodeStatsApi || {};
const nodeByName = new Map();
(nodeStats || []).forEach((n) => {
if (n && n.nodeName) nodeByName.set(n.nodeName, n);
});
return STATISTIC_CARDS.map((card) => {
let value = card.value;
if (card.key === 'archived') {
value = Number(archivedProjectCount) || 0;
} else if (card.key === 'delayed') {
value = Number(delayedProjectCount) || 0;
} else {
const node = nodeByName.get(card.title);
if (node) value = Number(node.pendingCount) || 0;
}
return { ...card, value };
});
}, [nodeStatsApi]);
const projectSummary = useMemo(() => {
if (!nodeStatsApi) return { total: 0, statutory: 0 };
return {
total: Number(nodeStatsApi.totalProjects) || 0,
statutory: Number(nodeStatsApi.statutoryProjects) || 0,
};
}, [nodeStatsApi]);
const alertItems = useMemo(() => {
if (!noticesApi) {
return [
{ key: 'qualCheck', title: '资质现场审查通知', value: 0, char: '审', colorClass: 'yellow' },
{ key: 'supervisionCheck', title: '监督检查通知', value: 0, char: '检', colorClass: 'red' },
{ key: 'unreadNotice', title: '未读监管通知', value: 0, char: '未', colorClass: 'blue' },
];
}
return [
{ key: 'qualCheck', title: '资质现场审查通知', value: Number(noticesApi.qualOnSiteReviewCount) || 0, char: '审', colorClass: 'yellow' },
{ key: 'supervisionCheck', title: '监督检查通知', value: Number(noticesApi.inspectionCount) || 0, char: '检', colorClass: 'red' },
{ key: 'unreadNotice', title: '未读监管通知', value: Number(noticesApi.unreadRegulatoryCount) || 0, char: '未', colorClass: 'blue' },
];
}, [noticesApi]);
// 接口无数据时使用空结构,不再用 mock 伪造数据
const industryStatData = useMemo(() => industryStatApi || { list: [] }, [industryStatApi]);
const evalTypeRatioData = useMemo(() => evalTypeRatioApi || { totalProjectCount: 0, items: [] }, [evalTypeRatioApi]);
const projectExecutionData = useMemo(() => projectExecutionApi || { list: [] }, [projectExecutionApi]);
const legendColors = useMemo(() => ({
project: '#4285f4',
statutory: '#ffab31',
}), []);
return (
{!tools.inIframe() && }
{/* ===== 第一行:项目节点统计 + 通知提醒 ===== */}
当前项目节点统计
项目总数:{loading ? : {projectSummary.total}}
法定项目:{loading ? : {projectSummary.statutory}}
{statusCards.map(item => (
))}
通知提醒
{alertItems.map(item => (
))}
{/* ===== 第二行:服务行业项目统计 + 评价类别占比 ===== */}
{/* ===== 第三行:项目执行情况 ===== */}
{}}
/>
);
}