diff --git a/src/service/api/groupEvolution.js b/src/service/api/groupEvolution.js index fe842e4..89b7292 100644 --- a/src/service/api/groupEvolution.js +++ b/src/service/api/groupEvolution.js @@ -52,7 +52,10 @@ export function getStructuralEvolutionAnalysisPost(time) { return http.get(`/groupEvolution/groupStructure/posts?date=${time}`) } - +// 2.6 群体结构演化分析的关系图 +export function getStructuralEvolutionAnalysisGraph(time) { + return http.get(`/groupEvolution/groupStructure/relation?date=${time}`) +} // 3.群体成员演化分析 // 3.1 获取时间线数据 @@ -80,6 +83,10 @@ export function getGroupMemberEvolutionAnalysisChart() { return http.get(`/groupEvolution/groupMember/rightChart`) } +//3.6 群体成员演化分析的关系图 +export function getGroupMemberEvolutionAnalysisGraph(time) { + return http.get(`/groupEvolution/groupMember/relation?date=${time}`) +} // 4.异常群体捕捉 // 4.1获取时间轴 export function getAbnormalGroupTimeLine() { @@ -102,4 +109,3 @@ export function getAbnormalGroupBehaviorPosts(time) { export function getAbnormalGroupBehaviorDetail(time) { return http.get(`/groupEvolution/groupException/rightChart?date=${time}`) } - diff --git a/src/store/groupEvolution/index.js b/src/store/groupEvolution/index.js index b17b014..bcb1318 100644 --- a/src/store/groupEvolution/index.js +++ b/src/store/groupEvolution/index.js @@ -22,6 +22,8 @@ import { getGroupMemberChart, getGroupMemberEvolutionInfoByTime, getGroupMemberEvolutionAnalysisChart, + getStructuralEvolutionAnalysisGraph, + getGroupMemberEvolutionAnalysisGraph, // 4.异常群体捕捉 getAbnormalGroupTimeLine, @@ -523,7 +525,7 @@ export const useGroupStructureStore = defineStore("groupStructure", { } return colorMap[parseInt(groupId)] } - const res = await getRelationGraphByUtcTime(utcTime) + const res = await getStructuralEvolutionAnalysisGraph(utcTime) if (res.code != 200) return const newSet = new Set() this.graph["links"] = res.data.links.map((link) => ({ @@ -546,6 +548,7 @@ export const useGroupStructureStore = defineStore("groupStructure", { type: node.groupId } }) + this.graph["newLinks"] = res.data?.newAddRelation ?? [] }, // 初始化群体结构演化分析的群体演化信息-中下-随时间轴变化 async initializeStructuralPost(time = "2024-06-19T07:57:46Z") { @@ -591,8 +594,6 @@ export const useGroupMemberStore = defineStore("groupMember", { }, async initializeGroupMemberChart() { const res = await getGroupMemberChart() - // console.log("测试获取groupMemberChart:",res); - const xAxisData = res.data.xaxisData.map((item) => utcStringToHHMMSS(item)) const yAxisRange = res.data.yaxisRange const themeColors = ["#2AB8FD", "#02D7DA", "#FFDA09", "#EB57B0"] @@ -689,7 +690,9 @@ export const useGroupMemberStore = defineStore("groupMember", { } return colorMap[parseInt(groupId)] } - const res = await getRelationGraphByUtcTime(utcTime) + const res = await getGroupMemberEvolutionAnalysisGraph(utcTime) + console.log(res) + if (res.code != 200) return const newSet = new Set() this.graph["links"] = res.data.links.map((link) => ({ @@ -712,17 +715,17 @@ export const useGroupMemberStore = defineStore("groupMember", { type: node.groupId } }) - console.log(this.graph); + this.graph["newNodes"] = res.data?.newAddUser ?? [] } }, persist: true // 开启持久化 }) -// —— 时间门槛 —— -const T0 = "2024-06-19T07:57:46Z"; // 默认渲染出全部节点 -const TA = "2024-06-19T08:57:55Z"; // A 组异常开始 -const TB = "2024-06-19T10:58:03Z"; // B 组异常开始 -const TC = "2024-06-19T12:58:04Z"; // C 组异常开始 +// —— 时间门槛 —— +const T0 = "2024-06-19T07:57:46Z" // 默认渲染出全部节点 +const TA = "2024-06-19T08:57:55Z" // A 组异常开始 +const TB = "2024-06-19T10:58:03Z" // B 组异常开始 +const TC = "2024-06-19T12:58:04Z" // C 组异常开始 export const useAnomalousGroup = defineStore("anomalousGroup", { state: () => ({ @@ -868,37 +871,37 @@ export const useAnomalousGroup = defineStore("anomalousGroup", { graphData: { nodes: [ { id: "G01_A", type: "0", isAnomaly: false, label: "G01" }, - { id: "G02_A", type: "0", isAnomaly: true, label: "G02" }, + { id: "G02_A", type: "0", isAnomaly: true, label: "G02" }, { id: "G03_A", type: "0", isAnomaly: false, label: "G03" }, { id: "G04_A", type: "0", isAnomaly: false, label: "G04" }, { id: "G05_A", type: "0", isAnomaly: false, label: "G05" }, { id: "G06_A", type: "0", isAnomaly: false, label: "G06" }, - { id: "G07_A", type: "0", isAnomaly: true, label: "G07" }, + { id: "G07_A", type: "0", isAnomaly: true, label: "G07" }, { id: "G08_A", type: "0", isAnomaly: false, label: "G08" }, { id: "G09_A", type: "0", isAnomaly: false, label: "G09" }, { id: "G10_A", type: "0", isAnomaly: false, label: "G10" }, { id: "G11_A", type: "0", isAnomaly: false, label: "G11" }, { id: "G12_A", type: "0", isAnomaly: false, label: "G12" }, - + { id: "G01_B", type: "1", isAnomaly: false, label: "G01" }, { id: "G02_B", type: "1", isAnomaly: false, label: "G02" }, { id: "G03_B", type: "1", isAnomaly: false, label: "G03" }, - { id: "G04_B", type: "1", isAnomaly: true, label: "G04" }, + { id: "G04_B", type: "1", isAnomaly: true, label: "G04" }, { id: "G05_B", type: "1", isAnomaly: false, label: "G05" }, { id: "G06_B", type: "1", isAnomaly: false, label: "G06" }, { id: "G07_B", type: "1", isAnomaly: false, label: "G07" }, - { id: "G08_B", type: "1", isAnomaly: true, label: "G08" }, + { id: "G08_B", type: "1", isAnomaly: true, label: "G08" }, { id: "G09_B", type: "1", isAnomaly: false, label: "G09" }, { id: "G10_B", type: "1", isAnomaly: false, label: "G10" }, { id: "G11_B", type: "1", isAnomaly: false, label: "G11" }, { id: "G12_B", type: "1", isAnomaly: false, label: "G12" }, - + { id: "G01_C", type: "6", isAnomaly: false, label: "G01" }, { id: "G02_C", type: "6", isAnomaly: false, label: "G02" }, - { id: "G03_C", type: "6", isAnomaly: true, label: "G03" }, + { id: "G03_C", type: "6", isAnomaly: true, label: "G03" }, { id: "G04_C", type: "6", isAnomaly: false, label: "G04" }, { id: "G05_C", type: "6", isAnomaly: false, label: "G05" }, - { id: "G06_C", type: "6", isAnomaly: true, label: "G06" }, + { id: "G06_C", type: "6", isAnomaly: true, label: "G06" }, { id: "G07_C", type: "6", isAnomaly: false, label: "G07" }, { id: "G08_C", type: "6", isAnomaly: false, label: "G08" }, { id: "G09_C", type: "6", isAnomaly: false, label: "G09" }, @@ -927,7 +930,7 @@ export const useAnomalousGroup = defineStore("anomalousGroup", { { source: "G07_A", target: "G10_A", type: "0" }, { source: "G07_A", target: "G01_A", type: "0" }, { source: "G07_A", target: "G04_A", type: "0" }, - + /* —— 组内:B 环 —— */ { source: "G01_B", target: "G02_B", type: "1" }, { source: "G02_B", target: "G03_B", type: "1" }, @@ -948,7 +951,7 @@ export const useAnomalousGroup = defineStore("anomalousGroup", { { source: "G08_B", target: "G11_B", type: "1" }, { source: "G08_B", target: "G02_B", type: "1" }, { source: "G08_B", target: "G05_B", type: "1" }, - + /* —— 组内:C 环 —— */ { source: "G01_C", target: "G02_C", type: "6" }, { source: "G02_C", target: "G03_C", type: "6" }, @@ -969,18 +972,18 @@ export const useAnomalousGroup = defineStore("anomalousGroup", { { source: "G06_C", target: "G09_C", type: "6" }, { source: "G06_C", target: "G12_C", type: "6" }, { source: "G06_C", target: "G03_C", type: "6" }, - + /* —— 跨组连边 —— */ { source: "G02_A", target: "G04_B", type: "0" }, { source: "G07_A", target: "G08_B", type: "0" }, { source: "G01_A", target: "G05_B", type: "0" }, { source: "G05_A", target: "G10_B", type: "0" }, - + { source: "G04_B", target: "G03_C", type: "1" }, { source: "G08_B", target: "G06_C", type: "1" }, { source: "G02_B", target: "G09_C", type: "1" }, { source: "G11_B", target: "G01_C", type: "1" }, - + { source: "G03_C", target: "G02_A", type: "6" }, { source: "G06_C", target: "G07_A", type: "6" }, { source: "G04_C", target: "G09_A", type: "6" }, @@ -995,12 +998,12 @@ export const useAnomalousGroup = defineStore("anomalousGroup", { } }, graphAbnormalData: { - groupA: ["G02_A", "G07_A"], - groupB: ["G04_B", "G08_B"], - groupC: ["G03_C", "G06_C"], - abnormalNodesT1: ["G02_A", "G07_A"], - abnormalNodesT2: ["G04_B", "G08_B"], - abnormalNodesT3: ["G02_A", "G07_A", "G04_B", "G08_B", "G03_C", "G06_C"] + groupA: ["G02_A", "G07_A"], + groupB: ["G04_B", "G08_B"], + groupC: ["G03_C", "G06_C"], + abnormalNodesT1: ["G02_A", "G07_A"], + abnormalNodesT2: ["G04_B", "G08_B"], + abnormalNodesT3: ["G02_A", "G07_A", "G04_B", "G08_B", "G03_C", "G06_C"] } }), actions: { @@ -1043,7 +1046,7 @@ export const useAnomalousGroup = defineStore("anomalousGroup", { async initializeAbnormalGroupPosts(time = "2024-06-19T07:57:46Z") { const res = await getAbnormalGroupBehaviorPosts(time) if (res.code === 200) { - this.posts = res.data.map((item => ({ + this.posts = res.data.map((item) => ({ id: item.id, abnormalGroup: item.abnormalGroup, explanation: item.explanation, @@ -1052,10 +1055,8 @@ export const useAnomalousGroup = defineStore("anomalousGroup", { JS: parseFloat(item.js), CUSUM: parseFloat(item.cusum), KS: parseFloat(item.ks) - }))) - + })) } - }, // 异常互动详情-右上 @@ -1067,16 +1068,16 @@ export const useAnomalousGroup = defineStore("anomalousGroup", { }, // 用于画中间组件的圆 async initialGraphByUtcTime(utcIso) { - this.currentUtc = utcIso; + this.currentUtc = utcIso // 1) 复制 nodes 并上色 - const nodes = this.graphData.nodes.map(n => { + const nodes = this.graphData.nodes.map((n) => { return { id: n.id, label: n.label, type: n.type, // 0=A, 1=B, 6=C(组件里 colorMap 已按这三个上色/分组) isAnomaly: n.isAnomaly - }; - }); + } + }) this.graph["nodes"] = nodes @@ -1088,14 +1089,13 @@ export const useAnomalousGroup = defineStore("anomalousGroup", { } return colorMap[type] } - - const links = this.graphData.links.map(l => ({ + + const links = this.graphData.links.map((l) => ({ source: l.source, target: l.target, - color: setColor(l.type), + color: setColor(l.type) })) this.graph["links"] = links - } }, persist: true // 开启持久化 diff --git a/src/views/GroupEvolution/component/groupGraph.vue b/src/views/GroupEvolution/component/groupGraph.vue index 134ee99..32a0021 100644 --- a/src/views/GroupEvolution/component/groupGraph.vue +++ b/src/views/GroupEvolution/component/groupGraph.vue @@ -144,7 +144,67 @@ const runDiffForceLayout = (layoutConfig, layoutType, isAsync) => { } const handleAnomalousGroup = () => { - console.log(storeId) + // 当前时间从 store 取;没有就用 T0 + const now = props.store.currentUtc + const TA = "2024-06-19T08:57:55Z" // A + const TB = "2024-06-19T10:58:03Z" // B + const TC = "2024-06-19T12:58:04Z" // C + // 组色(与你现有 colorMap 一致) + const GROUP_ALPHA = 0.3 + const RED = "220,50,60" + // 时间门控:达到阈值就把各组异常节点染红 + const shouldA = now >= TA + const shouldB = now >= TB + const shouldC = now >= TC + if (shouldA) { + graphVis.nodes = graphVis.nodes.map((n) => { + if (props.store.graphAbnormalData.groupA.includes(n.id)) { + n.fillColor = RED + } + return n + }) + graphVis.addNodesInGroup( + graphVis.nodes.filter((n) => props.store.graphAbnormalData.groupA.includes(n.id)), + { + shape: "circle", + color: RED, + alpha: GROUP_ALPHA + } + ) + } + if (shouldB) { + graphVis.nodes = graphVis.nodes.map((n) => { + if (props.store.graphAbnormalData.groupB.includes(n.id)) { + n.fillColor = RED + } + return n + }) + graphVis.addNodesInGroup( + graphVis.nodes.filter((n) => props.store.graphAbnormalData.groupB.includes(n.id)), + { + shape: "circle", + color: RED, + alpha: GROUP_ALPHA + } + ) + } + if (shouldC) { + graphVis.nodes = graphVis.nodes.map((n) => { + if (props.store.graphAbnormalData.groupC.includes(n.id)) { + n.fillColor = RED + } + return n + }) + graphVis.addNodesInGroup( + graphVis.nodes.filter((n) => props.store.graphAbnormalData.groupC.includes(n.id)), + { + shape: "circle", + color: RED, + alpha: GROUP_ALPHA + } + ) + } + graphVis.autoGroupLayout(graphVis.nodes) } new Map([ @@ -191,91 +251,6 @@ const clusterAnalyze = () => { }) }) graphVis.autoGroupLayout(graphVis.nodes) - - function handleGroupDiscoveryDiff() { - console.log(storeId) - } - - function handleGroupStructureDiff() { - console.log(storeId) - } - - function handleGroupMemberDiff() { - console.log(storeId) - } - - function handleAnomalousGroup() { - console.log(storeId) - - // 当前时间从 store 取;没有就用 T0 - const now = (props.store.currentUtc); - - const TA = "2024-06-19T08:57:55Z"; // A - const TB = "2024-06-19T10:58:03Z"; // B - const TC = "2024-06-19T12:58:04Z"; // C - - // 组色(与你现有 colorMap 一致) - const GROUP_ALPHA = 0.30; - - const RED = "220,50,60"; - - // 时间门控:达到阈值就把各组异常节点染红 - const shouldA = now >= TA; - const shouldB = now >= TB; - const shouldC = now >= TC; - - if(shouldA) { - graphVis.nodes = graphVis.nodes.map(n => { - if(props.store.graphAbnormalData.groupA.includes(n.id)) { - n.fillColor = RED; - } - return n; - }) - console.log(graphVis.nodes) - graphVis.addNodesInGroup(graphVis.nodes.filter(n => props.store.graphAbnormalData.groupA.includes(n.id)), { - shape: "circle", - color: RED, - alpha: GROUP_ALPHA - }) - - } - if(shouldB) { - graphVis.nodes = graphVis.nodes.map(n => { - if(props.store.graphAbnormalData.groupB.includes(n.id)) { - n.fillColor = RED; - } - return n; - }) - graphVis.addNodesInGroup(graphVis.nodes.filter(n => props.store.graphAbnormalData.groupB.includes(n.id)), { - shape: "circle", - color: RED, - alpha: GROUP_ALPHA - }) - - } - if(shouldC) { - graphVis.nodes = graphVis.nodes.map(n => { - if(props.store.graphAbnormalData.groupC.includes(n.id)) { - n.fillColor = RED; - } - return n; - }) - graphVis.addNodesInGroup(graphVis.nodes.filter(n => props.store.graphAbnormalData.groupC.includes(n.id)), { - shape: "circle", - color: RED, - alpha: GROUP_ALPHA - }) - } - graphVis.autoGroupLayout(graphVis.nodes); - } - - new Map([ - ["groupDiscovery", () => handleGroupDiscoveryDiff()], - ["groupStructure", () => handleGroupStructureDiff()], - ["groupMember", () => handleGroupMemberDiff()], - ["anomalousGroup", () => handleAnomalousGroup()] - ]).get(storeId)?.() - // graphVis.selectedEdge(graphVis.links[0]) } // 仅对“异常群体模块”生效:时间变化时强制重绘一次