This commit is contained in:
duanhao 2025-07-31 17:06:57 +08:00
commit 761373ed93
8 changed files with 223 additions and 190 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 B

View File

@ -86,9 +86,27 @@ export function getSocialCommunityDetailNodes(ids, relationId, time = "2024-05-1
} }
} }
//人物社交隐关系预测用户组列表 //获取人物社交隐关系预测社团节点
export function getInteractionHiddenPostList(outoIncrement) { export function getCharacterSocialCommunityNodes() {
return http.get(`/linkPrediction/triangle/post_list?page=${outoIncrement}`) return http.get("/linkPrediction/social/community")
} }
// //获取人物社交隐关系预测社团统计
export function getCharacterSocialCommunityStatistics() {
return http.get(`/linkPrediction/social/community_statistics`)
}
//获取人物社交隐关系预测社团内部节点
export function getCharacterSocialCommunityDetailNodes(
ids,
relationId,
time = "2024-05-16 16:56:04"
) {
if (relationId != -1) {
return http.get(
`/linkPrediction/social/community_detail?groupIds=${ids}&dateTime=${time}&relationId=${relationId}`
)
} else {
return http.get(`/linkPrediction/social/community_detail?groupIds=${ids}&dateTime=${time}`)
}
}

View File

@ -4,14 +4,16 @@ import {
getGroupUserListFromTriangle, getGroupUserListFromTriangle,
getGroupUserListFromSocial, getGroupUserListFromSocial,
getInteractionPostList, getInteractionPostList,
getInteractionHiddenPostList,
getInteractionCommunityNodes, getInteractionCommunityNodes,
getInteractionCommunityDetailNodes, getInteractionCommunityDetailNodes,
getInteractionCommunityStatistics, getInteractionCommunityStatistics,
getSocialCommunityList, getSocialCommunityList,
getSocialCommunityStatistics, getSocialCommunityStatistics,
getSocialCommunityDetailNodes, getSocialCommunityDetailNodes,
getSocialPostListByRelationId getSocialPostListByRelationId,
getCharacterSocialCommunityNodes,
getCharacterSocialCommunityStatistics,
getCharacterSocialCommunityDetailNodes
} from "@/service/api/linkPrediction" } from "@/service/api/linkPrediction"
import defaultAvatar from "@/assets/images/avatar/default.png" import defaultAvatar from "@/assets/images/avatar/default.png"
@ -28,11 +30,14 @@ export const useCharacterInteractionStore = defineStore("characterInteraction",
communityNodeList: [], //所有社团数据 communityNodeList: [], //所有社团数据
curComponent: "CommunityNode", curComponent: "CommunityNode",
curSelecedGroupIds: [], curSelecedGroupIds: [],
predictionLegendContent: "互动隐关系",
communityDetailNodeRelation: [], //点击一级界面后,查询到的节点间关系 communityDetailNodeRelation: [], //点击一级界面后,查询到的节点间关系
communityDetailNodeList: [], //节点用户列表 communityDetailNodeList: [], //节点用户列表
timeList: [], timeList: [],
predictionUserIds: [], //包含从用户组选择的用户id或者是点击某个社团或者连边后所需要高亮的所有用户的id predictionUserIds: [], //包含从用户组选择的用户id或者是点击某个社团或者连边后所需要高亮的所有用户的id
curRelationId: "", curRelationId: "",
predictionLineColor: "#f8bf38",
predictionLegendIcon: `image://${new URL("@/assets/images/linkPrediction/icon/hidden-icon.png", import.meta.url)}`,
anlysisList: [ anlysisList: [
{ {
id: 1, id: 1,
@ -159,7 +164,7 @@ export const useCharacterInteractionStore = defineStore("characterInteraction",
if (res.code != 200) { if (res.code != 200) {
return return
} }
this.userList = res.data.userList this.userList = res.data.userList.sort((a, b) => a.rank - b.rank)
}, },
initGroupCorrelationForChart() { initGroupCorrelationForChart() {
@ -181,7 +186,6 @@ export const useCharacterInteractionStore = defineStore("characterInteraction",
if (res.code != 200) return if (res.code != 200) return
const customStatisticsObj = Object.assign({}, res.data.communityStatistics) const customStatisticsObj = Object.assign({}, res.data.communityStatistics)
//计算两个用户是否同属与同一个社团 //计算两个用户是否同属与同一个社团
if ( if (
customStatisticsObj.groupCount == null && customStatisticsObj.groupCount == null &&
customStatisticsObj.hiddenInteractionCount == null customStatisticsObj.hiddenInteractionCount == null
@ -497,58 +501,23 @@ export const useSocialGroupsStore = defineStore("socialGroups", {
export const useCharacterHiddenStore = defineStore("characterHidden", { export const useCharacterHiddenStore = defineStore("characterHidden", {
state: () => ({ state: () => ({
userList: [], userList: [],
userChartList: [
{
id: 1,
group: [
{ id: 1, name: "Polo Hun", avatar: defaultAvatar, fancy: 634, post: 32 },
{ id: 2, name: "楊政子", avatar: defaultAvatar, fancy: 5556, post: 23 }
],
number: "0.36"
},
{
id: 2,
group: [
{
id: 7,
name: "一人一讚 馬總統感恩有您 永遠支...",
avatar: defaultAvatar,
fancy: 0,
post: 0
},
{
id: 8,
name: "一人一讚 馬總統感恩有您 永遠支...",
avatar: defaultAvatar,
fancy: 564,
post: 13
}
],
number: 0.28
},
{
id: 3,
group: [
{
id: 9,
name: "一人一讚 馬總統感恩有您 永遠支...",
avatar: defaultAvatar,
fancy: 0,
post: 0
},
{
id: 10,
name: "一人一讚 馬總統感恩有您 永遠支...",
avatar: defaultAvatar,
fancy: 564,
post: 13
}
],
number: 0.24
}
],
posts: [], posts: [],
communityNodeList: [],
curComponent: "CommunityNode",
timeList: [],
predictionUserIds: [], //包含从用户组选择的用户id或者是点击某个社团或者连边后所需要高亮的所有用户的id
curRelationId: "",
curSelecedGroupIds: [],
communityDetailNodeRelation: [], //点击一级界面后,查询到的节点间关系
communityDetailNodeList: [], //节点用户列表
predictionLineColor: "#FF3F8F",
predictionLegendContent: "社交隐关系",
predictionLegendIcon: `image://${new URL("@/assets/images/linkPrediction/icon/socialCharacter-legend-icon.png", import.meta.url)}`,
statisticsList: [
{ id: 1, icon: nodePrefix, name: "节点数", key: "nodesCount" },
{ id: 2, icon: communityPrefix, name: "社团数", key: "groupCount" },
{ id: 3, icon: hiddenPrefix, name: "隐关系数", key: "hiddenInteractionCount" }
],
anlysisList: [ anlysisList: [
{ {
id: 1, id: 1,
@ -656,19 +625,60 @@ export const useCharacterHiddenStore = defineStore("characterHidden", {
{ text: "领土", top: 57.5, left: 72.5, width: 49, height: 19, fontSize: 12, opacity: 0.6 }, { 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: 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: 195.5, left: 287.5, width: 49, height: 19, fontSize: 12, opacity: 0.8 }
],
statisticsDetailList: [
{ id: 1, icon: nodePrefix, name: "节点数", key: "nodesCount" },
{ id: 2, icon: communityPrefix, name: "社团数", key: "groupCount" },
{ id: 3, icon: hiddenPrefix, name: "隐关系数", key: "hiddenInteractionCount" }
] ]
}), }),
actions: { actions: {
async initGroupList() { async initGroupList() {
const res = await getGroupUserListFromSocial() const res = await getGroupUserListFromSocial()
if (res.code != 200) return if (res.code != 200) return
this.userList = res.data.userList this.userList = res.data.userList.sort((a, b) => a.rank - b.rank)
}, },
async initPostList(autoIncrement) {
const res = await getInteractionHiddenPostList(autoIncrement) async initCharacterSocialHiddenPostList(relationId) {
const res = await getInteractionPostList(relationId)
if (res.code != 200) return if (res.code != 200) return
if (this.posts.length != 0) this.posts.push(...res.data) this.posts = res.data
else this.posts = res.data },
async initGraphCommunityNode() {
const res = await getCharacterSocialCommunityNodes()
if (res.code !== 200) return
this.communityNodeList = res.data
},
async initGraphStatistics() {
const res = await getCharacterSocialCommunityStatistics()
this.statisticsList = this.statisticsList.map((item) => ({
...item,
count: res.data[item.key]
}))
},
async initGraphCommunityDetailNode(ids, time = "2024-05-16 16:56:04", relationId = -1) {
this.curSelecedGroupIds = ids
const res = await getCharacterSocialCommunityDetailNodes(ids, relationId, time)
if (res.code != 200) return
const customStatisticsObj = Object.assign({}, res.data.communityStatistics)
//计算两个用户是否同属与同一个社团
if (
customStatisticsObj.groupCount == null &&
customStatisticsObj.hiddenInteractionCount == null
) {
customStatisticsObj.hiddenInteractionCount = 1
customStatisticsObj.groupCount = ids[0] === ids[1] ? 1 : 2
}
this.statisticsDetailList = this.statisticsDetailList.map((item) => ({
...item,
count: customStatisticsObj[item.key]
}))
this.communityDetailNodeRelation = res.data.userRelation
this.communityDetailNodeList = res.data.userList
this.timeList = res.data.timeList
this.predictionUserIds = res.data.predictNodes
} }
}, },
persist: true // 开启持久化 persist: true // 开启持久化

View File

@ -14,7 +14,7 @@
</div> </div>
<div class="middle-container"> <div class="middle-container">
<div class="graph"> <div class="graph">
<Graph :title="graphTitleImg"></Graph> <Graph :title="graphTitleImg" :interactionStore="interactionStore"></Graph>
</div> </div>
<div class="postList"> <div class="postList">
<PostList :posts="interactionStore.posts"></PostList> <PostList :posts="interactionStore.posts"></PostList>
@ -53,7 +53,6 @@ const interactionStore = useCharacterInteractionStore()
const handleSelectedUserGroup = (group) => { const handleSelectedUserGroup = (group) => {
interactionStore.curComponent = "detailNode" interactionStore.curComponent = "detailNode"
interactionStore.timeList = group.timeList // interactionStore.timeList = group.timeList //
interactionStore.userIds = group.list.map((user) => user.userId) //id
interactionStore.curRelationId = group.relationId //relationid interactionStore.curRelationId = group.relationId //relationid
interactionStore.initInteractionPostList(group.relationId) interactionStore.initInteractionPostList(group.relationId)
interactionStore.initGraphCommunityDetailNode( interactionStore.initGraphCommunityDetailNode(

View File

@ -14,14 +14,10 @@
</div> </div>
<div class="middle-container"> <div class="middle-container">
<div class="graph"> <div class="graph">
<Graph :title="graphTitleImg"></Graph> <Graph :title="graphTitleImg" :interactionStore="characterHiddenStore"></Graph>
</div> </div>
<div class="postList"> <div class="postList">
<PostList <PostList :posts="characterHiddenStore.posts"></PostList>
:posts="characterHiddenStore.posts"
@click:openDialog="handleOpenPostDialog"
@scroll:touchButtom="handleTouchButtom"
></PostList>
</div> </div>
</div> </div>
<div class="right-container"> <div class="right-container">
@ -36,70 +32,43 @@
</div> </div>
</div> </div>
</div> </div>
<el-dialog v-model="postDialog" width="640" align-center class="custom-dialog">
<img src="@/assets/images/head/post-dialog-title.png" alt="" class="postTitleImage" />
<div class="dialog-content">
<div class="post-content">{{ currentPostPost.content }}</div>
<div class="heat">
<div class="item-heat-detail">
<div class="item-heat-like">
<Icon icon="ei:like" width="25" height="25" /> {{ currentPostPost.like }}
</div>
<div class="item-heat-comment">
<Icon icon="la:comment-dots" width="25" height="25" /> {{ currentPostPost.comment }}
</div>
<div class="item-heat-transmit">
<Icon icon="mdi:share-outline" width="25" height="25" /> {{
currentPostPost.transmit
}}
</div>
</div>
</div>
</div>
</el-dialog>
</div> </div>
</template> </template>
<script setup> <script setup>
import { onMounted, ref } from "vue"; import { onMounted, provide } from "vue"
import UserPanel from "../components/userPanel.vue"; import UserPanel from "../components/userPanel.vue"
import UserChart from "../components/userChart.vue"; import PostList from "../components/postList.vue"
import PostList from "../components/postList.vue"; import AnlysisPanle from "../components/anlysisPanle.vue"
import AnlysisPanle from "../components/anlysisPanle.vue"; import Graph from "../components/graph.vue"
import Graph from "../components/graph.vue"; import WordsCloud from "../components/cloudWords.vue"
import WordsCloud from "../components/cloudWords.vue"; import { useCharacterHiddenStore } from "@/store/llinkPrediction/index"
import { Icon } from "@iconify/vue"; import userPanelTitleImg from "@/assets/images/linkPrediction/title/user-title.png"
import { useCharacterHiddenStore } from "@/store/llinkPrediction/index"; import graphTitleImg from "@/assets/images/linkPrediction/title/graph1-title.png"
import userPanelTitleImg from "@/assets/images/linkPrediction/title/user-title.png"; import analysisTitleImg from "@/assets/images/linkPrediction/title/analysis-title.png"
import userChartTitleImg from "@/assets/images/linkPrediction/title/interaction-strenth-title.png";
import graphTitleImg from "@/assets/images/linkPrediction/title/graph1-title.png";
import analysisTitleImg from "@/assets/images/linkPrediction/title/analysis-title.png";
const characterHiddenStore = useCharacterHiddenStore();
// const characterHiddenStore = useCharacterHiddenStore()
const postDialog = ref(false);
//
const currentPostPost = ref(null);
const handleSelectedUserGroup = (group) => { const handleSelectedUserGroup = (group) => {
console.log(group); characterHiddenStore.curComponent = "detailNode"
}; characterHiddenStore.timeList = group.timeList //
characterHiddenStore.curRelationId = group.relationId //relationid
const handleOpenPostDialog = (post) => { characterHiddenStore.initCharacterSocialHiddenPostList(group.relationId)
postDialog.value = true; characterHiddenStore.initGraphCommunityDetailNode(
currentPostPost.value = post; group.list.map((item) => item.groupId),
}; "2024-05-16 16:56:04",
group.relationId
const handleTouchButtom = (autoIncrement) => { )
characterHiddenStore.initPostList(autoIncrement); }
};
onMounted(() => { onMounted(() => {
characterHiddenStore.initGroupList(); characterHiddenStore.initGroupList()
characterHiddenStore.initPostList(0); characterHiddenStore.initCharacterSocialHiddenPostList("79") //
}); characterHiddenStore.initGraphCommunityNode() //
characterHiddenStore.initGraphStatistics() //
})
provide("communityNodeList", characterHiddenStore.communityNodeList) //
provide("statisticsList", characterHiddenStore.statisticsList)
</script> </script>
<style scoped lang="less"> <style scoped lang="less">

View File

@ -12,23 +12,28 @@
</template> </template>
<script setup> <script setup>
import { onMounted, defineEmits, inject } from "vue" import { onMounted, defineEmits, inject, defineProps } from "vue"
import * as echarts from "echarts" import * as echarts from "echarts"
import nodeHoverImg from "@/assets/images/nodeHover.png" import nodeHoverImg from "@/assets/images/nodeHover.png"
let chart = null let chart = null
const emit = defineEmits(["click:node", "click:edge"]) const emit = defineEmits(["click:node", "click:edge"])
const statisticsList = inject("statisticsList") const statisticsList = inject("statisticsList")
const props = defineProps({
const initChart = async () => { interactionStore: {
type: Object,
required: true
}
})
const initChart = () => {
chart = echarts.init(document.getElementById("container")) chart = echarts.init(document.getElementById("container"))
// //
const nodes = Object.values(inject("communityNodeList") ?? []).map((item) => ({ const nodes = Object.values(inject("communityNodeList") ?? []).map((item) => ({
id: parseInt(item.id), id: item.id,
name: parseInt(item.id), name: item.id,
isIncludePredictNodes: item.isIncludePredictNodes, isIncludePredictNodes: item.isIncludePredictNodes,
nodesNum: item.nodesNum, nodesNum: item.nodesNum,
neighbors: item.neighbors.map((item) => ({ ...item, name: parseInt(item.id) })), neighbors: item.neighbors,
category: item.isIncludePredictNodes ? 1 : 0, category: item.isIncludePredictNodes ? 1 : 0,
selfIncludeImplicitRelationship: selfIncludeImplicitRelationship:
item.neighbors.map((nei) => nei.id).includes(item.id) && //id item.neighbors.map((nei) => nei.id).includes(item.id) && //id
@ -37,24 +42,23 @@ const initChart = async () => {
// //
const links = [] const links = []
const edgeSet = new Set() // const newSet = new Set()
nodes.forEach((communityNode) => { nodes.forEach((communityNode) => {
communityNode.neighbors.forEach((communityNei) => { communityNode.neighbors.forEach((communityNei) => {
const key = [communityNode.name, communityNei.name].sort().join("-") if (newSet.has(communityNei.id)) return
if (edgeSet.has(key)) return
links.push({ links.push({
source: communityNode.name, source: communityNode.id,
target: communityNei.name, target: communityNei.id,
edge: communityNei.isHidden ? 1 : 0, //10 edge: communityNei.isHidden ? 1 : 0, //10
lineStyle: { lineStyle: {
width: communityNei.isHidden ? 4 : 1, // =线= width: communityNei.isHidden ? 4 : 1, // =线=
color: communityNei.isHidden ? "#f8bf38" : "#37ACD7", // == color: communityNei.isHidden ? props.interactionStore.predictionLineColor : "#37ACD7", // ==
type: communityNei.isHidden ? "dashed" : "solid", // =线=线 opacity: communityNei.isHidden ? 1 : 0.8, //
dashArray: [2, 1] // 2线1 type: communityNei.isHidden ? "dashed" : "solid" // =线=线
} }
}) })
edgeSet.add(key)
}) })
newSet.add(communityNode.id) // id
}) })
const data = { nodes, links } const data = { nodes, links }
@ -63,9 +67,9 @@ const initChart = async () => {
{ name: "普通社团", category: 0, icon: "circle" }, { name: "普通社团", category: 0, icon: "circle" },
{ name: "含预测节点社团", category: 1, icon: "circle" }, { name: "含预测节点社团", category: 1, icon: "circle" },
{ {
name: "互动隐关系", name: props.interactionStore.predictionLegendContent,
category: 2, category: 2,
icon: `image://${new URL("@/assets/images/linkPrediction/icon/hidden-icon.png", import.meta.url)}` icon: props.interactionStore.predictionLegendIcon
} }
] ]
const option = { const option = {
@ -196,7 +200,9 @@ const initChart = async () => {
]), ]),
opacity: 1, opacity: 1,
borderColor: node.selfIncludeImplicitRelationship ? "#f8bf38" : "#46C6AD", borderColor: node.selfIncludeImplicitRelationship
? props.interactionStore.predictionLineColor
: "#46C6AD",
borderWidth: node.selfIncludeImplicitRelationship ? 3 : 1, borderWidth: node.selfIncludeImplicitRelationship ? 3 : 1,
shadowBlur: 4, shadowBlur: 4,
borderType: "dashed", borderType: "dashed",
@ -233,6 +239,8 @@ const initChart = async () => {
const handleClickNode = () => { const handleClickNode = () => {
chart.on("click", function (params) { chart.on("click", function (params) {
console.log(params)
if (params.dataType === "node") { if (params.dataType === "node") {
emit("click:node", params.data) emit("click:node", params.data)
} else if (params.dataType == "edge") { } else if (params.dataType == "edge") {
@ -245,7 +253,7 @@ const handleClickNode = () => {
} }
onMounted(async () => { onMounted(async () => {
await initChart() initChart()
handleClickNode() handleClickNode()
}) })
</script> </script>

View File

@ -55,15 +55,30 @@
</template> </template>
<script setup> <script setup>
import { defineEmits, onMounted, ref, onUnmounted, computed, watch, nextTick } from "vue" import {
defineEmits,
onMounted,
ref,
onUnmounted,
computed,
watch,
nextTick,
defineProps
} from "vue"
import { TansTimestamp } from "@/utils/transform" import { TansTimestamp } from "@/utils/transform"
import nodeHoverImg from "@/assets/images/nodeHover.png" import nodeHoverImg from "@/assets/images/nodeHover.png"
import * as echarts from "echarts" import * as echarts from "echarts"
import { storeToRefs } from "pinia" import { storeToRefs } from "pinia"
import { useCharacterInteractionStore } from "@/store/llinkPrediction/index"
const interactionStore = useCharacterInteractionStore() const props = defineProps({
const { communityDetailNodeRelation, timeList, predictionUserIds } = storeToRefs(interactionStore) interactionStore: {
type: Object,
required: true
}
})
const { communityDetailNodeRelation, timeList, predictionUserIds } = storeToRefs(
props.interactionStore
)
const emit = defineEmits(["click:goback"]) const emit = defineEmits(["click:goback"])
const chartsData = ref({}) const chartsData = ref({})
const handleGoback = () => { const handleGoback = () => {
@ -128,13 +143,16 @@ const pause = () => {
// //
const sendTimeChangeRequest = () => { const sendTimeChangeRequest = () => {
const currentTimes = TansTimestamp(currentTime.value, "YYYY-MM-DD HH:mm:ss") const currentTimes = TansTimestamp(currentTime.value, "YYYY-MM-DD HH:mm:ss")
if (interactionStore.curRelationId == "") { if (props.interactionStore.curRelationId == "") {
interactionStore.initGraphCommunityDetailNode(interactionStore.curSelecedGroupIds, currentTimes) props.interactionStore.initGraphCommunityDetailNode(
props.interactionStore.curSelecedGroupIds,
currentTimes
)
} else { } else {
interactionStore.initGraphCommunityDetailNode( props.interactionStore.initGraphCommunityDetailNode(
interactionStore.curSelecedGroupIds, props.interactionStore.curSelecedGroupIds,
currentTimes, currentTimes,
interactionStore.curRelationId props.interactionStore.curRelationId
) )
} }
} }
@ -206,16 +224,16 @@ const handlePointPointerDown = (e) => {
isDragging.value = false isDragging.value = false
// //
const currentTimes = TansTimestamp(currentTime.value, "YYYY-MM-DD HH:mm:ss") const currentTimes = TansTimestamp(currentTime.value, "YYYY-MM-DD HH:mm:ss")
if (interactionStore.curRelationId == "") { if (props.interactionStore.curRelationId == "") {
interactionStore.initGraphCommunityDetailNode( props.interactionStore.initGraphCommunityDetailNode(
interactionStore.curSelecedGroupIds, props.interactionStore.curSelecedGroupIds,
currentTimes currentTimes
) )
} else { } else {
interactionStore.initGraphCommunityDetailNode( props.interactionStore.initGraphCommunityDetailNode(
interactionStore.curSelecedGroupIds, props.interactionStore.curSelecedGroupIds,
currentTimes, currentTimes,
interactionStore.curRelationId props.interactionStore.curRelationId
) )
} }
@ -256,10 +274,10 @@ const initChart = async () => {
else if (interactionTime > 30) return 10 else if (interactionTime > 30) return 10
else return 1 else return 1
} }
if (!Object.keys(interactionStore.communityDetailNodeRelation).length) return if (!Object.keys(props.interactionStore.communityDetailNodeRelation).length) return
// //
nodes = interactionStore.communityDetailNodeList.map((item) => ({ nodes = props.interactionStore.communityDetailNodeList.map((item) => ({
id: item.userId, id: item.userId,
name: item.userName, name: item.userName,
symbolSize: 40, symbolSize: 40,
@ -267,7 +285,8 @@ const initChart = async () => {
fancy: item.fans fancy: item.fans
})) }))
Object.entries(interactionStore.communityDetailNodeRelation).forEach(([parentId, children]) => { Object.entries(props.interactionStore.communityDetailNodeRelation).forEach(
([parentId, children]) => {
children.forEach((child) => { children.forEach((child) => {
links.push({ links.push({
source: parentId, source: parentId,
@ -275,13 +294,15 @@ const initChart = async () => {
edge: child.isHidden ? 1 : 0, edge: child.isHidden ? 1 : 0,
interactionTimes: child.interactionTime, interactionTimes: child.interactionTime,
lineStyle: { lineStyle: {
width: child.isHidden ? 4 : edgeWidth(child.interactionTime), width: child.isHidden ? 7 : edgeWidth(child.interactionTime),
color: child.isHidden ? "#f8bf38" : "#37ACD7", // == color: child.isHidden ? props.interactionStore.predictionLineColor : "#37ACD7", // ==
opacity: child.isHidden ? 1 : 0.5, //
type: child.isHidden ? "dashed" : "solid" // =线=线 type: child.isHidden ? "dashed" : "solid" // =线=线
} }
}) })
}) })
}) }
)
chartsData.value = { links, nodes } chartsData.value = { links, nodes }
const categories = [ const categories = [
@ -292,9 +313,9 @@ const initChart = async () => {
icon: `image://${new URL("@/assets/images/linkPrediction/icon/interaction-icon2.png", import.meta.url)}` icon: `image://${new URL("@/assets/images/linkPrediction/icon/interaction-icon2.png", import.meta.url)}`
}, },
{ {
name: "互动隐关系", name: props.interactionStore.predictionLegendContent,
category: 2, category: 2,
icon: `image://${new URL("@/assets/images/linkPrediction/icon/hidden-icon.png", import.meta.url)}` icon: props.interactionStore.predictionLegendIcon
} }
] ]
const option = { const option = {
@ -404,7 +425,7 @@ const initChart = async () => {
zoom: 0.1, zoom: 0.1,
categories: categories, categories: categories,
force: { force: {
edgeLength: 2500, edgeLength: 4000,
repulsion: 4000, repulsion: 4000,
gravity: 0.1, gravity: 0.1,
friction: 0.02, friction: 0.02,

View File

@ -6,8 +6,13 @@
v-if="interactionStore.curComponent == 'CommunityNode'" v-if="interactionStore.curComponent == 'CommunityNode'"
@click:node="handleClickNode" @click:node="handleClickNode"
@click:edge="handleClickEdge" @click:edge="handleClickEdge"
:interaction-store="interactionStore"
></CommunityNode> ></CommunityNode>
<DetailNode v-else @click:goback="handleClickGoBack"></DetailNode> <DetailNode
v-else
@click:goback="handleClickGoBack"
:interaction-store="interactionStore"
></DetailNode>
</div> </div>
</template> </template>
@ -15,30 +20,33 @@
import { defineProps } from "vue" import { defineProps } from "vue"
import CommunityNode from "./communityNode.vue" import CommunityNode from "./communityNode.vue"
import DetailNode from "./detailNode.vue" import DetailNode from "./detailNode.vue"
import { useCharacterInteractionStore } from "@/store/llinkPrediction/index"
const interactionStore = useCharacterInteractionStore()
const props = defineProps({ const props = defineProps({
title: { title: {
type: String, type: String,
default: "" default: ""
},
interactionStore: {
type: Object,
required: true
} }
}) })
// //
const handleClickNode = async (nodeInfo) => { const handleClickNode = async (nodeInfo) => {
interactionStore.curComponent = "detailNode" props.interactionStore.curComponent = "detailNode"
interactionStore.curRelationId = "" props.interactionStore.curRelationId = ""
interactionStore.initGraphCommunityDetailNode([nodeInfo.id]) props.interactionStore.initGraphCommunityDetailNode([nodeInfo.id])
} }
// //
const handleClickEdge = (edgeInfo) => { const handleClickEdge = (edgeInfo) => {
interactionStore.curComponent = "detailNode" props.interactionStore.curComponent = "detailNode"
interactionStore.curRelationId = "" props.interactionStore.curRelationId = ""
interactionStore.initGraphCommunityDetailNode([edgeInfo.source, edgeInfo.target]) props.interactionStore.initGraphCommunityDetailNode([edgeInfo.source, edgeInfo.target])
} }
const handleClickGoBack = (currentComponentName) => { const handleClickGoBack = (currentComponentName) => {
interactionStore.curComponent = currentComponentName props.interactionStore.curComponent = currentComponentName
} }
</script> </script>