SocialNetworks_duan/src/views/LinkPrediction/characterInteraction/index.vue
qumeng039@126.com b6bbb15ad3 修改bug
2025-08-13 17:54:33 +08:00

370 lines
11 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="layout-container">
<div class="top-container"></div>
<div class="content">
<div class="left-container">
<div class="userPanel">
<UserPanel
:title="userPanelTitleImg"
:userList="interactionStore.userList"
:panelHeight="750"
@click:selectedGroup="handleSelectedUserGroup"
></UserPanel>
</div>
</div>
<div class="middle-container">
<div class="graph">
<Graph
:title="graphTitleImg"
:interactionStore="interactionStore"
:storeId="storeId"
@click:openUserInfoDialog="handleOpenUserInfoDialog"
></Graph>
</div>
<div class="postList">
<PostList :posts="interactionStore.posts"></PostList>
</div>
</div>
<div class="right-container">
<div class="anlysisPanel">
<AnlysisPanle
:anlysis-list="interactionStore.anlysisList"
:title="analysisTitleImg"
></AnlysisPanle>
</div>
<div class="cloudWords">
<WordsCloud :wordsCloudList="interactionStore.wordCloudData"></WordsCloud>
</div>
</div>
</div>
<el-dialog v-model="userInfoDialog" width="640" align-center class="custom-dialog">
<img
src="@/assets/images/linkPrediction/title/user-info-title.png"
alt=""
class="userInfoTitle"
/>
<div class="user-dialog-content">
<div class="user-basic-info">
<img
:src="
curSelectedUser.avatarData ? getAvatarUrl(curSelectedUser.avatarData) : defaultAvatar
"
alt=""
class="avatar"
/>
<div class="info-detail">
<div class="username">
{{ curSelectedUser.nodeName }}
</div>
<div class="info-fans-posts">
<div class="fans">
粉丝量:&nbsp;&nbsp;
<p>{{ curSelectedUser.fans }}</p>
</div>
</div>
</div>
</div>
<div class="info-group">
<div class="info-item">
<img src="@/assets/images/linkPrediction/icon/user-info-group-icon.png" alt="" />
<div class="info-item-content">
发帖总数:&nbsp;&nbsp;
<p>{{ curSelectedUser.postNum }}</p>
</div>
</div>
<div class="info-item">
<img src="@/assets/images/linkPrediction/icon/user-info-group-icon.png" alt="" />
<div class="info-item-content">
发帖频率:&nbsp;&nbsp;
<p>{{ curSelectedUser.postFreqPerDay }}</p>
</div>
</div>
<div class="info-item">
<img src="@/assets/images/linkPrediction/icon/user-info-group-icon.png" alt="" />
<div class="info-item-content">
参与互动次数:&nbsp;&nbsp;
<p>{{ curSelectedUser.interactionNum }}</p>
</div>
</div>
<div class="info-item">
<img src="@/assets/images/linkPrediction/icon/user-info-group-icon.png" alt="" />
<div class="info-item-content">
参与互动频率:&nbsp;&nbsp;
<p>{{ curSelectedUser.interactionFreqPerDay }}</p>
</div>
</div>
<div class="info-item">
<img src="@/assets/images/linkPrediction/icon/user-info-group-icon.png" alt="" />
<div class="info-item-content">
帖文被互动次数:&nbsp;&nbsp;
<p>{{ curSelectedUser.interactedNum }}</p>
</div>
</div>
<div class="info-item">
<img src="@/assets/images/linkPrediction/icon/user-info-group-icon.png" alt="" />
<div class="info-item-content">
最近活跃时间:&nbsp;&nbsp;
<p>{{ curSelectedUser.recentActiveTime }}</p>
</div>
</div>
</div>
</div>
</el-dialog>
</div>
</template>
<script setup>
import defaultAvatar from "@/assets/images/avatar/default.png"
import { onMounted, ref, provide } from "vue"
import { useCharacterInteractionStore } from "@/store/linkPrediction/index"
import UserPanel from "../components/userPanel.vue"
import PostList from "../components/postList.vue"
import AnlysisPanle from "../components/anlysisPanle.vue"
import Graph from "../components/graph.vue"
import WordsCloud from "../components/cloudWords.vue"
import userPanelTitleImg from "@/assets/images/linkPrediction/title/user-title.png"
import graphTitleImg from "@/assets/images/linkPrediction/title/graph1-title.png"
import analysisTitleImg from "@/assets/images/linkPrediction/title/analysis-title.png"
import { getAvatarUrl } from "@/utils/transform"
const interactionStore = useCharacterInteractionStore()
// 控制个人信息弹窗
const userInfoDialog = ref(false)
const curSelectedUser = ref(null)
const storeId = "characterInteraction"
//选择某个用户组,更新贴文列表 && 更新关系图二级界面
const handleSelectedUserGroup = (group) => {
interactionStore.curComponent = "detailNode"
interactionStore.timeList = group.timeList //保存从用户列表选择的用户组,为了显示这两个用户交互的时间切片
interactionStore.curRelationId = group.relationId //保存当前点击的relationid为了区分到底是从哪点进二级界面的
interactionStore.initInteractionPostList(group.relationId)
interactionStore.initGraphCommunityDetailNode(
group.list.map((item) => item.groupId),
"2024-05-16 16:56:04",
group.relationId
)
}
const handleOpenUserInfoDialog = (params) => {
userInfoDialog.value = params.userInfoDialog
curSelectedUser.value = params.curSelectedUser
}
onMounted(() => {
interactionStore.curComponent = "CommunityNode"
interactionStore.initGroupList() //初始化用户组列表
interactionStore.initGraphCommunityNode() //初始化所有社团节点
interactionStore.initGraphStatistics() //初始化所有社团状态统计
interactionStore.initInteractionPostList("106888") //初始贴文列表
})
provide("communityNodeList", interactionStore.communityNodeList) // 提供数据
provide("statisticsList", interactionStore.statisticsList)
</script>
<style scoped lang="less">
:deep(.custom-dialog) {
width: 640px;
border-width: 0px, 0px, 0px, 0px;
border-style: solid;
border-image-source: linear-gradient(180deg, #3aa1f8 0%, rgba(58, 161, 248, 0.2) 100%);
background-color: rgba(6, 45, 90, 1);
border: 1px solid #1a8bff;
border-radius: 2px;
padding: 0 0;
z-index: 1;
}
:deep(.post-dialog) {
height: 300px;
}
:deep(.custom-dialog) .postTitleImage {
margin-top: -24px;
margin-left: -2px;
}
:deep(.custom-dialog) .userInfoTitle {
margin-top: -24px;
margin-left: -2px;
}
:deep(.custom-dialog) .dialog-content {
width: 100%;
padding: 25px 20px;
}
:deep(.custom-dialog) .dialog-content .content {
color: rgba(255, 255, 255, 0.8);
font-family: "PingFang SC";
font-size: 16px;
font-style: normal;
font-weight: 400;
opacity: 0.7;
}
:deep(.custom-dialog) .user-dialog-content {
width: 100%;
padding: 30px;
.user-basic-info {
width: 428px;
display: flex;
justify-content: start;
align-items: center;
.avatar {
width: 70px;
height: 70px;
border-radius: 5px;
}
.info-detail {
height: 70px;
padding: 0 24px;
color: #fff;
display: flex;
flex-direction: column;
justify-content: space-around;
.info-fans-posts {
display: flex;
justify-content: start;
.fans {
margin-right: 63px;
display: flex;
justify-content: start;
}
.posts {
display: flex;
justify-content: start;
}
}
}
}
.info-group {
margin-top: 32px;
margin-left: -10px;
display: grid;
grid-template-columns: 1fr 1fr;
row-gap: 15px;
color: #fff;
font-size: 16px;
.info-item {
display: flex;
justify-content: start;
align-items: center;
.info-item-content {
display: flex;
justify-content: start;
}
}
}
}
.post-content {
color: #fff;
font-size: 16px;
opacity: 0.7;
}
.heat {
display: flex;
justify-content: flex-end;
margin-top: 20px;
.item-heat-detail {
display: flex;
justify-content: space-between;
div {
display: flex;
align-items: center;
justify-content: center;
width: 70px;
color: #fff;
opacity: 0.7;
}
}
}
.layout-container {
display: flex;
flex-direction: column;
gap: 20px;
.top-container {
width: 100%;
height: 88px;
background-image: url(@/assets/images/linkPrediction/title/page-title.png);
background-repeat: no-repeat;
background-size: cover;
fill: linear-gradient(270deg, rgba(6, 61, 113, 0.1) 0%, rgba(8, 30, 56, 0.38) 100%);
stroke-width: 1px;
stroke: #3aa1f8;
}
.content {
width: 100%;
height: 805px;
display: flex;
justify-content: space-between;
gap: 15px;
.left-container {
flex: 27%;
height: 100%;
display: flex;
flex-direction: column;
gap: 15px;
.userPanel {
width: 100%;
height: 100%;
border-radius: 2px;
flex-shrink: 0;
background-color: rgba(6, 45, 90, 0.3);
border: 1px solid rgba(0, 113, 188, 0.705);
}
}
.middle-container {
flex: 60%;
display: flex;
flex-direction: column;
gap: 15px;
.search {
width: 100%;
height: 60px;
}
.graph {
width: 100%;
height: 541px;
background-color: #070a22;
border-radius: 4px;
background-color: rgba(6, 45, 90, 0.3);
border: 1px solid rgba(0, 113, 188, 0.705);
}
.postList {
flex: 1;
border-radius: 4px;
background-color: rgba(6, 45, 90, 0.3);
border: 1px solid rgba(0, 113, 188, 0.705);
fill: linear-gradient(270deg, rgba(6, 61, 113, 0.1) 0%, rgba(8, 30, 56, 0.38) 100%);
stroke-width: 1px;
stroke: #3aa1f8;
overflow: auto;
padding: 10px 10px;
}
}
.right-container {
flex: 20%;
height: 100%;
display: flex;
flex-direction: column;
gap: 15px;
.anlysisPanel {
width: 100%;
height: 540px;
border-radius: 2px;
flex-shrink: 0;
background-color: rgba(6, 45, 90, 0.3);
border: 1px solid rgba(0, 113, 188, 0.705);
}
.cloudWords {
flex: 1;
border-radius: 2px;
flex-shrink: 0;
background-color: rgba(6, 45, 90, 0.3);
border: 1px solid rgba(0, 113, 188, 0.705);
}
}
}
}
</style>