/** * AI 聊天关系图谱 —— 独立明细查询封装 * * 与「对象关系分析」页面的 graph/api/analysis.ts 完全独立:只请求后端既有的 * /graph/nodeDetail、/graph/callDetail、/graph/transDetail 三个只读接口。 */ import { defHttp } from '@/core/utils/http/axios'; import { useGlobSetting } from '@/core/hooks/setting'; import { useUserStoreWithOut } from '@/core/store/modules/case'; import { normalizeText, type GraphModelEdge, type GraphModelNode } from './graphData'; const { adminPath } = useGlobSetting(); function resolveCaseId(): string | number | undefined { const raw: any = useUserStoreWithOut().getCaseInfo?.id; if (raw === undefined || raw === null || raw === '') return undefined; return typeof raw === 'number' ? raw : String(raw).trim() || undefined; } function withCaseId(data: Record): Record { const caseId = data.caseId ?? resolveCaseId(); return caseId === undefined ? data : { ...data, caseId }; } function removeEmpty(data: Record): Record { const result: Record = {}; Object.entries(data).forEach(([key, value]) => { if (value === undefined || value === null || value === '') return; result[key] = value; }); return result; } async function postGraph(url: string, data: Record): Promise { return defHttp.postJson( { url: adminPath + url, data: withCaseId(removeEmpty(data)), }, { skipSuccessMessage: true }, ); } function defaultClazz(node: GraphModelNode): string { if (node.kind === 'person') return 'sfz'; if (node.kind === 'phone') return 'tel'; if (node.kind === 'bank') return 'card'; if (node.kind === 'house') return 'dz_fc'; if (node.kind === 'car') return 'car'; if (node.kind === 'group') return 'obj'; return 'x'; } function nodeToken(node: GraphModelNode): string { const raw = node.raw || {}; return normalizeText(raw.node ?? raw.bm ?? raw.sfz ?? raw.id) || node.id; } function nodeClazz(node: GraphModelNode): string { const raw = node.raw || {}; return normalizeText(raw.clazz ?? raw.class) || defaultClazz(node); } function edgeEndpoint(edge: GraphModelEdge, endpoint: 'source' | 'target'): string { const raw = edge.raw || {}; const value = endpoint === 'source' ? (raw.node1 ?? raw.dx1) : (raw.node2 ?? raw.dx2); return normalizeText(value) || (endpoint === 'source' ? edge.source : edge.target); } export interface NodeDetailExtra { page?: number; limit?: number; startDate?: string; endDate?: string; transAmount?: number | string; transAmountSymbol?: string; } /** 节点详情查询(非人节点:卡/号码/车/房/机构等) */ export function buildNodeDetailQuery(node: GraphModelNode, extra: NodeDetailExtra = {}): Record { const raw = node.raw || {}; const lx = Number(raw.lx); const fx = Number(raw.fx); return { node: nodeToken(node), clazz: nodeClazz(node), lx: Number.isFinite(lx) ? lx : 0, fx: Number.isFinite(fx) ? fx : 0, page: extra.page, limit: extra.limit, startDate: extra.startDate, endDate: extra.endDate, transAmount: extra.transAmount, transAmountSymbol: extra.transAmount ? extra.transAmountSymbol || 'GE' : undefined, }; } /** 电话节点 → 通话明细 */ export function buildCallDetailQueryFromNode(node: GraphModelNode): Record { const phone = nodeToken(node); return { personPhone: phone, personPhones: [phone], }; } /** 通话关系边 → 通话明细 */ export function buildCallDetailQueryFromEdge(edge: GraphModelEdge): Record { const dx1 = edgeEndpoint(edge, 'source'); const dx2 = edgeEndpoint(edge, 'target'); return { dx1, dx2, personPhone: dx1, otherPhone: dx2, personPhones: [dx1], otherPhones: [dx2], clazz: edge.clazz, edgeId: edge.id, }; } /** 银行卡节点 → 交易明细 */ export function buildTransDetailQueryFromNode(node: GraphModelNode): Record { const card = nodeToken(node); return { personCardNo: card, bankCardNo: card, cardNo: card, bm: card, }; } /** 交易关系边 → 交易明细 */ export function buildTransDetailQueryFromEdge(edge: GraphModelEdge): Record { const raw = edge.raw || {}; const dx1 = edgeEndpoint(edge, 'source'); const dx2 = edgeEndpoint(edge, 'target'); const lx = Number(raw.lx); return { personCardNo: dx1, otherCardNo: dx2, bankCardNo: dx1, cardNo: dx1, bm: dx1, lx: Number.isFinite(lx) ? lx : 1, edgeId: edge.id, }; } export function fetchNodeDetail(data: Record): Promise { return postGraph('/graph/nodeDetail', data); } export function fetchCallDetail(data: Record): Promise { return postGraph('/graph/callDetail', data); } export function fetchTransDetail(data: Record): Promise { return postGraph('/graph/transDetail', data); }