This commit is contained in:
duanhao 2025-07-31 10:10:45 +08:00
commit 0f57cffe44
7 changed files with 77 additions and 18 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 B

View File

@ -14,7 +14,7 @@ export function getInteractionCommunityNodes() {
export function getInteractionCommunityDetailNodes(ids, relationId, time = "2024-05-16 16:56:04") {
if (relationId != -1) {
return http.get(
`/linkPrediction/interaction/community_detail?groupIds=${ids}&relationId=${relationId}&dateTime=${time}`
`/linkPrediction/interaction/community_detail?groupIds=${ids}&dateTime=${time}&relationId=${relationId}`
)
} else {
return http.get(`/linkPrediction/interaction/community_detail?groupIds=${ids}&dateTime=${time}`)

View File

@ -11,8 +11,7 @@ import {
getSocialCommunityList,
getSocialCommunityStatistics,
getSocialCommunityDetailNodes,
getSocialPostListByRelationId,
getInteractionCommunityDetailFromUserGroup
getSocialPostListByRelationId
} from "@/service/api/linkPrediction"
import defaultAvatar from "@/assets/images/avatar/default.png"
@ -33,6 +32,7 @@ export const useCharacterInteractionStore = defineStore("characterInteraction",
communityDetailNodeList: [], //节点用户列表
timeList: [],
predictionUserIds: [], //包含从用户组选择的用户id或者是点击某个社团或者连边后所需要高亮的所有用户的id
curRelationId: "",
anlysisList: [
{
id: 1,
@ -175,13 +175,24 @@ export const useCharacterInteractionStore = defineStore("characterInteraction",
if (res.code != 200) return
this.communityNodeList = res.data
},
async initGraphCommunityDetailNode(ids, relationId = -1, time = "2024-05-16 16:56:04") {
async initGraphCommunityDetailNode(ids, time = "2024-05-16 16:56:04", relationId = -1) {
this.curSelecedGroupIds = ids
const res = await getInteractionCommunityDetailNodes(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: res.data.communityStatistics[item.key]
count: customStatisticsObj[item.key]
}))
this.communityDetailNodeRelation = res.data.userRelation
this.communityDetailNodeList = res.data.userList

View File

@ -54,11 +54,12 @@ const handleSelectedUserGroup = (group) => {
interactionStore.curComponent = "detailNode"
interactionStore.timeList = group.timeList //
interactionStore.userIds = group.list.map((user) => user.userId) //id
interactionStore.curRelationId = group.relationId //relationid
interactionStore.initInteractionPostList(group.relationId)
interactionStore.initGraphCommunityDetailNode(
group.list.map((item) => item.groupId),
group.relationId,
"2024-05-16 16:56:04"
"2024-05-16 16:56:04",
group.relationId
)
}

View File

@ -16,21 +16,36 @@
<div class="time-axis">
<div class="time">{{ TansTimestamp(startTime, "YYYY.MM.DD HH:mm:ss") }}</div>
<div class="axis" ref="axisRef" @pointerdown="handlePointerDown">
<div
class="time-section"
<el-tooltip
v-for="time in timeList"
:key="time"
:style="{ left: getTimeSectionLeft(time) + 5 + 'px' }"
></div>
:content="TansTimestamp(time, 'YYYY.MM.DD HH:mm:ss')"
placement="bottom"
effect="light"
>
<div class="time-section" :style="{ left: getTimeSectionLeft(time) + 5 + 'px' }"></div>
</el-tooltip>
<div class="progress-bar" :style="trackStyle"></div>
<div class="active-sign" :style="{ left: `${currentPosition}px` }">
<div class="active-needle"></div>
<div class="active-sign">
<el-tooltip
:content="TansTimestamp(timeList[timeList.length - 1], 'YYYY.MM.DD HH:mm:ss')"
placement="bottom"
effect="light"
>
<div class="active-needle" :style="showHidden"></div>
</el-tooltip>
<el-tooltip
:content="TansTimestamp(currentTime, 'YYYY.MM.DD HH:mm:ss')"
placement="bottom"
effect="light"
>
<div class="timeLine-point" @pointerdown.stop="handlePointPointerDown"></div>
<div
class="timeLine-point"
@pointerdown.stop="handlePointPointerDown"
:style="{ left: `${currentPosition}px` }"
></div>
</el-tooltip>
</div>
</div>
@ -100,6 +115,16 @@ const getTimeSectionLeft = computed(() => {
}
})
// active-needle timeList
const showHidden = computed(() => {
if (!timeList.value || timeList.value.length === 0) return {}
//
const lastTime = timeList.value[timeList.value.length - 1]
// left
const left = getTimeSectionLeft.value(lastTime) + 5 // +5px time-section
return { left: `${left}px` }
})
//
const getTimeFromPosition = (position) => {
const ratio = Math.max(0, Math.min(1, position / axisWidth))
@ -119,7 +144,15 @@ const handlePointerDown = (e) => {
//
const currentTimes = TansTimestamp(currentTime.value, "YYYY-MM-DD HH:mm:ss")
interactionStore.initGraphCommunityDetailNode(interactionStore.curSelecedGroupIds, currentTimes)
if (interactionStore.curRelationId == "") {
interactionStore.initGraphCommunityDetailNode(interactionStore.curSelecedGroupIds, currentTimes)
} else {
interactionStore.initGraphCommunityDetailNode(
interactionStore.curSelecedGroupIds,
currentTimes,
interactionStore.curRelationId
)
}
}
//
@ -144,7 +177,18 @@ const handlePointPointerDown = (e) => {
isDragging.value = false
//
const currentTimes = TansTimestamp(currentTime.value, "YYYY-MM-DD HH:mm:ss")
interactionStore.initGraphCommunityDetailNode(interactionStore.curSelecedGroupIds, currentTimes)
if (interactionStore.curRelationId == "") {
interactionStore.initGraphCommunityDetailNode(
interactionStore.curSelecedGroupIds,
currentTimes
)
} else {
interactionStore.initGraphCommunityDetailNode(
interactionStore.curSelecedGroupIds,
currentTimes,
interactionStore.curRelationId
)
}
document.removeEventListener("pointermove", handlePointerMove)
document.removeEventListener("pointerup", handlePointerUp)
@ -518,7 +562,7 @@ onMounted(() => {
height: 34px;
background-image: url("@/assets/images/point.png");
background-size: cover;
bottom: 1px;
bottom: -8px;
left: -11px;
position: absolute;
}

View File

@ -27,11 +27,13 @@ const props = defineProps({
//
const handleClickNode = async (nodeInfo) => {
interactionStore.curComponent = "detailNode"
interactionStore.curRelationId = ""
interactionStore.initGraphCommunityDetailNode([nodeInfo.id])
}
//
const handleClickEdge = (edgeInfo) => {
interactionStore.curComponent = "detailNode"
interactionStore.curRelationId = ""
interactionStore.initGraphCommunityDetailNode([edgeInfo.source, edgeInfo.target])
}

View File

@ -13,7 +13,7 @@
<div class="group-type-content">TOP{{ group.rank }}</div>
</div>
<div class="user-list-item" v-for="child in group.list" :key="child.id">
<img :src="getAvatarUrl(child.avatarData)" alt="" class="avatar" />
<img :src="getAvatarUrl(child.avatarData) ?? defaultAvatar" class="avatar" />
<div class="user-info">
<div class="username">{{ child.userName }}</div>
<div class="userState">
@ -36,6 +36,7 @@
<script setup>
import { defineProps, defineEmits, ref } from "vue"
import defaultAvatar from "@/assets/images/avatar/default.png"
import { getAvatarUrl } from "@/utils/transform"
const curUserGroupIndex = ref(0)
const emit = defineEmits(["click:selectedGroup"])