import { defineStore } from "pinia" import nodePrefix from "@/assets/images/groupEvolution/node-prefix.png" import edgePrefix from "@/assets/images/groupEvolution/edge-prefix.png" import splitImg from "@/assets/images/groupMember/splitImg.png" import mergeImg from "@/assets/images/groupMember/mergeImg.png" import shrinkImg from "@/assets/images/groupMember/shrinkImg.png" import expamdImg from "@/assets/images/groupMember/expamdImg.png" import defaultAvatar from "@/assets/images/avatar/default.png" import { getGroupEvolutionGroupList, getGroupEvolutionGroupScaleChart, getGroupEvolutionTimeLine, getPostByUtcTime, getGroupMemberInfo, getStructuralEvolutionChart, getStructuralEvolutionAnalysisChart, getStructuralEvolutionAnalysisTimeLine, getStructuralEvolutionAnalysisInfoList, getStructuralEvolutionAnalysisPost, getGroupMemberInfoList, getGroupMemberTimeLine, getGroupMemberChart, getGroupMemberEvolutionInfoByTime, getGroupMemberEvolutionAnalysisChart, getStructuralEvolutionAnalysisGraph, getGroupMemberEvolutionAnalysisGraph, // 4.异常群体捕捉 getAbnormalGroupTimeLine, getAbnormalGroupList, getAbnormalGroupInteractionChart, getAbnormalGroupBehaviorPosts, getAbnormalGroupBehaviorDetail, getRelationGraphByUtcTime } from "@/service/api/groupEvolution" import { TansTimestamp, utcStringToHHMMSS, getMaxCeiled, parsePercentage } from "@/utils/transform" import groupDiscoveryTitle from "@/assets/images/groupEvolution/graph-title.png" import groupStructTitle from "@/assets/images/head/evolutionStruct-title.png" import groupAnalysis from "@/assets/images/head/groupAnlysis-title.png" import groupAbnormal from "@/assets/images/head/groupAnlysis-title.png" export const useGroupDiscoveryStore = defineStore("groupDiscovery", { state: () => ({ groupList: [], graphTitle: groupDiscoveryTitle, chartData: {}, timeList: [], graph: {}, groupMemberInfo: {}, chartsData: { topSelfMedia: { xAxis: [ "15:57:46", "16:57:55", "17:57:32", "18:58:03", "19:58:03", "20:58:04", "21:57:47", "22:58:12" ], yAxis: [0.5, 1.0, 1.5, 2.0, 2.5], data: [1.0, 0.99, 1.0, 1.0, 1.01, 2.03, 1.2, 0.99] }, officialMedia: { xAxis: [ "15:57:46", "16:57:55", "17:57:32", "18:58:03", "19:58:03", "20:58:04", "21:57:47", "22:58:12" ], yAxis: [0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2], data: [1.0, 0.99, 1.0, 1.0, 1.01, 2.03, 1.2, 0.99] }, ordinaryMedia: { xAxis: [ "15:57:46", "16:57:55", "17:57:32", "18:58:03", "19:58:03", "20:58:04", "21:57:47", "22:58:12" ], yAxis: [0, 1.0, 2.0, 3.0], data: [1.08, 2.54, 1.47, 1.03, 0.98, 0.99, 1.0, 1.12] } }, wordCloudData: [ { text: "主权权益", top: 115.5, left: 215.5, width: 80, height: 22, fontSize: 13, opacity: 1 }, { text: "局座预言", top: 80, left: 69.5, width: 73, height: 22, fontSize: 12, opacity: 0.7 }, { text: "吃瓜", top: 72.5, left: 132.5, width: 50, height: 22, fontSize: 12, opacity: 1 }, { text: "中国海警", top: 140, left: 212.5, width: 130, height: 40, fontSize: 22, opacity: 0.8 }, { text: "菲律宾", top: 150, left: 50, width: 81, height: 22, fontSize: 14, opacity: 0.8 }, { text: "手指", top: 200.5, left: 38.5, width: 73, height: 19, fontSize: 12, opacity: 0.7 }, { text: "装甲船", top: 50, left: 160.5, width: 73, height: 19, fontSize: 12, opacity: 0.7 }, { text: "登检", top: 211.5, left: 143.5, width: 50, height: 19, fontSize: 12, opacity: 1 }, { text: "执法", top: 176.5, left: 15.5, width: 49, height: 19, fontSize: 12, opacity: 0.8 }, { text: "现场画面", top: 110, left: 26, width: 90, height: 22, fontSize: 14, opacity: 1 }, { text: "渔民", top: 103.5, left: 95.5, width: 49, height: 19, fontSize: 12, opacity: 0.8 }, { text: "包夹", top: 57.5, left: 72.5, width: 49, height: 19, fontSize: 12, opacity: 0.6 }, { text: "枪支", top: 77.5, left: 264.5, width: 49, height: 19, fontSize: 12, opacity: 0.7 }, { text: "解决", top: 195.5, left: 287.5, width: 49, height: 19, fontSize: 12, opacity: 0.8 }, { text: "大刀长矛", top: 186, left: 200.5, width: 70, height: 19, fontSize: 12, opacity: 0.8 } ], posts: [] }), actions: { //获取群体列表数据 async initializeGroupList(time = "") { const res = await getGroupEvolutionGroupList(time) if (res.code != 200) return const iconMap = { 节点数: nodePrefix, 连边数: edgePrefix } this.groupList = res.data this.groupList.forEach((item) => { item.list = item.list.map((statistic) => ({ ...statistic, iconImg: iconMap[statistic.name] })) }) }, //获取群体规模演化图数据 async initializeGroupScaleChart() { const res = await getGroupEvolutionGroupScaleChart() if (res.code != 200) return let resultObj = {} const themeMap = { 群体一: "#00d6da", 群体二: "#fddc33", 群体三: "#32b6fb" } resultObj["xAxisData"] = res.data.timeList.map((item) => TansTimestamp(item, "HH:mm:ss")) resultObj["yAxisRange"] = res.data.scale resultObj["seriesList"] = [] // 定义明确的群体顺序 const groupOrder = ["群体一", "群体二", "群体三"] groupOrder.forEach((key) => { if (res.data.data[key]) { resultObj["seriesList"].push({ name: key, themeColor: themeMap[key], data: res.data.data[key] }) } }) this.chartData = resultObj }, //获取时间轴参数 async initialGraphTimestamp() { const res = await getGroupEvolutionTimeLine() if (res.code != 200) return this.timeList = res.data }, async initialGraphByUtcTime(utcTime = "") { const setColor = (groupId) => { const colorMap = { 0: "50,141,120", 1: "133,129,48", 6: "12,112,144" } return colorMap[parseInt(groupId)] } const res = await getRelationGraphByUtcTime(utcTime) if (res.code != 200) return const newSet = new Set() this.graph["links"] = res.data.links.map((link) => ({ source: link.source, target: link.target, color: setColor(link.type) })) this.graph["nodes"] = res.data.nodes .filter((node) => { if (!newSet.has(node.name)) { newSet.add(node.name) return true } return false }) .map((node) => { return { id: node.name, label: node.name, type: node.groupId } }) }, // 通过时间来获取帖文列表 //根据时间参数获取贴文数据 async initialPostByUtcTime(utcTime) { const res = await getPostByUtcTime(utcTime) if (res.code != 200) return this.posts = res.data }, // 悬浮显示群体中的成员 async initialGroupMemberInfo(time = "2024-06-19T07:57:46Z") { const res = await getGroupMemberInfo(time) if (res.code != 200) return const groupOne = [] const groupTwo = [] const groupThree = [] res.data.forEach((item) => { if (item.groupId == 0) { groupOne.push(item.userId) } else if (item.groupId == 1) { groupTwo.push(item.userId) } else if (item.groupId == 6) { groupThree.push(item.userId) } }) this.groupMemberInfo = { 0: groupOne, 1: groupTwo, 6: groupThree } } }, persist: true // 开启持久化 }) export const useGroupStructureStore = defineStore("groupStructure", { state: () => ({ groupList: [], groupMemberInfo: {}, graphTitle: groupStructTitle, graph: {}, timeList: [], chartData: {}, chartsData: {}, wordCloudData: [ { text: "主权权益", top: 115.5, left: 215.5, width: 80, height: 22, fontSize: 13, opacity: 1 }, { text: "局座预言", top: 80, left: 69.5, width: 73, height: 22, fontSize: 12, opacity: 0.7 }, { text: "吃瓜", top: 72.5, left: 132.5, width: 50, height: 22, fontSize: 12, opacity: 1 }, { text: "中国海警", top: 140, left: 212.5, width: 130, height: 40, fontSize: 22, opacity: 0.8 }, { text: "菲律宾", top: 150, left: 50, width: 81, height: 22, fontSize: 14, opacity: 0.8 }, { text: "手指", top: 200.5, left: 38.5, width: 73, height: 19, fontSize: 12, opacity: 0.7 }, { text: "装甲船", top: 50, left: 160.5, width: 73, height: 19, fontSize: 12, opacity: 0.7 }, { text: "登检", top: 211.5, left: 143.5, width: 50, height: 19, fontSize: 12, opacity: 1 }, { text: "执法", top: 176.5, left: 15.5, width: 49, height: 19, fontSize: 12, opacity: 0.8 }, { text: "现场画面", top: 110, left: 26, width: 90, height: 22, fontSize: 14, opacity: 1 }, { text: "渔民", top: 103.5, left: 95.5, width: 49, height: 19, fontSize: 12, opacity: 0.8 }, { text: "包夹", top: 57.5, left: 72.5, width: 49, height: 19, fontSize: 12, opacity: 0.6 }, { text: "枪支", top: 77.5, left: 264.5, width: 49, height: 19, fontSize: 12, opacity: 0.7 }, { text: "解决", top: 195.5, left: 287.5, width: 49, height: 19, fontSize: 12, opacity: 0.8 }, { text: "大刀长矛", top: 186, left: 200.5, width: 70, height: 19, fontSize: 12, opacity: 0.8 } ], posts: [ { id: 1, time: "2024-01-04 0:03:16", groupCategory: "群体一", innerEdgeAddCount: 8, outerEdgeAddCount: 2 }, { id: 2, time: "2024-02-03 12:58:53", groupCategory: "群体一", innerEdgeAddCount: 8, outerEdgeAddCount: 2 }, { id: 3, time: "2024-02-22 17:13:44", groupCategory: "群体二", innerEdgeAddCount: 13, outerEdgeAddCount: 3 }, { id: 4, time: "2024-02-23 17:54:46", groupCategory: "群体三", innerEdgeAddCount: 1, outerEdgeAddCount: 2 }, { id: 5, time: "2024-03-14 09:58:12", groupCategory: "群体三", innerEdgeAddCount: 1, outerEdgeAddCount: 2 }, { id: 6, time: "2024-03-23 21:20:40", groupCategory: "群体三", innerEdgeAddCount: 1, outerEdgeAddCount: 2 }, { id: 7, time: "2024-03-23 21:42:36", groupCategory: "群体三", innerEdgeAddCount: 1, outerEdgeAddCount: 2 }, { id: 8, time: "2024-04-06 18:17:30", groupCategory: "群体三", innerEdgeAddCount: 1, outerEdgeAddCount: 2 }, { id: 9, time: "2024-04-06 19:19:50", groupCategory: "群体三", innerEdgeAddCount: 1, outerEdgeAddCount: 2 }, { id: 10, time: "2024-05-16 00:22:18", groupCategory: "群体三", innerEdgeAddCount: 1, outerEdgeAddCount: 2 } ] }), actions: { // 初始化timeList async initializeStructuralEvolutionAnalysisTimeLine() { const res = await getStructuralEvolutionAnalysisTimeLine() this.timeList = res.data }, // 初始化群体结构演化分析信息列表 async initializeStructuralEvolutionAnalysisInfoList(time = "2024-06-19T07:57:46Z") { const res = await getStructuralEvolutionAnalysisInfoList(time) this.groupList = res.data.map((item) => ({ id: item.id, type: item.type, name: item.name, focusedTopic: item.focusedTopic, innerNum: parsePercentage(item.innerNum), outerNum: parsePercentage(item.outerNum) })) }, // 悬浮显示群体中的成员 async initialGroupMemberInfo(time = "2024-06-19T07:57:46Z") { const res = await getGroupMemberInfo(time) if (res.code != 200) return const groupOne = [] const groupTwo = [] const groupThree = [] res.data.forEach((item) => { if (item.groupId == 0) { groupOne.push(item.userId) } else if (item.groupId == 1) { groupTwo.push(item.userId) } else if (item.groupId == 6) { groupThree.push(item.userId) } }) this.groupMemberInfo = { 0: groupOne, 1: groupTwo, 6: groupThree } }, // 初始化全局连通性演化图--左下方 async initializeStructuralEvolutionChart() { const res = await getStructuralEvolutionChart() this.chartData = { xAxisData: res.data.xaxisData.map((item) => utcStringToHHMMSS(item)), seriesList: [ { name: "", data: res.data.seriesList[0].data, themeColor: "#2AB8FD" } ], yAxisRange: { min: 0, max: 1, interval: 0.2 } } }, // 初始化群体结构演化分析图表--右上方 async initializeStructuralEvolutionAnalysisChart() { const res = await getStructuralEvolutionAnalysisChart() const topSelfMedia = res.data.topSelfMedia.map((item) => ({ id: item.id, name: item.name, chart: { xAxisData: item.chart.xaxisData.map((item) => utcStringToHHMMSS(item)), yAxisRange: { min: item.name === "内部密度指数演化" ? 20.0 : 0, max: item.name === "内部密度指数演化" ? 20.5 : Math.ceil(item.chart.yaxisRange.max / 5) * 5, interval: item.name === "内部密度指数演化" ? 0.1 : Math.ceil(item.chart.yaxisRange.max / 5) }, seriesList: item.chart.seriesList.map((item) => ({ data: item.data, name: item.name, themeColor: "#2AB8FD" })) } })) const officalMedia = res.data.officalMedia.map((item) => ({ id: item.id, name: item.name, chart: { xAxisData: item.chart.xaxisData.map((item) => utcStringToHHMMSS(item)), yAxisRange: { min: item.name === "内部密度指数演化" ? 20.0 : 0, max: item.name === "内部密度指数演化" ? 20.5 : Math.ceil(item.chart.yaxisRange.max / 5) * 5, interval: item.name === "内部密度指数演化" ? 0.1 : Math.ceil(item.chart.yaxisRange.max / 5) }, seriesList: item.chart.seriesList.map((item) => ({ data: item.data, name: item.name, themeColor: "#2AB8FD" })) } })) const ordinaryMedia = res.data.ordinaryMedia.map((item) => ({ id: item.id, name: item.name, chart: { xAxisData: item.chart.xaxisData.map((item) => utcStringToHHMMSS(item)), yAxisRange: { min: item.name === "内部密度指数演化" ? 20.0 : 0, max: item.name === "内部密度指数演化" ? 20.5 : Math.ceil(item.chart.yaxisRange.max / 5) * 5, interval: item.name === "内部密度指数演化" ? 0.1 : Math.ceil(item.chart.yaxisRange.max / 5) }, seriesList: item.chart.seriesList.map((item) => ({ data: item.data, name: item.name, themeColor: "#2AB8FD" })) } })) this.chartsData = { topSelfMedia, officalMedia, ordinaryMedia } }, async initialGraphByUtcTime(utcTime = "") { const setColor = (groupId) => { const colorMap = { 0: "50,141,120", 1: "133,129,48", 6: "12,112,144" } return colorMap[parseInt(groupId)] } const res = await getStructuralEvolutionAnalysisGraph(utcTime) if (res.code != 200) return const newSet = new Set() this.graph["links"] = res.data.links.map((link) => ({ source: link.source, target: link.target, color: setColor(link.type) })) this.graph["nodes"] = res.data.nodes .filter((node) => { if (!newSet.has(node.name)) { newSet.add(node.name) return true } return false }) .map((node) => { return { id: node.name, label: node.name, type: node.groupId } }) this.graph["newLinks"] = res.data?.newAddRelation ?? [] }, // 初始化群体结构演化分析的群体演化信息-中下-随时间轴变化 async initializeStructuralPost(time = "2024-06-19T07:57:46Z") { const res = await getStructuralEvolutionAnalysisPost(time) this.posts = res.data.map((item) => ({ id: item.id, time: TansTimestamp(item.time, "YYYY.MM.DD HH:mm:ss"), groupCategory: item.groupCategory, innerEdgeAddCount: item.innerEdgeAddCount, outerEdgeAddCount: item.outerEdgeAddCount })) } }, persist: true // 开启持久化 }) export const useGroupMemberStore = defineStore("groupMember", { state: () => ({ groupList: [], groupMemberInfo: {}, graphTitle: groupAnalysis, timeList: [], graph: {}, chartData: {}, chartsData: {}, posts: [], wordCloudData: [ { text: "主权权益", top: 115.5, left: 215.5, width: 80, height: 22, fontSize: 13, opacity: 1 }, { text: "局座预言", top: 80, left: 69.5, width: 73, height: 22, fontSize: 12, opacity: 0.7 }, { text: "吃瓜", top: 72.5, left: 132.5, width: 50, height: 22, fontSize: 12, opacity: 1 }, { text: "中国海警", top: 140, left: 212.5, width: 130, height: 40, fontSize: 22, opacity: 0.8 }, { text: "菲律宾", top: 150, left: 50, width: 81, height: 22, fontSize: 14, opacity: 0.8 }, { text: "手指", top: 200.5, left: 38.5, width: 73, height: 19, fontSize: 12, opacity: 0.7 }, { text: "装甲船", top: 50, left: 160.5, width: 73, height: 19, fontSize: 12, opacity: 0.7 }, { text: "登检", top: 211.5, left: 143.5, width: 50, height: 19, fontSize: 12, opacity: 1 }, { text: "执法", top: 176.5, left: 15.5, width: 49, height: 19, fontSize: 12, opacity: 0.8 }, { text: "现场画面", top: 110, left: 26, width: 90, height: 22, fontSize: 14, opacity: 1 }, { text: "渔民", top: 103.5, left: 95.5, width: 49, height: 19, fontSize: 12, opacity: 0.8 }, { text: "包夹", top: 57.5, left: 72.5, width: 49, height: 19, fontSize: 12, opacity: 0.6 }, { text: "枪支", top: 77.5, left: 264.5, width: 49, height: 19, fontSize: 12, opacity: 0.7 }, { text: "解决", top: 195.5, left: 287.5, width: 49, height: 19, fontSize: 12, opacity: 0.8 }, { text: "大刀长矛", top: 186, left: 200.5, width: 70, height: 19, fontSize: 12, opacity: 0.8 } ] }), actions: { // 获取时间轴 async initializeGroupMemberTimeLine() { const res = await getGroupMemberTimeLine() this.timeList = res.data }, // 群体成员演化信息列表-左上 async initializeGroupList(time = "2024-06-19T07:57:46Z") { const res = await getGroupMemberInfoList(time) const groupList = res.data.map((item) => ({ id: item.id, type: item.type, focusedTopic: item.focusedTopic, value: item.value.map((item) => item.toFixed(2)) // value: item.value.map(item => (item * 100 + 20).toFixed(2)) })) this.groupList = groupList }, // 悬浮显示群体中的成员 async initialGroupMemberInfo(time = "2024-06-19T07:57:46Z") { const res = await getGroupMemberInfo(time) if (res.code != 200) return const groupOne = [] const groupTwo = [] const groupThree = [] res.data.forEach((item) => { if (item.groupId == 0) { groupOne.push(item.userId) } else if (item.groupId == 1) { groupTwo.push(item.userId) } else if (item.groupId == 6) { groupThree.push(item.userId) } }) this.groupMemberInfo = { 0: groupOne, 1: groupTwo, 6: groupThree } }, async initializeGroupMemberChart() { const res = await getGroupMemberChart() const xAxisData = res.data.xaxisData.map((item) => utcStringToHHMMSS(item)) const yAxisRange = res.data.yaxisRange const themeColors = ["#2AB8FD", "#02D7DA", "#FFDA09", "#EB57B0"] const seriesList = res.data.seriesList.map((item) => ({ data: item.data.map((item) => item.toFixed(2)), name: item.name, themeColor: themeColors[item.id - 1] })) this.chartData = { xAxisData, yAxisRange, seriesList } }, async initialPostByUtcTime(utcTime) { const res = await getGroupMemberEvolutionInfoByTime(utcTime) this.posts = res.data }, async initializeGroupMemberEvolutionAnalysisChart() { const res = await getGroupMemberEvolutionAnalysisChart() const themeColors = { 分裂演化: "#2AB8FD", 合并演化: "#02D7DA", 收缩演化: "#FFDA09", 扩展演化: "#EB57B0" } const topSelfMedia = res.data.topSelfMedia.map((item) => ({ id: item.id, name: item.name, chart: { xAxisData: item.chart.xaxisData.map((item) => utcStringToHHMMSS(item)), yAxisRange: { min: item.name === "合并演化" || item.name === "扩展演化" ? 19 : 0, max: item.name === "合并演化" || item.name === "扩展演化" ? 21 : Math.ceil(item.chart.yaxisRange.max / 5) * 5, interval: item.name === "合并演化" || item.name === "扩展演化" ? 0.4 : Math.ceil(item.chart.yaxisRange.max / 5) }, seriesList: item.chart.seriesList.map((item) => ({ data: item.data.map((item) => item.toFixed(2)), name: item.name, themeColor: themeColors[item.name] })) } })) const officalMedia = res.data.officalMedia.map((item) => ({ id: item.id, name: item.name, chart: { xAxisData: item.chart.xaxisData.map((item) => utcStringToHHMMSS(item)), yAxisRange: { min: item.name === "合并演化" || item.name === "扩展演化" ? 19.0 : 0, max: item.name === "合并演化" || item.name === "扩展演化" ? 21.0 : Math.ceil(item.chart.yaxisRange.max / 5) * 5, interval: item.name === "合并演化" || item.name === "扩展演化" ? 0.4 : Math.ceil(item.chart.yaxisRange.max / 5) }, seriesList: item.chart.seriesList.map((item) => ({ data: item.data.map((item) => item.toFixed(2)), name: item.name, themeColor: themeColors[item.name] })) } })) const ordinaryMedia = res.data.ordinaryMedia.map((item) => ({ id: item.id, name: item.name, chart: { xAxisData: item.chart.xaxisData.map((item) => utcStringToHHMMSS(item)), yAxisRange: { min: item.name === "合并演化" ? 19 : 0, max: item.name === "合并演化" ? 21 : Math.ceil(item.chart.yaxisRange.max / 5) * 5, interval: item.name === "合并演化" ? 0.4 : Math.ceil(item.chart.yaxisRange.max / 5) }, seriesList: item.chart.seriesList.map((item) => ({ data: item.data.map((item) => item.toFixed(2)), name: item.name, themeColor: themeColors[item.name] })) } })) this.chartsData = { topSelfMedia: topSelfMedia, officalMedia: officalMedia, ordinaryMedia: ordinaryMedia } }, async initialGraphByUtcTime(utcTime = "") { const setColor = (groupId) => { const colorMap = { 0: "50,141,120", 1: "133,129,48", 6: "12,112,144" } return colorMap[parseInt(groupId)] } const res = await getGroupMemberEvolutionAnalysisGraph(utcTime) if (res.code != 200) return const newSet = new Set() this.graph["links"] = res.data.links.map((link) => ({ source: link.source, target: link.target, color: setColor(link.type) })) this.graph["nodes"] = res.data.nodes .filter((node) => { if (!newSet.has(node.name)) { newSet.add(node.name) return true } return false }) .map((node) => { return { id: node.name, label: node.name, type: node.groupId } }) 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 组异常开始 export const useAnomalousGroup = defineStore("anomalousGroup", { state: () => ({ groupList: [], graph: {}, timeList: [], graphTitle: groupAbnormal, wordCloudData: [ { text: "局座", top: 115.5, left: 220.5, width: 80, height: 40, fontSize: 28, opacity: 1 }, { text: "折叠屏", top: 160.5, left: 69.5, width: 105, height: 35, fontSize: 20, opacity: 1 }, { text: "蹬鼻子上脸", top: 50.5, left: 132.5, width: 90, height: 22, fontSize: 12, opacity: 1 }, { text: "菲律宾", top: 171.5, left: 200.5, width: 81, height: 22, fontSize: 14, opacity: 0.8 }, { text: "中国海警", top: 120.5, left: 30.5, width: 100, height: 24, fontSize: 16, opacity: 1 }, { text: "船", top: 223.5, left: 230.5, width: 50, height: 22, fontSize: 14, opacity: 0.8 }, { text: "斧头", top: 200.5, left: 38.5, width: 40, height: 19, fontSize: 12, opacity: 0.7 }, { text: "执法", top: 223.5, left: 130.5, width: 60, height: 19, fontSize: 12, opacity: 0.7 }, { text: "登检", top: 200.5, left: 143.5, width: 60, height: 19, fontSize: 12, opacity: 1 }, { text: "蹲下", top: 176.5, left: 15.5, width: 49, height: 19, fontSize: 12, opacity: 0.8 }, { text: "邦邦邦邦", top: 87.5, left: 20.5, width: 106, height: 22, fontSize: 14, opacity: 1 } /* { text: "抱头", top: 103.5, left: 95.5, width: 49, height: 19, fontSize: 12, opacity: 0.8 }, { text: "包夹", top: 57.5, left: 72.5, width: 49, height: 19, fontSize: 12, opacity: 0.6 }, { text: "吃瓜", top: 77.5, left: 264.5, width: 49, height: 19, fontSize: 12, opacity: 0.7 }, { text: "手指", top: 195.5, left: 287.5, width: 49, height: 19, fontSize: 12, opacity: 0.8 } */ ], abnormalContentList: [], chartData: { xAxisData: ["t0", "t1", "t2", "t3", "t4", "t5", "t6"], yAxisRange: { min: 0, max: 5, interval: 1 }, seriesList: [ { name: "社团组一", themeColor: "#2AB8FD", data: [0, 5, 4, 3, 0, 5, 0] }, { name: "社团组二", themeColor: "#02D7DA", data: [3, 0, 1, 0, 3, 5, 0] }, { name: "社团组三", themeColor: "#FFDA09", data: [5, 0, 4, 0, 3, 0, 0] } ] }, posts: [ { id: 1, abnormalGroup: "G02与G07互动方式出现显著异常", explanation: "持续异常行为已累积显著,疑似某组织突然发动“”信息攻击“或”舆论战“", firstDiscoverTime: "2024.06.20", duration: 6, JS: 0.3, CUSUM: 6.21, KS: 0.02 }, { id: 2, abnormalGroup: "GO4与G08互动方式出现显著异常", firstDiscoverTime: "2024.06.23", duration: 4, explanation: "疑似“统一指令”或“操控集群”在某时段被同时激活", JS: 0.41, CUSUM: 5.0, KS: 0.05 }, { id: 3, abnormalGroup: "G02与G07互动方式出现显著异常", firstDiscoverTime: "2024.07.25", duration: 6, explanation: "疑似群体间短时高强度联动", JS: 0.41, CUSUM: 5.0, KS: 0.02 } ], currentUtc: T0, graphData: { nodes: [ { id: "G01_A", type: "0", isAnomaly: false, label: "G01" }, { 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: "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: "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: "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: "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: "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" }, { id: "G10_C", type: "6", isAnomaly: false, label: "G10" }, { id: "G11_C", type: "6", isAnomaly: false, label: "G11" }, { id: "G12_C", type: "6", isAnomaly: false, label: "G12" } ], links: [ /* —— 组内:A 环 —— */ { source: "G01_A", target: "G02_A", type: "0" }, { source: "G02_A", target: "G03_A", type: "0" }, { source: "G03_A", target: "G04_A", type: "0" }, { source: "G04_A", target: "G05_A", type: "0" }, { source: "G05_A", target: "G06_A", type: "0" }, { source: "G06_A", target: "G07_A", type: "0" }, { source: "G07_A", target: "G08_A", type: "0" }, { source: "G08_A", target: "G09_A", type: "0" }, { source: "G09_A", target: "G10_A", type: "0" }, { source: "G10_A", target: "G11_A", type: "0" }, { source: "G11_A", target: "G12_A", type: "0" }, { source: "G12_A", target: "G01_A", type: "0" }, /* —— A 组:异常节点额外连边(突出)—— */ { source: "G02_A", target: "G05_A", type: "0" }, { source: "G02_A", target: "G08_A", type: "0" }, { source: "G02_A", target: "G11_A", type: "0" }, { 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" }, { source: "G03_B", target: "G04_B", type: "1" }, { source: "G04_B", target: "G05_B", type: "1" }, { source: "G05_B", target: "G06_B", type: "1" }, { source: "G06_B", target: "G07_B", type: "1" }, { source: "G07_B", target: "G08_B", type: "1" }, { source: "G08_B", target: "G09_B", type: "1" }, { source: "G09_B", target: "G10_B", type: "1" }, { source: "G10_B", target: "G11_B", type: "1" }, { source: "G11_B", target: "G12_B", type: "1" }, { source: "G12_B", target: "G01_B", type: "1" }, /* —— B 组:异常节点额外连边 —— */ { source: "G04_B", target: "G07_B", type: "1" }, { source: "G04_B", target: "G10_B", type: "1" }, { source: "G04_B", target: "G01_B", type: "1" }, { 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" }, { source: "G03_C", target: "G04_C", type: "6" }, { source: "G04_C", target: "G05_C", type: "6" }, { source: "G05_C", target: "G06_C", type: "6" }, { source: "G06_C", target: "G07_C", type: "6" }, { source: "G07_C", target: "G08_C", type: "6" }, { source: "G08_C", target: "G09_C", type: "6" }, { source: "G09_C", target: "G10_C", type: "6" }, { source: "G10_C", target: "G11_C", type: "6" }, { source: "G11_C", target: "G12_C", type: "6" }, { source: "G12_C", target: "G01_C", type: "6" }, /* —— C 组:异常节点额外连边 —— */ { source: "G03_C", target: "G06_C", type: "6" }, { source: "G03_C", target: "G09_C", type: "6" }, { source: "G03_C", target: "G12_C", type: "6" }, { 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" }, { source: "G12_C", target: "G06_A", type: "6" } ], meta: { groups: [ { id: "A", anomalies: ["G02_A", "G07_A"] }, { id: "B", anomalies: ["G04_B", "G08_B"] }, { id: "C", anomalies: ["G03_C", "G06_C"] } ] } }, 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"] } }), actions: { // 获取时间轴数据-中间时间轴 async initializeAbnormalGroupTimeLine() { const res = await getAbnormalGroupTimeLine() if (res.code === 200) { this.timeList = res.data } }, // 异常用户组展示-左上 async initializeAbnormalGroupList() { const res = await getAbnormalGroupList() if (res.code === 200) { this.groupList = res.data } }, // 全局异常互动时刻表-左下 async initializeAbnormalGroupInteractionChart() { const res = await getAbnormalGroupInteractionChart() const xAxisData = res.data.xaxisData.map((item) => utcStringToHHMMSS(item)) const yAxisRange = res.data.yaxisRange const themeColors = { 社团组一: "#00d6da", 社团组二: "#fddc33", 社团组三: "#32b6fb" } const seriesList = res.data.seriesList.map((item) => ({ data: item.data.map((item) => item.toFixed(2)), name: item.name, themeColor: themeColors[item.name] })) this.chartData = { xAxisData, yAxisRange, seriesList } }, // 异常行为分析-中下 async initializeAbnormalGroupPosts(time = "2024-06-19T07:57:46Z") { const res = await getAbnormalGroupBehaviorPosts(time) if (res.code === 200) { this.posts = res.data.map((item) => ({ id: item.id, abnormalGroup: item.abnormalGroup, explanation: item.explanation, firstDiscoverTime: TansTimestamp(item.firstDiscoverTime, "YYYY-MM-DD"), duration: item.duration, JS: parseFloat(item.js), CUSUM: parseFloat(item.cusum), KS: parseFloat(item.ks) })) } }, // 异常互动详情-右上 async initializeAbnormalGroupInteractionDetail(time = "2024-06-19T07:57:46Z") { const res = await getAbnormalGroupBehaviorDetail(time) if (res.code === 200) { this.abnormalContentList = res.data } }, // 用于画中间组件的圆 async initialGraphByUtcTime(utcIso) { this.currentUtc = utcIso // 1) 复制 nodes 并上色 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 const setColor = (type) => { const colorMap = { 0: "50,141,120", 1: "133,129,48", 6: "12,112,144" } return colorMap[type] } const links = this.graphData.links.map((l) => ({ source: l.source, target: l.target, color: setColor(l.type) })) this.graph["links"] = links } }, persist: true // 开启持久化 })