群体成员演化分析-左-中时间轴-中群体演化信息
This commit is contained in:
parent
022bb34123
commit
bb9aae9172
BIN
src/assets/images/groupMember/group-member-user-list-title.png
Normal file
BIN
src/assets/images/groupMember/group-member-user-list-title.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 392 B |
|
|
@ -122,6 +122,8 @@ watch(
|
|||
timeList.value = newVal
|
||||
},
|
||||
{ deep: true }
|
||||
|
||||
|
||||
)
|
||||
// 让 active-needle 标定在 timeList 最后一个时间点
|
||||
const showHidden = computed(() => {
|
||||
|
|
|
|||
|
|
@ -22,7 +22,22 @@ export function getPostByUtcTime(utcTime) {
|
|||
|
||||
|
||||
// 3.群体成员演化分析
|
||||
// 3.1 群体成员演化信息列表信息
|
||||
export function getGroupMemberInfoList() {
|
||||
return http.get(`/groupEvolution/groupMember/infoList`)
|
||||
// 3.1 获取时间线数据
|
||||
export function getGroupMemberTimeLine() {
|
||||
return http.get(`/groupEvolution/groupMember/timeline`)
|
||||
}
|
||||
|
||||
// 3.2 群体成员演化信息列表信息
|
||||
export function getGroupMemberInfoList(time) {
|
||||
return http.get(`/groupEvolution/groupMember/infoList?time=${time}`)
|
||||
}
|
||||
|
||||
// 3.3 全局群体成员演化图
|
||||
export function getGroupMemberChart() {
|
||||
return http.get(`/groupEvolution/groupMember/chart`)
|
||||
}
|
||||
|
||||
// 3.4 群体演化信息
|
||||
export function getGroupMemberEvolutionInfoByTime(date) {
|
||||
return http.get(`/groupEvolution/groupMember/changeList?date=${date}`)
|
||||
}
|
||||
|
|
@ -12,9 +12,12 @@ import {
|
|||
getGroupEvolutionGroupScaleChart,
|
||||
getGroupEvolutionTimeLine,
|
||||
getPostByUtcTime,
|
||||
getGroupMemberInfoList
|
||||
getGroupMemberInfoList,
|
||||
getGroupMemberTimeLine,
|
||||
getGroupMemberChart,
|
||||
getGroupMemberEvolutionInfoByTime
|
||||
} from "@/service/api/groupEvolution"
|
||||
import { TansTimestamp } from "@/utils/transform"
|
||||
import { TansTimestamp, utcStringToHHMMSS } from "@/utils/transform"
|
||||
|
||||
export const useGroupDiscoveryStore = defineStore("groupDiscovery", {
|
||||
state: () => ({
|
||||
|
|
@ -183,10 +186,9 @@ export const useGroupDiscoveryStore = defineStore("groupDiscovery", {
|
|||
|
||||
async initialGraphByUtcTime() {},
|
||||
|
||||
// 通过时间来获取帖文列表
|
||||
async initialPostByUtcTime(utcTime) {
|
||||
const res = await getPostByUtcTime(utcTime)
|
||||
if (res.code != 200) return
|
||||
this.posts = res.data
|
||||
|
||||
}
|
||||
},
|
||||
persist: true // 开启持久化
|
||||
|
|
@ -526,7 +528,7 @@ export const useGroupStructureStore = defineStore("groupStructure", {
|
|||
|
||||
export const useGroupMemberStore = defineStore("groupMember", {
|
||||
state: () => ({
|
||||
groupList: [
|
||||
/* groupList
|
||||
{
|
||||
id: 1,
|
||||
type: "群体一",
|
||||
|
|
@ -539,7 +541,9 @@ export const useGroupMemberStore = defineStore("groupMember", {
|
|||
focusedTopic: "#中国海警首次登检菲律宾#",
|
||||
value: [10, 20, 15, 5],
|
||||
}
|
||||
],
|
||||
*/
|
||||
groupList: [],
|
||||
timeList: [],
|
||||
groupMemberList: [
|
||||
{
|
||||
id: 1,
|
||||
|
|
@ -779,62 +783,62 @@ export const useGroupMemberStore = defineStore("groupMember", {
|
|||
posts: [
|
||||
{
|
||||
id: 1,
|
||||
timestamp: "2024-01-04 0:03:16",
|
||||
groupCategory: "群体一",
|
||||
time: "2024-01-04 0:03:16",
|
||||
type: "群体一",
|
||||
memberAddCount: 1
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
timestamp: "2024-02-03 12:58:53",
|
||||
groupCategory: "群体二",
|
||||
time: "2024-02-03 12:58:53",
|
||||
type: "群体二",
|
||||
memberAddCount: 2
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
timestamp: "2024-02-22 17:13:44",
|
||||
groupCategory: "群体三",
|
||||
time: "2024-02-22 17:13:44",
|
||||
type: "群体三",
|
||||
memberAddCount: 4
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
timestamp: "2024-02-23 17:54:46",
|
||||
groupCategory: "群体一",
|
||||
time: "2024-02-23 17:54:46",
|
||||
type: "群体一",
|
||||
memberAddCount: 4
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
timestamp: "2024-03-14 09:58:12",
|
||||
groupCategory: "群体三",
|
||||
time: "2024-03-14 09:58:12",
|
||||
type: "群体三",
|
||||
memberAddCount: 4
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
timestamp: "2024-03-23 21:20:40",
|
||||
groupCategory: "群体二",
|
||||
time: "2024-03-23 21:20:40",
|
||||
type: "群体二",
|
||||
memberAddCount: 4
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
timestamp: "2024-03-23 21:42:36",
|
||||
groupCategory: "群体一",
|
||||
time: "2024-03-23 21:42:36",
|
||||
type: "群体一",
|
||||
memberAddCount: 2
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
timestamp: "2024-04-06 18:17:30",
|
||||
groupCategory: "群体二",
|
||||
time: "2024-04-06 18:17:30",
|
||||
type: "群体二",
|
||||
memberAddCount: 4
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
timestamp: "2024-04-06 19:19:50",
|
||||
groupCategory: "群体一",
|
||||
time: "2024-04-06 19:19:50",
|
||||
type: "群体一",
|
||||
memberAddCount: 4
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
timestamp: "2024-05-16 00:22:18",
|
||||
groupCategory: "群体二",
|
||||
time: "2024-05-16 00:22:18",
|
||||
type: "群体二",
|
||||
memberAddCount: 5
|
||||
}
|
||||
],
|
||||
|
|
@ -913,19 +917,46 @@ export const useGroupMemberStore = defineStore("groupMember", {
|
|||
]
|
||||
}),
|
||||
actions: {
|
||||
async initializeGroupList() {
|
||||
const res = await getGroupMemberInfoList()
|
||||
async initializeGroupMemberTimeLine() {
|
||||
const res = await getGroupMemberTimeLine()
|
||||
this.timeList = res.data
|
||||
console.log("测试获取timeList:",this.timeList);
|
||||
},
|
||||
async initializeGroupList(time = "2024-06-19T07:57:46Z") {
|
||||
const res = await getGroupMemberInfoList(time)
|
||||
console.log("测试获取groupMemberInfoList:",res);
|
||||
const groupList = res.data.map(item => ({
|
||||
id: item.id,
|
||||
type: item.type,
|
||||
focusedTopic: item.focusedTopic,
|
||||
value: item.value
|
||||
value: item.value.map(item => item * 100)
|
||||
}))
|
||||
this.groupList = groupList
|
||||
console.log("测试获取groupList:",res);
|
||||
},
|
||||
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
|
||||
console.log("测试获取groupMemberEvolutionInfoByTime:",res.data);
|
||||
}
|
||||
|
||||
},
|
||||
persist: false // 开启持久化
|
||||
persist: true // 开启持久化
|
||||
})
|
||||
|
||||
export const useAnomalousGroup = defineStore("anomalousGroup", {
|
||||
|
|
|
|||
|
|
@ -91,3 +91,17 @@ export function getAvatarUrl(binaryStream) {
|
|||
return `data:image/jpeg;base64,${binaryStream}`
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将UTC格式时间字符串转换为时间戳并返回HH:mm:ss格式
|
||||
* @param {string} utcString - UTC格式时间字符串,如"2024-06-19T07:57:46Z"
|
||||
* @returns {string} 格式化后的时间字符串,格式为HH:mm:ss
|
||||
*/
|
||||
export function utcStringToHHMMSS(utcString) {
|
||||
if (!utcString) return ''
|
||||
// 解析UTC时间字符串为dayjs对象
|
||||
const date = dayjs.utc(utcString).add(8, 'hour')
|
||||
|
||||
// 格式化为HH:mm:ss
|
||||
return date.format('HH:mm:ss')
|
||||
}
|
||||
|
|
|
|||
|
|
@ -287,9 +287,6 @@ watch(
|
|||
)
|
||||
|
||||
onMounted(() => {
|
||||
console.log("111");
|
||||
|
||||
console.log(props.moduleName)
|
||||
// 获取容器宽度
|
||||
sliderContainerWidth.value = document.querySelector(".slider-container").offsetWidth
|
||||
})
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ const handlePointerDown = (time) => {
|
|||
const utcTime = convertToUtcIsoString(time)
|
||||
emit("click:pointerDownAndSlide", utcTime)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
|
|
|
|||
|
|
@ -40,8 +40,8 @@
|
|||
>条
|
||||
</span>
|
||||
<span class="author" v-else-if="props.moduleName == '群体成员演化分析'"
|
||||
>【{{ post.groupCategory }}】 的成员数目增加了<span style="color: #9df9fe">{{
|
||||
post.memberAddCount
|
||||
>【{{ post.type }}】 的成员数目{{ post.memberAddCount < 0 ? "减少" : "增加"}}了<span style="color: #9df9fe">{{
|
||||
Math.abs(post.memberAddCount)
|
||||
}}</span
|
||||
>位
|
||||
</span>
|
||||
|
|
|
|||
|
|
@ -30,9 +30,10 @@
|
|||
<script setup>
|
||||
import { defineProps, onMounted, ref } from "vue";
|
||||
import GroupChart from "../../component/groupChart.vue";
|
||||
const curSelectedTab = ref("头部自媒体");
|
||||
const curSelectedTab = ref("群体一");
|
||||
const curSelectedTabData = ref(null);
|
||||
const tabs = ["头部自媒体", "官方媒体", "普通自媒体"];
|
||||
const tabs = ["群体一", "群体二", "群体三"];
|
||||
|
||||
const moduleName = "群体成员演化分析"
|
||||
const props = defineProps({
|
||||
title: {
|
||||
|
|
@ -48,15 +49,15 @@ const props = defineProps({
|
|||
const handleSwitch = (item) => {
|
||||
curSelectedTab.value = item;
|
||||
const keyMapList = {
|
||||
头部自媒体: "topSelfMedia",
|
||||
官方媒体: "officalMedia",
|
||||
普通自媒体: "ordinaryMedia"
|
||||
群体一: "topSelfMedia",
|
||||
群体二: "officalMedia",
|
||||
群体三: "ordinaryMedia"
|
||||
};
|
||||
curSelectedTabData.value = props.chartsData[keyMapList[item]];
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
handleSwitch("头部自媒体");
|
||||
handleSwitch("群体一");
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<div class="group-item-title">
|
||||
<img
|
||||
class="group-item-title-icon"
|
||||
src="@/assets/images/linkPrediction/title/group-item-title.png"
|
||||
src="@/assets/images/groupMember/group-member-user-list-title.png"
|
||||
alt=""
|
||||
/>
|
||||
<div class="group-item-title-type">{{ group.type }}</div>
|
||||
|
|
@ -21,8 +21,9 @@
|
|||
</template>
|
||||
|
||||
<script setup>
|
||||
import { defineProps, ref, onMounted, onUnmounted } from "vue";
|
||||
import { defineProps, ref, onMounted, onUnmounted, watch, nextTick } from "vue";
|
||||
import * as echarts from "echarts";
|
||||
import nodeHoverImg from "@/assets/images/nodeHover.png"
|
||||
const props = defineProps({
|
||||
groupList: {
|
||||
type: Array,
|
||||
|
|
@ -34,6 +35,23 @@ const props = defineProps({
|
|||
}
|
||||
});
|
||||
|
||||
const groupList = ref(props.groupList)
|
||||
|
||||
|
||||
// 添加对groupList的监听
|
||||
watch(() => props.groupList, (newVal) => {
|
||||
groupList.value = newVal
|
||||
// 先销毁已存在的图表实例
|
||||
chartInstances.forEach(chart => {
|
||||
chart.dispose();
|
||||
});
|
||||
chartInstances.clear();
|
||||
// 使用nextTick确保DOM更新后再初始化图表
|
||||
nextTick(() => {
|
||||
initChart(groupList.value);
|
||||
});
|
||||
}, { deep: true });
|
||||
|
||||
// 存储图表实例,用于销毁
|
||||
const chartInstances = new Map();
|
||||
const indicator = [
|
||||
|
|
@ -49,14 +67,55 @@ const initChart = (groupList) => {
|
|||
if (chartDom && group.value) {
|
||||
const myChart = echarts.init(chartDom);
|
||||
chartInstances.set(group.id, myChart);
|
||||
// 动态设置雷达图的 indicator 最大值
|
||||
const maxValue = Math.ceil(Math.max(...group.value));
|
||||
|
||||
const option = {
|
||||
tooltip: {},
|
||||
tooltip: {
|
||||
trigger: "item",
|
||||
backgroundColor: "rgba(0,0,0,0)", // 透明背景
|
||||
borderColor: "rgba(0,0,0,0)", // 透明边框
|
||||
borderWidth: 0,
|
||||
extraCssText: "box-shadow:none;padding:0;",
|
||||
formatter: function (params) {
|
||||
return `<div
|
||||
style="
|
||||
padding:10px 15px;
|
||||
height: 100px;
|
||||
border-radius: 4px;
|
||||
background: url('${nodeHoverImg}');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
">
|
||||
<div style="color:#fff;letter-spacing: 0.14px;">
|
||||
<div >成长:${params.data.value[0]}</div>
|
||||
<div >收缩:${params.data.value[1]}</div>
|
||||
<div >合并:${params.data.value[2]}</div>
|
||||
<div >分裂:${params.data.value[3]}</div>
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
// 雷达图配置
|
||||
radar: {
|
||||
startAngle: 135, // 原点从 -45° 开始
|
||||
indicator: indicator, // 雷达图坐标轴
|
||||
indicator: [
|
||||
{ name: '成长期', max: Math.max(30, maxValue) },
|
||||
{ name: '收缩期', max: Math.max(30, maxValue) },
|
||||
{ name: '合并期', max: Math.max(30, maxValue) },
|
||||
{ name: '分裂期', max: Math.max(30, maxValue) },
|
||||
], // 雷达图坐标轴
|
||||
shape: 'circle', // 圆形分层
|
||||
splitNumber: 5, // 分层的数量
|
||||
min: 0,
|
||||
alignTicks: false,
|
||||
// 坐标字体
|
||||
axisName: {
|
||||
color: '#94C1EC',
|
||||
|
|
@ -88,7 +147,7 @@ const initChart = (groupList) => {
|
|||
type: 'radar',
|
||||
data: [
|
||||
{
|
||||
value: group.value,
|
||||
value: group.value || [0,0,0,0],
|
||||
symbol: "circle",
|
||||
symbolSize: 5,
|
||||
itemStyle: {
|
||||
|
|
@ -116,7 +175,12 @@ const initChart = (groupList) => {
|
|||
|
||||
onMounted(() => {
|
||||
// 调用初始化图表函数
|
||||
initChart(props.groupList);
|
||||
console.log("props.groupList:",props.groupList);
|
||||
|
||||
// 使用nextTick确保DOM更新后再初始化图表
|
||||
nextTick(() => {
|
||||
initChart(props.groupList);
|
||||
});
|
||||
|
||||
// 响应窗口大小变化
|
||||
window.addEventListener('resize', handleResize);
|
||||
|
|
@ -145,7 +209,7 @@ onUnmounted(() => {
|
|||
width: 100%;
|
||||
height: 100%;
|
||||
.title {
|
||||
margin-top: -7px;
|
||||
margin-top: -8px;
|
||||
margin-left: -2px;
|
||||
}
|
||||
.groupPanel-list {
|
||||
|
|
@ -166,17 +230,17 @@ onUnmounted(() => {
|
|||
}
|
||||
.group-item {
|
||||
width: 100%;
|
||||
height: 260px;
|
||||
padding-top: 16px;
|
||||
padding-bottom: 20px;
|
||||
height: 240px;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 0.5px solid rgba(0, 113, 188, 0.5);
|
||||
.group-item-title {
|
||||
position: relative;
|
||||
.group-item-title-type {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
top: 2px;
|
||||
color: #8efbff;
|
||||
left: 17px;
|
||||
left: 12px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
|
@ -191,8 +255,8 @@ onUnmounted(() => {
|
|||
font-size: 14px;
|
||||
.container {
|
||||
left: 40px;
|
||||
width: 218px;
|
||||
height: 170px;
|
||||
width: 210px;
|
||||
height: 160px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,12 @@
|
|||
</div>
|
||||
<!-- 中间大矩形 2 -->
|
||||
<div class="middle-container">
|
||||
<div class="graph"></div>
|
||||
<div class="graph">
|
||||
<GroupGraph
|
||||
:store="groupMemberStore"
|
||||
@click:pointerDownAndSlide="handleChangeXAxis"
|
||||
></GroupGraph>
|
||||
</div>
|
||||
<div class="postList">
|
||||
|
||||
<GroupPost
|
||||
|
|
@ -73,6 +78,7 @@
|
|||
|
||||
<script setup>
|
||||
import { onMounted, ref } from "vue";
|
||||
import GroupGraph from "../component/groupGraph.vue"
|
||||
import GroupPanel from "./components/groupPanel.vue";
|
||||
import GroupPost from "../component/groupPost.vue";
|
||||
import GroupAnalysis from "./components/groupAnalysis.vue";
|
||||
|
|
@ -96,8 +102,15 @@ const postDialog = ref(false);
|
|||
//当前选中的贴文数据
|
||||
const currentPostPost = ref(null);
|
||||
|
||||
// 图例颜色
|
||||
const handleChangeXAxis = (utcTime) => {
|
||||
const timeList = groupMemberStore.timeList
|
||||
// console.log("传入时间:",utcTime)
|
||||
|
||||
// if (!timeList.includes(utcTime)) return
|
||||
|
||||
groupMemberStore.initializeGroupList(utcTime) //随着时间轴变动,更新群体成员信息列表
|
||||
groupMemberStore.initialPostByUtcTime(utcTime) //随着时间轴变动,更新贴文列表
|
||||
}
|
||||
|
||||
const handleOpenPostDialog = (post) => {
|
||||
postDialog.value = true;
|
||||
|
|
@ -105,7 +118,14 @@ const handleOpenPostDialog = (post) => {
|
|||
};
|
||||
|
||||
onMounted(async () => {
|
||||
await groupMemberStore.initializeGroupMemberTimeLine()
|
||||
console.log("初始化成员演化信息表");
|
||||
await groupMemberStore.initializeGroupList()
|
||||
console.log("初始化后的群体成员信息表:",groupMemberStore.groupList);
|
||||
await groupMemberStore.initializeGroupMemberChart()
|
||||
console.log("初始化后的全局群体成员演化图:");
|
||||
|
||||
|
||||
})
|
||||
</script>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user