- useHealthStore 新增 batchResolvePatientNames/batchResolveDoctorNames 批量解析方法(去重 → 过滤已缓存 → 5 并发批次加载) - PointsOrderList 移除局部 nameCache,改用 useHealthStore 全局缓存 - PluginCRUDPage (871L) 拆分为 usePluginData + DetailDrawer + ImportModal + PluginCRUDPageInner,原文件改为 re-export - PluginGraphPage (765L) 拆分为 useGraphData + useGraphCanvas hooks - StatisticsDashboard (580L) 拆分为 useStatsData + HealthDataCenter
118 lines
4.1 KiB
TypeScript
118 lines
4.1 KiB
TypeScript
import { useEffect, useState } from 'react';
|
|
import { message } from 'antd';
|
|
import { listPluginData } from '../../api/pluginData';
|
|
import {
|
|
getPluginSchema,
|
|
type PluginFieldSchema,
|
|
type PluginSchemaResponse,
|
|
} from '../../api/plugins';
|
|
import type { GraphNode, GraphEdge, GraphConfig } from '../graph/graphTypes';
|
|
|
|
export function useGraphData(pluginId?: string, entityName?: string) {
|
|
const [customers, setCustomers] = useState<GraphNode[]>([]);
|
|
const [relationships, setRelationships] = useState<GraphEdge[]>([]);
|
|
const [loading, setLoading] = useState(false);
|
|
const [graphConfig, setGraphConfig] = useState<GraphConfig | null>(null);
|
|
const [fields, setFields] = useState<PluginFieldSchema[]>([]);
|
|
const [relTypes, setRelTypes] = useState<string[]>([]);
|
|
|
|
useEffect(() => {
|
|
if (!pluginId || !entityName) return;
|
|
const abortController = new AbortController();
|
|
|
|
async function loadSchema() {
|
|
try {
|
|
const schema: PluginSchemaResponse = await getPluginSchema(pluginId!);
|
|
if (abortController.signal.aborted) return;
|
|
|
|
const pages = schema.ui?.pages || [];
|
|
const graphPage = pages.find(
|
|
(p): p is typeof p & GraphConfig & { type: 'graph' } =>
|
|
p.type === 'graph' && p.entity === entityName,
|
|
);
|
|
if (graphPage) {
|
|
setGraphConfig({
|
|
entity: graphPage.entity,
|
|
relationshipEntity: graphPage.relationship_entity,
|
|
sourceField: graphPage.source_field,
|
|
targetField: graphPage.target_field,
|
|
edgeLabelField: graphPage.edge_label_field,
|
|
nodeLabelField: graphPage.node_label_field,
|
|
});
|
|
}
|
|
|
|
const entity = schema.entities?.find((e) => e.name === entityName);
|
|
if (entity) setFields(entity.fields);
|
|
} catch {
|
|
message.warning('Schema 加载失败,部分功能不可用');
|
|
}
|
|
}
|
|
|
|
loadSchema();
|
|
return () => abortController.abort();
|
|
}, [pluginId, entityName]);
|
|
|
|
useEffect(() => {
|
|
if (!pluginId || !graphConfig) return;
|
|
const abortController = new AbortController();
|
|
const gc = graphConfig;
|
|
const labelField = fields.find((f) => f.name === gc.nodeLabelField)?.name || fields[1]?.name || 'name';
|
|
|
|
async function loadData() {
|
|
setLoading(true);
|
|
try {
|
|
let allCustomers: GraphNode[] = [];
|
|
let page = 1;
|
|
let hasMore = true;
|
|
while (hasMore) {
|
|
if (abortController.signal.aborted) return;
|
|
const result = await listPluginData(pluginId!, gc.entity, page, 100);
|
|
allCustomers = [
|
|
...allCustomers,
|
|
...result.data.map((r) => ({
|
|
id: r.id,
|
|
label: String(r.data[labelField] || '未命名'),
|
|
data: r.data,
|
|
})),
|
|
];
|
|
hasMore = result.data.length === 100 && allCustomers.length < result.total;
|
|
page++;
|
|
}
|
|
if (abortController.signal.aborted) return;
|
|
setCustomers(allCustomers);
|
|
|
|
let allRels: GraphEdge[] = [];
|
|
page = 1;
|
|
hasMore = true;
|
|
const types = new Set<string>();
|
|
while (hasMore) {
|
|
if (abortController.signal.aborted) return;
|
|
const result = await listPluginData(pluginId!, gc.relationshipEntity, page, 100);
|
|
for (const r of result.data) {
|
|
const relType = String(r.data[gc.edgeLabelField] || '');
|
|
types.add(relType);
|
|
allRels.push({
|
|
source: String(r.data[gc.sourceField] || ''),
|
|
target: String(r.data[gc.targetField] || ''),
|
|
label: relType,
|
|
});
|
|
}
|
|
hasMore = result.data.length === 100 && allRels.length < result.total;
|
|
page++;
|
|
}
|
|
if (abortController.signal.aborted) return;
|
|
setRelationships(allRels);
|
|
setRelTypes(Array.from(types));
|
|
} catch {
|
|
message.warning('数据加载失败');
|
|
}
|
|
if (!abortController.signal.aborted) setLoading(false);
|
|
}
|
|
|
|
loadData();
|
|
return () => abortController.abort();
|
|
}, [pluginId, graphConfig, fields]);
|
|
|
|
return { customers, relationships, loading, fields, graphConfig, relTypes };
|
|
}
|