import { useEffect, useState } from 'react'; import { Card, Row, Col, Statistic, Spin, Empty, Select, Tag } from 'antd'; import { TeamOutlined, RiseOutlined, PhoneOutlined, TagsOutlined, } from '@ant-design/icons'; import { listPluginData } from '../api/pluginData'; import { PluginFieldSchema, PluginEntitySchema } from '../api/plugins'; interface PluginDashboardPageProps { pluginId: string; entities: PluginEntitySchema[]; } interface AggregationResult { key: string; count: number; } /** * 插件统计概览页面 * 使用 listPluginData 加载全量数据前端聚合 */ export function PluginDashboardPage({ pluginId, entities }: PluginDashboardPageProps) { const [loading, setLoading] = useState(false); const [selectedEntity, setSelectedEntity] = useState( entities[0]?.name || '', ); const [totalCount, setTotalCount] = useState(0); const [aggregations, setAggregations] = useState([]); const currentEntity = entities.find((e) => e.name === selectedEntity); const filterableFields = currentEntity?.fields.filter((f) => f.filterable) || []; useEffect(() => { if (!pluginId || !selectedEntity) return; setLoading(true); async function loadData() { try { let allData: Record[] = []; let page = 1; let hasMore = true; let total = 0; while (hasMore) { const result = await listPluginData(pluginId, selectedEntity!, page, 200); allData = [...allData, ...result.data.map((r) => r.data)]; total = result.total; hasMore = result.data.length === 200 && allData.length < result.total; page++; } setTotalCount(total); const aggs: AggregationResult[] = []; for (const field of filterableFields) { const grouped = new Map(); for (const item of allData) { const val = String(item[field.name] ?? '(空)'); grouped.set(val, (grouped.get(val) || 0) + 1); } for (const [key, count] of grouped) { aggs.push({ key: `${field.display_name || field.name}: ${key}`, count }); } } setAggregations(aggs); } catch { // 加载失败 } setLoading(false); } loadData(); }, [pluginId, selectedEntity, filterableFields.length]); const iconMap: Record = { customer: , contact: , communication: , customer_tag: , customer_relationship: , }; if (loading) { return (
); } return (
({ label: e.display_name || e.name, value: e.name, }))} onChange={setSelectedEntity} /> } > } valueStyle={{ color: '#4F46E5' }} /> {aggregations.length > 0 && ( {aggregations.slice(0, 20).map((agg, idx) => ( {agg.key}: {agg.count} ))} )} {aggregations.length === 0 && totalCount === 0 && ( )}
); }