import { defHttp } from '@jeesite/core/utils/http/axios'; import { useGlobSetting } from '@jeesite/core/hooks/setting'; import { useUserStoreWithOut } from '@jeesite/core/store/modules/case'; import type { LocationQuery, LocationQueryValue } from 'vue-router'; export type RelationMode = 'object' | 'entity'; export type TradeMode = 'trade' | 'commonTrade' | 'mutualTrade'; export type CommunicationMode = 'contact' | 'commonContact' | 'mutualContact'; type GraphQueryValue = string | string[] | number | number[] | null | undefined; const { adminPath } = useGlobSetting(); const GRAPH_QUERY_OBJECT_ID_KEYS = [ 'ojbs', 'objIds', 'objId', 'ids', 'respondentIds', 'respondentId', 'targetIds', 'targetId', ]; const GRAPH_QUERY_NAME_KEYS = [ 'personNames', 'personName', 'respondentNames', 'respondentName', 'names', 'name', 'objNames', 'objName', ]; const GRAPH_QUERY_IDENTITY_KEYS = [ 'personCardNos', 'personCardNo', 'identityCodes', 'identityCode', 'cardNos', 'cardNo', 'sfz', 'sfzs', ]; const GRAPH_QUERY_NESTED_KEYS = ['query', 'params', 'payload']; export interface AnalysisRespondent { id: string; name: string; objId?: string; identityCode?: string; photograph?: string; degree?: number; } export interface AnalysisConditionPayload { respondents: AnalysisRespondent[]; queryTime?: [string, string]; tradeMode?: TradeMode; tradeAmountMin?: number; tradeAmountMax?: number; communicationMode?: CommunicationMode; communicationCount?: number; } export interface GraphAnalysisNode { dxId?: string | null; level?: number | null; sfz?: string | null; photo?: string | null; main?: string | null; team_id?: string | null; bm: string; type?: string | null; mc?: string | null; nodecn?: string | null; zp?: string | null; dxId0?: string | null; sm?: string | null; mc1?: string | null; id: string; kg?: string | null; class?: string | null; clazz?: string | null; fzId?: string | null; node?: string | null; lx?: number | null; fx?: number | null; [key: string]: unknown; } export interface GraphAnalysisEdge { mc?: string | null; sm?: string | null; id: string; obj2_name?: string | null; dx1: string; clazz: string; dx2: string; obj1_name?: string | null; money?: number | null; lx?: number | null; sjfx?: number | null; sbxq?: number | null; nums?: string | number | null; } export interface GraphAnalysisResponse { code: number; msg: string; data: { dx: GraphAnalysisNode[]; gx: GraphAnalysisEdge[]; }; } interface LegacyGraphAnalysisNode { id?: string | number | null; node?: string | number | null; bm?: string | number | null; sfz?: string | number | null; mc?: string | null; mc1?: string | null; nodecn?: string | null; name?: string | null; label?: string | null; class?: string | null; clazz?: string | null; dxId?: string | null; dxId0?: string | null; fzId?: string | null; photo?: string | null; zp?: string | null; [key: string]: unknown; } interface LegacyGraphAnalysisEdge { id?: string | number | null; dx1?: string | null; dx2?: string | null; node1?: string | null; node2?: string | null; obj1_name?: string | null; obj2_name?: string | null; node1cn?: string | null; node2cn?: string | null; clazz?: string | null; class?: string | null; lx?: string | number | null; mc?: string | null; sm?: string | null; money?: string | number | null; nums?: string | number | null; num?: string | number | null; [key: string]: unknown; } export interface GraphHistoryCreateQuery { caseId?: ApiId | number; graphHisName?: ApiText; name?: ApiText; graphName?: ApiText; title?: ApiText; content?: ApiText; graphData?: ApiText; graphJson?: ApiText; nodeCount?: ApiCount; edgeCount?: ApiCount; } export interface GraphHistoryItem { id?: ApiId | number; graphHisName?: ApiText; name?: ApiText; graphName?: ApiText; title?: ApiText; path?: ApiText; filePath?: ApiText; content?: ApiText; graphData?: ApiText; graphJson?: ApiText; data?: ApiText; createDate?: ApiDateString; createTime?: ApiDateString; createDateTime?: ApiDateString; createdAt?: ApiDateString; nodeCount?: ApiCount; edgeCount?: ApiCount; } export interface GraphHistoryDeleteQuery { id?: ApiId | number; } export interface GraphViewQuery extends Record { caseId?: number; page?: number; limit?: number; type?: number[]; startMoney?: string; endMoney?: string; callNum?: string; order?: string; asc?: string | number; export?: string | number; erId?: number; ojbs?: string[]; configDxMove?: string; configTeam?: string; configNoGx?: string; gxYs?: string; gxUser?: string; gxYsFs?: string; gxYsFsNum?: string; configYsGtgxr?: string; configYsGtgxrNum?: string; configYsGtgxrFs?: string; yhJy?: string; jyGtgxr?: string; jyGtgxrNum?: string; jyGtgxrMoney1?: string; jyGtgxrMoney2?: string; allJy?: string; jyXh?: string; jyGt?: string; gxTel?: string; telGtgxr?: string; telGtgxrNum?: string; telXh?: string; telGt?: string; telGtgxrFs1?: string; telDzTel?: string; telDzGtgxrNum?: string; allTel?: string; dxDzFc?: string; dxCar?: string; dxDzYh?: string; dxDzIp?: string; dxDzGa?: string; date1?: string; date2?: string; jt?: string; zdy?: string; model?: number; personName?: string; personNames?: string[]; personCardNo?: string; personCardNos?: string[]; identityCode?: string; identityCodes?: string[]; startDate?: string; endDate?: string; keyword?: string; tableName?: string; tableNameEn?: string; tableNameCn?: string; rowId?: string; id?: string; objId?: string; objIds?: string[]; ids?: string[]; } export interface GraphTransDetailQuery extends GraphViewQuery { personCardNo?: string; otherName?: string; otherCardNo?: string; lx?: number; jdlx?: string; ext1?: string; transAmountSymbol?: string; transAmount?: string | number; debitCreditFlag?: string; transSummary?: string; orderKey?: string; sort?: string; bankCardNo?: string; cardNo?: string; bm?: string; nodeId?: string; nodeClass?: string; dxId?: string; dxId0?: string; } export interface GraphCallDetailQuery extends GraphViewQuery { personPhones?: string[]; otherName?: string; otherPhones?: string[]; callDirection?: string; callType?: string; startTime?: string; endTime?: string; orderKey?: string; sort?: string; phoneNo?: string; personPhone?: string; otherPhone?: string; bm?: string; nodeId?: string; nodeClass?: string; dxId?: string; dxId0?: string; dx1?: string; dx2?: string; clazz?: string; edgeId?: string; } export interface GraphNodeDetailQuery { node: string; lx?: number; fx?: number; clazz: string; page?: number; limit?: number; startDate?: string; endDate?: string; transAmountSymbol?: string; transAmount?: string | number; orderKey?: string; sort?: string; } const GRAPH_VIEW_REQUEST_KEYS: (keyof GraphViewQuery)[] = [ 'caseId', 'personNames', 'type', 'startMoney', 'endMoney', 'callNum', 'date1', 'date2', 'startDate', 'endDate', ]; const pickRouteQueryValue = (value?: LocationQueryValue | LocationQueryValue[]) => { return Array.isArray(value) ? value[0] : value; }; const normalizeText = (value: unknown) => { if (value === 0) return '0'; const text = String(value ?? '').trim(); if (!text || text === 'null' || text === 'undefined') return undefined; return text; }; const normalizeNumber = (value: unknown) => { if (value === null || value === undefined || value === '') return undefined; const numeric = Number(value); if (!Number.isFinite(numeric)) return undefined; return numeric; }; const normalizeNumericText = (value: unknown) => { if (value === null || value === undefined || value === '') return undefined; const numeric = Number(value); if (!Number.isFinite(numeric)) return undefined; return String(numeric); }; const normalizeStringArray = (value: unknown) => { if (Array.isArray(value)) { const values = value.map((item) => normalizeText(item)).filter((item): item is string => Boolean(item)); return values.length ? Array.from(new Set(values)) : undefined; } const text = normalizeText(value); if (!text) return undefined; if (text.startsWith('[') && text.endsWith(']')) { try { const parsed = JSON.parse(text); if (Array.isArray(parsed)) return normalizeStringArray(parsed); } catch { // Ignore invalid JSON and keep the plain-text fallback. } } const values = text .split(',') .map((item) => normalizeText(item)) .filter((item): item is string => Boolean(item)); return values.length ? Array.from(new Set(values)) : undefined; }; const normalizeNumberArray = (value: unknown) => { if (Array.isArray(value)) { const values = value.map((item) => normalizeNumber(item)).filter((item): item is number => item !== undefined); return values.length ? Array.from(new Set(values)) : undefined; } const text = normalizeText(value); if (!text) return undefined; if (text.startsWith('[') && text.endsWith(']')) { try { const parsed = JSON.parse(text); if (Array.isArray(parsed)) return normalizeNumberArray(parsed); } catch { // Ignore invalid JSON and keep the plain-text fallback. } } const values = text .split(',') .map((item) => normalizeNumber(item)) .filter((item): item is number => item !== undefined); return values.length ? Array.from(new Set(values)) : undefined; }; const hasGraphQueryValue = (value: GraphQueryValue) => { if (value === null || value === undefined) return false; if (Array.isArray(value)) return value.length > 0; if (typeof value === 'number') return Number.isFinite(value); if (typeof value === 'string') return value.trim().length > 0; return false; }; const pickGraphViewRequestPayload = (query: GraphViewQuery): GraphViewQuery => { const payload: GraphViewQuery = {}; GRAPH_VIEW_REQUEST_KEYS.forEach((key) => { const value = query[key]; if (!hasGraphQueryValue(value)) return; payload[key] = value; }); return payload; }; const isObjectOrOrgNodeClass = (value?: string | null) => { const normalized = normalizeText(value)?.toLowerCase() || ''; return normalized === 'obj' || normalized === 'org' || normalized === 'ins'; }; const normalizeGraphAnalysisNode = (node: LegacyGraphAnalysisNode, index: number): GraphAnalysisNode | null => { const normalizedClass = normalizeText(node?.class ?? node?.clazz); const preferNodeValue = isObjectOrOrgNodeClass(normalizedClass); const nodeCn = normalizeText(node?.nodecn); const token = preferNodeValue ? normalizeText(node?.node ?? node?.bm ?? node?.sfz ?? node?.id) : normalizeText(node?.bm ?? node?.node ?? node?.sfz ?? node?.id); const fullLabel = preferNodeValue ? normalizeText(node?.node ?? node?.mc ?? node?.mc1 ?? node?.name ?? node?.label) : normalizeText(node?.mc ?? node?.mc1 ?? node?.name ?? node?.label ?? node?.node ?? node?.bm); const id = preferNodeValue ? normalizeText(node?.node ?? node?.id ?? node?.bm ?? node?.sfz ?? node?.dxId ?? node?.dxId0) : normalizeText(node?.id ?? node?.node ?? node?.bm ?? node?.sfz ?? node?.dxId ?? node?.dxId0); if (!token && !fullLabel && !id) return null; return { ...(node as Record), id: id || token || fullLabel || `graph-node-${index}`, bm: token || id || fullLabel || `graph-node-${index}`, mc: fullLabel || token || id || '未命名实体', nodecn: nodeCn, mc1: fullLabel || token || id || '未命名实体', sfz: normalizeText(node?.sfz), photo: normalizeText(node?.photo), zp: normalizeText(node?.zp), dxId: normalizeText(node?.dxId), dxId0: normalizeText(node?.dxId0), fzId: normalizeText(node?.fzId), class: normalizeText(node?.class ?? node?.clazz), clazz: normalizeText(node?.clazz ?? node?.class), type: normalizeText(node?.class ?? node?.clazz), node: normalizeText(node?.node), lx: normalizeNumber((node as Record)?.lx), fx: normalizeNumber((node as Record)?.fx), }; }; const buildGraphAnalysisNodeMergeKey = (node: GraphAnalysisNode) => { const clazz = normalizeText(node.class ?? node.type) || 'unknown'; const token = normalizeText(node.bm ?? node.sfz ?? node.id); if (!token) return ''; return `${clazz}::${token}`; }; const pickPreferredNodeText = (current?: string | null, incoming?: string | null) => { const currentText = normalizeText(current); const incomingText = normalizeText(incoming); if (!currentText) return incomingText; if (!incomingText) return currentText; return incomingText.length > currentText.length ? incomingText : currentText; }; const mergeGraphAnalysisNode = (current: GraphAnalysisNode, incoming: GraphAnalysisNode): GraphAnalysisNode => ({ ...current, id: pickPreferredNodeText(current.id, incoming.id) || current.id, bm: pickPreferredNodeText(current.bm, incoming.bm) || current.bm, mc: pickPreferredNodeText(current.mc, incoming.mc) || current.mc, nodecn: pickPreferredNodeText(current.nodecn, incoming.nodecn), mc1: pickPreferredNodeText(current.mc1, incoming.mc1) || current.mc1, sfz: pickPreferredNodeText(current.sfz, incoming.sfz), photo: pickPreferredNodeText(current.photo, incoming.photo), zp: pickPreferredNodeText(current.zp, incoming.zp), dxId: pickPreferredNodeText(current.dxId, incoming.dxId), dxId0: pickPreferredNodeText(current.dxId0, incoming.dxId0), fzId: pickPreferredNodeText(current.fzId, incoming.fzId), class: pickPreferredNodeText(current.class, incoming.class), clazz: pickPreferredNodeText(current.clazz, incoming.clazz), type: pickPreferredNodeText(current.type, incoming.type), node: pickPreferredNodeText(current.node, incoming.node), lx: current.lx ?? incoming.lx, fx: current.fx ?? incoming.fx, }); const dedupeGraphAnalysisNodes = (nodes: GraphAnalysisNode[]) => { const nodeMap = new Map(); nodes.forEach((node) => { const mergeKey = buildGraphAnalysisNodeMergeKey(node); if (!mergeKey) return; const currentNode = nodeMap.get(mergeKey); nodeMap.set(mergeKey, currentNode ? mergeGraphAnalysisNode(currentNode, node) : node); }); return Array.from(nodeMap.values()); }; const normalizeGraphAnalysisEdge = (edge: LegacyGraphAnalysisEdge, index: number): GraphAnalysisEdge | null => { const dx1 = normalizeText(edge?.dx1 ?? edge?.node1); const dx2 = normalizeText(edge?.dx2 ?? edge?.node2); if (!dx1 || !dx2) return null; const money = normalizeNumber(edge?.money ?? edge?.num); const nums = normalizeNumericText(edge?.nums ?? edge?.num); const clazz = normalizeText(edge?.clazz ?? edge?.class) || 'custom_assoc'; return { id: normalizeText(edge?.id) || `${dx1}-${dx2}-${clazz}-${index}`, dx1, dx2, clazz, mc: normalizeText(edge?.mc ?? edge?.sm), sm: normalizeText(edge?.sm ?? edge?.mc), obj1_name: normalizeText(edge?.obj1_name ?? edge?.node1cn), obj2_name: normalizeText(edge?.obj2_name ?? edge?.node2cn), money, lx: normalizeNumber(edge?.lx), nums, }; }; const normalizeGraphAnalysisResponse = (response: any): GraphAnalysisResponse => { const payload = response?.data !== undefined ? response.data : response; const graphData = payload?.data !== undefined ? payload.data : payload; const rawNodes = (Array.isArray(graphData?.dx) && graphData.dx) || (Array.isArray(graphData?.nodeList) && graphData.nodeList) || (Array.isArray(graphData?.nodelist) && graphData.nodelist) || []; const rawEdges = (Array.isArray(graphData?.gx) && graphData.gx) || (Array.isArray(graphData?.edgeList) && graphData.edgeList) || (Array.isArray(graphData?.edgelist) && graphData.edgelist) || []; return { code: normalizeNumber(payload?.code ?? response?.code) ?? 200, msg: normalizeText(payload?.msg ?? payload?.message ?? response?.msg ?? response?.message) || '', data: { dx: dedupeGraphAnalysisNodes( rawNodes .map((item: LegacyGraphAnalysisNode, index: number) => normalizeGraphAnalysisNode(item, index)) .filter((item): item is GraphAnalysisNode => Boolean(item)), ), gx: rawEdges .map((item: LegacyGraphAnalysisEdge, index: number) => normalizeGraphAnalysisEdge(item, index)) .filter((item): item is GraphAnalysisEdge => Boolean(item)), }, }; }; const parseObjectLike = (value: unknown): Record | undefined => { if (!value) return undefined; if (typeof value === 'object' && !Array.isArray(value)) { return value as Record; } const text = normalizeText(Array.isArray(value) ? value[0] : value); if (!text || !text.startsWith('{') || !text.endsWith('}')) return undefined; try { const parsed = JSON.parse(text); if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) { return parsed as Record; } } catch { // Ignore invalid JSON text. } return undefined; }; const expandLocationQuerySource = (query?: LocationQuery | Record) => { if (!query) return {}; const expanded: Record = { ...query }; GRAPH_QUERY_NESTED_KEYS.forEach((key) => { const nested = parseObjectLike((query as Record)[key]); if (!nested) return; Object.entries(nested).forEach(([nestedKey, nestedValue]) => { const currentValue = expanded[nestedKey]; if (currentValue === undefined || currentValue === null || currentValue === '') { expanded[nestedKey] = nestedValue; } }); }); return expanded; }; const normalizeLocationQuery = (query?: LocationQuery | Record): GraphViewQuery => { if (!query) return {}; const normalized: GraphViewQuery = {}; const expandedSource = expandLocationQuerySource(query); Object.entries(expandedSource).forEach(([key, rawValue]) => { if (typeof rawValue === 'number' && Number.isFinite(rawValue)) { normalized[key] = rawValue; return; } const arrayValue = normalizeStringArray(rawValue); if (Array.isArray(rawValue) || (arrayValue?.length && arrayValue.length > 1)) { if (arrayValue?.length) { normalized[key] = arrayValue; } return; } const routeValue = pickRouteQueryValue(rawValue as LocationQueryValue | LocationQueryValue[]); const textValue = normalizeText(routeValue); if (textValue !== undefined) { normalized[key] = textValue; } }); return normalized; }; const pickFirstText = (source: Record, keys: string[]) => { for (const key of keys) { const text = normalizeText(source[key]); if (text) return text; } return undefined; }; const pickFirstArray = (source: Record, keys: string[]) => { for (const key of keys) { const values = normalizeStringArray(source[key]); if (values?.length) return values; } return undefined; }; const pickFirstNumber = (source: Record, keys: string[]) => { for (const key of keys) { const value = normalizeNumber(source[key]); if (value !== undefined) return value; } return undefined; }; const uniqueValues = (values: T[]) => Array.from(new Set(values)); const uniqueNumberValues = (values: number[]) => Array.from(new Set(values.filter((item) => Number.isFinite(item)))); const resolveGraphTransDetailType = (source: Record) => { const directType = pickFirstNumber(source, ['lx']); if (directType !== undefined) return directType; const typeValues = normalizeNumberArray(source.type); return typeValues?.find((item) => item >= 100 && item < 200); }; const pickGraphTransDetailRequestPayload = (query: GraphTransDetailQuery): GraphTransDetailQuery => { const source = query as Record; const payload: GraphTransDetailQuery = {}; const caseId = resolveCaseId(query); if (caseId !== undefined) { payload.caseId = caseId; } const page = normalizeNumber(query.page); if (page !== undefined) { payload.page = page; } const limit = normalizeNumber(query.limit); if (limit !== undefined) { payload.limit = limit; } const startDate = pickFirstText(source, ['startDate', 'date1']); if (startDate) { payload.startDate = startDate; } const endDate = pickFirstText(source, ['endDate', 'date2']); if (endDate) { payload.endDate = endDate; } const personCardNo = pickFirstText(source, ['personCardNo', 'bankCardNo', 'cardNo', 'bm']); if (personCardNo) { payload.personCardNo = personCardNo; } const otherCardNo = pickFirstText(source, ['otherCardNo']); if (otherCardNo) { payload.otherCardNo = otherCardNo; } const lx = resolveGraphTransDetailType(source); if (lx !== undefined) { payload.lx = lx; } const jdlx = pickFirstText(source, ['jdlx', 'debitCreditFlag']); if (jdlx) { payload.jdlx = jdlx; } const otherName = pickFirstText(source, ['otherName']); if (otherName) { payload.otherName = otherName; } const ext1 = pickFirstText(source, ['ext1', 'transSummary']); if (ext1) { payload.ext1 = ext1; } const transAmountSymbol = pickFirstText(source, ['transAmountSymbol']); if (transAmountSymbol) { payload.transAmountSymbol = transAmountSymbol; } const transAmount = normalizeText(query.transAmount); if (transAmount) { payload.transAmount = transAmount; } const orderKey = pickFirstText(source, ['orderKey']); if (orderKey) { payload.orderKey = orderKey; } const sort = pickFirstText(source, ['sort']); if (sort) { payload.sort = sort; } return payload; }; const pickGraphCallDetailRequestPayload = (query: GraphCallDetailQuery): GraphCallDetailQuery => { const source = query as Record; const payload: GraphCallDetailQuery = {}; const caseId = resolveCaseId(query); if (caseId !== undefined) { payload.caseId = caseId; } const page = normalizeNumber(query.page); if (page !== undefined) { payload.page = page; } const limit = normalizeNumber(query.limit); if (limit !== undefined) { payload.limit = limit; } const personPhone = pickFirstText(source, ['personPhone', 'phoneNo', 'bm', 'dx1']) || query.personPhones?.[0]; if (personPhone) { payload.personPhone = personPhone; } const otherPhone = pickFirstText(source, ['otherPhone', 'dx2']) || query.otherPhones?.[0]; if (otherPhone) { payload.otherPhone = otherPhone; } const startDate = pickFirstText(source, ['startDate', 'date1']); if (startDate) { payload.startDate = startDate; } const endDate = pickFirstText(source, ['endDate', 'date2']); if (endDate) { payload.endDate = endDate; } const startTime = pickFirstText(source, ['startTime']); if (startTime) { payload.startTime = startTime; } const endTime = pickFirstText(source, ['endTime']); if (endTime) { payload.endTime = endTime; } const orderKey = pickFirstText(source, ['orderKey']); if (orderKey) { payload.orderKey = orderKey; } const sort = pickFirstText(source, ['sort']); if (sort) { payload.sort = sort; } return payload; }; const resolveCaseId = (query?: GraphViewQuery) => { const routeCaseId = pickFirstNumber((query || {}) as Record, ['caseId', 'case_id']); if (routeCaseId !== undefined) return routeCaseId; return normalizeNumber(useUserStoreWithOut().getCaseInfo?.id); }; const appendRespondent = ( respondents: AnalysisRespondent[], seenKeys: Set, payload: { objId?: string; name?: string; identityCode?: string; }, ) => { const objId = normalizeText(payload.objId); const name = normalizeText(payload.name); const identityCode = normalizeText(payload.identityCode); const id = objId || identityCode || name; if (!id || seenKeys.has(id)) return; seenKeys.add(id); respondents.push({ id, objId, name: name || identityCode || objId || id, identityCode, }); }; export const resolveGraphRespondentsFromRouteQuery = ( query?: LocationQuery | Record, ): AnalysisRespondent[] => { const normalized = normalizeLocationQuery(query); const objIds = pickFirstArray(normalized, GRAPH_QUERY_OBJECT_ID_KEYS) || []; const personNames = pickFirstArray(normalized, GRAPH_QUERY_NAME_KEYS) || []; const personCardNos = pickFirstArray(normalized, GRAPH_QUERY_IDENTITY_KEYS) || []; const respondents: AnalysisRespondent[] = []; const seenKeys = new Set(); const maxLength = Math.max(objIds.length, personNames.length, personCardNos.length); for (let index = 0; index < maxLength; index += 1) { appendRespondent(respondents, seenKeys, { objId: objIds[index], name: personNames[index], identityCode: personCardNos[index], }); } if (!respondents.length) { appendRespondent(respondents, seenKeys, { objId: pickFirstText(normalized, GRAPH_QUERY_OBJECT_ID_KEYS), name: normalizeText(normalized.keyword), identityCode: pickFirstText(normalized, GRAPH_QUERY_IDENTITY_KEYS), }); } return respondents; }; const applyRespondentFields = (target: GraphViewQuery, respondents: AnalysisRespondent[]) => { const respondentNames = uniqueValues( respondents.map((item) => normalizeText(item.name)).filter((item): item is string => Boolean(item)), ); target.personName = undefined; target.personNames = respondentNames.length ? respondentNames : undefined; target.personCardNo = undefined; target.personCardNos = undefined; target.identityCode = undefined; target.identityCodes = undefined; target.ojbs = undefined; target.objId = undefined; target.objIds = undefined; target.ids = undefined; }; const applyQueryTimeFields = (target: GraphViewQuery, queryTime?: [string, string]) => { const startDate = queryTime?.[0] || pickFirstText(target, ['date1', 'startDate']); const endDate = queryTime?.[1] || pickFirstText(target, ['date2', 'endDate']); target.date1 = startDate; target.date2 = endDate; target.startDate = startDate; target.endDate = endDate; }; const applyConditionFields = (target: GraphViewQuery, payload?: AnalysisConditionPayload) => { if (!payload) { applyQueryTimeFields(target); return; } if (payload.respondents.length) { applyRespondentFields(target, payload.respondents); } applyQueryTimeFields(target, payload.queryTime); const typeCodes = uniqueNumberValues([ payload.tradeMode ? payload.tradeMode === 'trade' ? 101 : payload.tradeMode === 'commonTrade' ? 102 : 103 : undefined, payload.communicationMode ? payload.communicationMode === 'contact' ? 201 : payload.communicationMode === 'commonContact' ? 202 : 203 : undefined, ]); target.type = typeCodes.length ? typeCodes : undefined; target.startMoney = normalizeNumericText(payload.tradeAmountMin); target.endMoney = normalizeNumericText(payload.tradeAmountMax); target.callNum = normalizeNumericText(payload.communicationCount); target.startDate = payload.queryTime?.[0] || target.startDate || target.date1; target.endDate = payload.queryTime?.[1] || target.endDate || target.date2; // Old graph/view flags are no longer used by the backend; clear them to avoid mixed payloads. target.gxYs = undefined; target.dxDzFc = undefined; target.dxCar = undefined; target.yhJy = undefined; target.allJy = undefined; target.jyGtgxr = undefined; target.jyGtgxrNum = undefined; target.jyGtgxrMoney1 = undefined; target.jyGtgxrMoney2 = undefined; target.jyXh = undefined; target.jyGt = undefined; target.gxTel = undefined; target.allTel = undefined; target.telGtgxr = undefined; target.telGtgxrNum = undefined; target.telGtgxrFs1 = undefined; target.telXh = undefined; target.telGt = undefined; target.configTeam = undefined; target.zdy = undefined; target.jt = undefined; }; const finalizeGraphViewQuery = (query: GraphViewQuery) => { const normalized = { ...query } as GraphViewQuery; const caseId = resolveCaseId(normalized); if (caseId !== undefined) { normalized.caseId = caseId; } delete normalized.page; delete normalized.limit; delete normalized.model; applyQueryTimeFields(normalized); normalized.startDate = normalized.startDate || normalized.date1; normalized.endDate = normalized.endDate || normalized.date2; const routePersonNames = pickFirstArray(normalized, GRAPH_QUERY_NAME_KEYS); if (!normalized.personNames && routePersonNames?.length) { normalized.personNames = routePersonNames; } normalized.personName = undefined; normalized.ojbs = undefined; normalized.objId = undefined; normalized.objIds = undefined; normalized.ids = undefined; normalized.gxYs = undefined; normalized.dxDzFc = undefined; normalized.dxCar = undefined; normalized.yhJy = undefined; normalized.allJy = undefined; normalized.jyGtgxr = undefined; normalized.jyGtgxrNum = undefined; normalized.jyGtgxrMoney1 = undefined; normalized.jyGtgxrMoney2 = undefined; normalized.jyXh = undefined; normalized.jyGt = undefined; normalized.gxTel = undefined; normalized.allTel = undefined; normalized.telGtgxr = undefined; normalized.telGtgxrNum = undefined; normalized.telGtgxrFs1 = undefined; normalized.telXh = undefined; normalized.telGt = undefined; normalized.configTeam = undefined; normalized.zdy = undefined; normalized.jt = undefined; return pickGraphViewRequestPayload(normalized); }; export const buildGraphViewQuery = ( routeQuery?: LocationQuery | Record, payload?: AnalysisConditionPayload, ): GraphViewQuery => { const normalized = normalizeLocationQuery(routeQuery); applyConditionFields(normalized, payload); return finalizeGraphViewQuery(normalized); }; export const buildGraphTransDetailQuery = ( routeQuery?: LocationQuery | Record, detailQuery?: Record, node?: GraphAnalysisNode | null, ): GraphTransDetailQuery => { const normalized = { ...normalizeLocationQuery(routeQuery), } as GraphTransDetailQuery; Object.entries(detailQuery || {}).forEach(([key, value]) => { if (typeof value === 'number' && Number.isFinite(value)) { normalized[key] = value; return; } const values = normalizeStringArray(value); if (Array.isArray(value) || (values?.length && values.length > 1)) { if (values?.length) { normalized[key] = values; } return; } const text = normalizeText(value); if (text !== undefined) { normalized[key] = text; } }); const bankCardNo = normalizeText(node?.bm); const nodeId = normalizeText(node?.id); const nodeClass = normalizeText(node?.class); const dxId = normalizeText(node?.dxId); const dxId0 = normalizeText(node?.dxId0); if (bankCardNo) { normalized.personCardNo = normalized.personCardNo || bankCardNo; normalized.bankCardNo = normalized.bankCardNo || bankCardNo; normalized.cardNo = normalized.cardNo || bankCardNo; normalized.bm = normalized.bm || bankCardNo; } const personCardNo = pickFirstText(normalized as Record, [ 'personCardNo', 'bankCardNo', 'cardNo', 'bm', ]); if (personCardNo) { normalized.personCardNo = personCardNo; } const lx = resolveGraphTransDetailType(normalized as Record); if (lx !== undefined) { normalized.lx = lx; } const jdlx = pickFirstText(normalized as Record, ['jdlx', 'debitCreditFlag']); if (jdlx) { normalized.jdlx = jdlx; } const ext1 = pickFirstText(normalized as Record, ['ext1', 'transSummary']); if (ext1) { normalized.ext1 = ext1; } if (nodeId && !normalized.nodeId) { normalized.nodeId = nodeId; } if (nodeClass && !normalized.nodeClass) { normalized.nodeClass = nodeClass; } if (dxId && !normalized.dxId) { normalized.dxId = dxId; } if (dxId0 && !normalized.dxId0) { normalized.dxId0 = dxId0; } normalized.ids = undefined; normalized.ojbs = undefined; normalized.objIds = undefined; normalized.objId = undefined; return normalized; }; export const buildGraphCallDetailQuery = ( routeQuery?: LocationQuery | Record, detailQuery?: Record, node?: GraphAnalysisNode | null, edge?: GraphAnalysisEdge | null, ): GraphCallDetailQuery => { const normalized = { ...normalizeLocationQuery(routeQuery), } as GraphCallDetailQuery; Object.entries(detailQuery || {}).forEach(([key, value]) => { if (typeof value === 'number' && Number.isFinite(value)) { normalized[key] = value; return; } const values = normalizeStringArray(value); if (Array.isArray(value) || (values?.length && values.length > 1)) { if (values?.length) { normalized[key] = values; } return; } const text = normalizeText(value); if (text !== undefined) { normalized[key] = text; } }); const phoneNo = normalizeText(node?.bm); const nodeId = normalizeText(node?.id); const nodeClass = normalizeText(node?.class); const dxId = normalizeText(node?.dxId); const dxId0 = normalizeText(node?.dxId0); const dx1 = normalizeText(edge?.dx1); const dx2 = normalizeText(edge?.dx2); const clazz = normalizeText(edge?.clazz); const edgeId = normalizeText(edge?.id); if (phoneNo) { normalized.phoneNo = normalized.phoneNo || phoneNo; normalized.personPhone = normalized.personPhone || phoneNo; normalized.bm = normalized.bm || phoneNo; if (!normalized.personPhones?.length) { normalized.personPhones = [phoneNo]; } } if (nodeId && !normalized.nodeId) { normalized.nodeId = nodeId; } if (nodeClass && !normalized.nodeClass) { normalized.nodeClass = nodeClass; } if (dxId && !normalized.dxId) { normalized.dxId = dxId; } if (dxId0 && !normalized.dxId0) { normalized.dxId0 = dxId0; } if (dx1) { normalized.dx1 = normalized.dx1 || dx1; normalized.personPhone = normalized.personPhone || dx1; if (!normalized.personPhones?.length) { normalized.personPhones = [dx1]; } } if (dx2) { normalized.dx2 = normalized.dx2 || dx2; normalized.otherPhone = normalized.otherPhone || dx2; if (!normalized.otherPhones?.length) { normalized.otherPhones = [dx2]; } } if (clazz && !normalized.clazz) { normalized.clazz = clazz; } if (edgeId && !normalized.edgeId) { normalized.edgeId = edgeId; } const personPhone = pickFirstText(normalized as Record, ['personPhone', 'phoneNo', 'bm', 'dx1']) || normalized.personPhones?.[0]; if (personPhone) { normalized.personPhone = personPhone; } const otherPhone = pickFirstText(normalized as Record, ['otherPhone', 'dx2']) || normalized.otherPhones?.[0]; if (otherPhone) { normalized.otherPhone = otherPhone; } normalized.ids = undefined; normalized.ojbs = undefined; normalized.objIds = undefined; normalized.objId = undefined; return normalized; }; export const fetchGraphAnalysis = async ( payload: AnalysisConditionPayload, routeQuery?: LocationQuery | Record, ): Promise => { const data = buildGraphViewQuery(routeQuery, payload); if (!data.personNames?.length) { throw new Error('当前未获取到对象名称,请先选择对象'); } const response = await defHttp.postJson( { url: adminPath + '/graph/view', data, }, { skipSuccessMessage: true, }, ); return normalizeGraphAnalysisResponse(response); }; export const fetchGraphTransDetail = async (data: GraphTransDetailQuery): Promise => { const payload = pickGraphTransDetailRequestPayload(data); return defHttp.postJson( { url: adminPath + '/graph/transDetail', data: payload, }, { skipSuccessMessage: true, }, ); }; export const fetchGraphCallDetail = async (data: GraphCallDetailQuery): Promise => { const payload = pickGraphCallDetailRequestPayload(data); return defHttp.postJson( { url: adminPath + '/graph/callDetail', data: payload, }, { skipSuccessMessage: true, }, ); }; export const fetchGraphNodeDetail = async (data: GraphNodeDetailQuery): Promise => { return defHttp.postJson( { url: adminPath + '/graph/nodeDetail', data, }, { skipSuccessMessage: true, }, ); }; export const createGraphHistory = async (params: GraphHistoryCreateQuery): Promise => { return defHttp.get( { url: adminPath + '/graph/createGraphHis', params, }, { skipSuccessMessage: true, }, ); }; export const fetchGraphHistory = async (params?: Partial): Promise => { return defHttp.get( { url: adminPath + '/graph/graphHis', params, }, { skipSuccessMessage: true, }, ); }; export const deleteGraphHistory = async (params: GraphHistoryDeleteQuery): Promise => { return defHttp.get( { url: adminPath + '/graph/deleteGraphHis', params, }, { skipSuccessMessage: true, }, ); };