传播意见-节点点击内容补全-时间轴样式修改

This commit is contained in:
duanhao 2025-07-17 15:54:29 +08:00
parent 83f5ae04d5
commit 03622f44d6
5 changed files with 519 additions and 20 deletions

View File

@ -1919,3 +1919,387 @@ export const useKeyNodeRecognitionStore = defineStore("keyNodeRecognition", {
actions: {}, actions: {},
persist: false // 开启持久化 persist: false // 开启持久化
}); });
export const useOptionLeaderDiscoveryStore = defineStore("OptionLeaderDiscovery", {
state: () => ({
leaderNodeList: [
{
userid: "huxijin",
name: "Hu Xijin",
chineseName: "胡锡进",
followers: "53.8万",
posts: "54",
avatar: new URL("@/assets/images/huxijin.png", import.meta.url).toString(),
default_avatar: new URL(
"@/assets/images/avatar/1/blue_huxijin.png",
import.meta.url
).toString(),
active_avatar: new URL(
"@/assets/images/avatar/1/light_huxijin.png",
import.meta.url
).toString(),
category: "自媒体",
labelling: [
{
id: 1,
like: "3935",
comment: "1727",
transmit: "842",
time: "2022-8-1 23:11:01",
type: "原发",
content:
"1.Where is Pelosi now, does anybody know? Some said that she will be going to Taiwan by a submarine instead, and others said that she has sneaked into Taiwan disguised as someone else, is that the case?"
},
{
id: 2,
like: "2827",
comment: "1350",
transmit: "1115",
time: "2022-8-2 00:12:01",
type: "原发",
content:
"If Pelosi really visits Taiwan as planned, the Tsai Ing-wen authorities are accomplice. The mainland will definitely carry out severe punishment actions on Taiwan at the same time. The unbearable consequences will fall on Tsai authorities."
}
]
},
{
id: "levi_godman",
name: "Levi Godman",
chineseName: null,
followers: "4.6万",
posts: "12847",
avatar: new URL("@/assets/images/levi.png", import.meta.url).toString(),
default_avatar: new URL(
"@/assets/images/avatar/1/blue_levi_godman.png",
import.meta.url
).toString(),
active_avatar: new URL(
"@/assets/images/avatar/1/light_levi_godman.png",
import.meta.url
).toString(),
category: "自媒体",
labelling: [
{
id: 1,
like: "5354",
comment: "155",
transmit: "1410",
time: "2022-8-1 17:56:56",
type: "原发",
content: "BREAKING : Pelosi seen flying over Taiwan https://t.co/VQdm88KVeU"
},
{
id: 2,
like: "469",
comment: "41",
transmit: "163",
time: "2022-8-2 04:39:53",
type: "原发",
content:
"The Taiwanese press writes that tomorrow Pelosi will arrive in Taipei at around 17.30 Moscow time (22.30 local time), spend the night at the Grand Hyatt Hotel, and the next morning will visit the Taiwan Legislative Council, where she will meet with the leadership of the island"
}
]
},
{
id: "bidishalolo",
name: "bidishalolo",
chineseName: null,
followers: "2387",
posts: "8380",
avatar: new URL("@/assets/images/bidishalolo.png", import.meta.url).toString(),
default_avatar: new URL(
"@/assets/images/avatar/1/blue_bidishalolo.png",
import.meta.url
).toString(),
active_avatar: new URL(
"@/assets/images/avatar/1/light_bidishalolo.png",
import.meta.url
).toString(),
category: "自媒体",
labelling: [
{
id: 1,
like: "5013",
comment: "247",
transmit: "1376",
time: "2022-8-1 17:26:46",
type: "原发",
content:
"BREAKING: #Pelosi seen flying over #Taiwan. Stunning footage... https://t.co/8AOJ6yMPvl"
}
]
},
{
id: "indopacific",
name: "Indo-Pacific News",
chineseName: null,
followers: "11.5万",
posts: "11.3万",
avatar: new URL("@/assets/images/indo.png", import.meta.url).toString(),
default_avatar: new URL(
"@/assets/images/avatar/1/blue_indopacific.png",
import.meta.url
).toString(),
active_avatar: new URL(
"@/assets/images/avatar/1/light_indopacific.png",
import.meta.url
).toString(),
category: "新闻媒体",
labelling: [
{
id: 1,
like: "2466",
comment: "89",
transmit: "938",
time: "2022-08-02 04:02:24",
type: "原发",
content:
"The US is moving planes and aircraft carriers closer to #Taiwan due to the upcoming visit of House Speaker Nancy Pelosi to Taiwan - Nikkei Asia\n\nThe #USNavy has 2 aircraft carrier groups & 2 amphibious assault groups in the region, plus other assets based in #Japan, Hawaii & Guam https://t.co/L0eEr3px5N"
},
{
id: 2,
like: "2506",
comment: "128",
transmit: "658",
time: "2022-8-2 02:39:49",
type: "原发",
content:
"Nancy Pelosi's #Taiwan Itinerary Confirmed by Local Media\n\nPelosi will touch down in Taipei Tuesday night and is going to spend the evening at the Grand Hyatt Hotel, local media said.\n\nPelosi will then visit Taiwan's parliament Wednesday morning where she will meet Tsai Ing-Wen. https://t.co/Bu7VPkd9yK"
}
]
},
{
id: "spectator",
name: "The Spectator Index",
chineseName: null,
followers: "233.5万",
posts: "56",
avatar: new URL("@/assets/images/spectator.png", import.meta.url).toString(),
category: "新闻媒体",
default_avatar: new URL(
"@/assets/images/avatar/1/blue_spectator.png",
import.meta.url
).toString(),
active_avatar: new URL(
"@/assets/images/avatar/1/light_spectator.png",
import.meta.url
).toString(),
labelling: [
{
id: 1,
like: "12118",
comment: "623",
transmit: "3731",
time: "2022-8-2 03:21:04",
type: "原发",
content: "BREAKING: CNN reports US House Speaker Nancy Pelosi will visit Taiwan"
},
{
id: 2,
like: "6238",
comment: "409",
transmit: "1698",
time: "2022-8-1 22:56:59",
type: "原发",
content:
"BREAKING: Press release by US House Speaker Pelosi lists she will visit Singapore, Malaysia, South Korea and Japan on upcoming trip, without mention of Taiwan."
}
]
},
{
id: "reuters",
name: "Reuters",
chineseName: null,
followers: "2575.7万",
posts: "98",
avatar: new URL("@/assets/images/reuters.png", import.meta.url).toString(),
category: "新闻媒体",
default_avatar: new URL(
"@/assets/images/avatar/1/blue_reuters.png",
import.meta.url
).toString(),
active_avatar: new URL(
"@/assets/images/avatar/1/light_reuters.png",
import.meta.url
).toString(),
labelling: [
{
id: 1,
like: "1786",
comment: "362",
transmit: "741",
time: "2022-8-2 03:41:57",
type: "原发",
content:
"1.U.S. House Speaker Pelosi to visit Taiwan on Tuesday -Taiwan media https://t.co/UWXopyKO5I https://t.co/KIoLpCFfXf"
},
{
id: 2,
like: "277",
comment: "266",
transmit: "132",
time: "2022-8-2 14:04:22",
type: "原发",
content:
"U.S. looking to China not to escalate tensions in event of Pelosi visit to Taiwan -Blinken https://t.co/CPdyuIbA88 https://t.co/sKhaWTyS4p"
}
]
},
{
id: "mickwallace",
name: "Mick Wallace",
chineseName: null,
followers: "24.8万",
posts: "10259",
avatar: new URL("@/assets/images/mick.png", import.meta.url).toString(),
category: "自媒体",
default_avatar: new URL(
"@/assets/images/avatar/1/blue_mickwallace.png",
import.meta.url
).toString(),
active_avatar: new URL(
"@/assets/images/avatar/1/light_mickwallace.png",
import.meta.url
).toString(),
labelling: [
{
id: 1,
like: "5354",
comment: "155",
transmit: "1410",
time: "2022-8-1 17:56:56",
type: "引用",
content: "BREAKING : Pelosi seen flying over Taiwan https://t.co/VQdm88KVeU"
},
{
id: 2,
like: "2254",
comment: "168",
transmit: "428",
time: "2022-8-1 10:55:50",
type: "二级转发",
content:
"If #Pelosi visits Taiwan to selfishly promote herself while knowingly undermining Peace and Security in the Region,she will be remembered as a disappointing piece of work..."
}
]
},
{
id: "jiushiniya",
name: "Jiushiniya",
chineseName: null,
followers: "557",
posts: "16020",
avatar: new URL("@/assets/images/jiushiniya.png", import.meta.url).toString(),
category: "自媒体",
default_avatar: new URL(
"@/assets/images/avatar/1/blue_jiushiniya.png",
import.meta.url
).toString(),
active_avatar: new URL(
"@/assets/images/avatar/1/light_jiushiniya.png",
import.meta.url
).toString(),
labelling: [
{
id: 1,
like: "3336",
comment: "135",
transmit: "1197",
time: "2022-8-2 15:33:45",
type: "引用",
content:
"House Speaker Nancy Pelosi is going to Taiwan as a show of US support for Taiwan's independence. Trump holds a secret Chinese bank account & Ivanka owns patents on Chinese Coffins & Body Bags. Democrats are tough on China. Republicans invest in China. MAGA hats are made in China"
},
{
id: 2,
like: "2405",
comment: "140",
transmit: "669",
time: "2022-8-2 02:48:07",
type: "引用",
content:
"BREAKING:\n\nCNN confirms Speaker of the House, Nancy Pelosi, will travel to Taiwan.\n\nTaiwanese sources say she will arrive tomorrow.\n\nPelosi will be the highest-ranking American to visit Taiwan in 25 years.\n\nThe island is the nod in the First Island Chain that is closest to China. https://t.co/wTjBnm0zpv"
}
]
},
{
id: "liuxiaoming",
name: "Liu Xiaoming",
chineseName: "刘晓明",
followers: "33.8万",
posts: "8757",
avatar: new URL("@/assets/images/liuxiaoming.png", import.meta.url).toString(),
category: "自媒体",
default_avatar: new URL(
"@/assets/images/avatar/1/blue_liuxiaoming.png",
import.meta.url
).toString(),
active_avatar: new URL(
"@/assets/images/avatar/1/light_liuxiaoming.png",
import.meta.url
).toString(),
labelling: [
{
id: 1,
like: "6545",
comment: "1561",
transmit: "1062",
time: "2022-8-2 19:48:22",
type: "原发",
content:
"我们正告美方,中方正严阵以待,中国人民解放军绝不会坐视不管,必将采取坚决应对和有力反制措施,捍卫中国主权和领土完整。美方应该做的是恪守一个中国原则和中美三个联合公报规定,兑现拜登总统不支持'台独'的承诺,不安排佩洛西访问台湾。"
},
{
id: 2,
like: "5261",
comment: "1602",
transmit: "1741",
time: "2022-8-2 13:44:38",
type: "原发",
content:
"We are closely following the itinerary of #Pelosi. A visit to #Taiwan by her would constitute a gross interference in #China's internal affairs, seriously undermine China's sovereignty and territorial integrity, wantonly trample on the #one-China principle."
}
]
},
{
id: "indobosss",
name: "indobosss",
chineseName: null,
followers: "32",
posts: "1403",
avatar: new URL("@/assets/images/indobosss.png", import.meta.url).toString(),
category: "自媒体",
default_avatar: new URL(
"@/assets/images/avatar/1/blue_indobosss.png",
import.meta.url
).toString(),
active_avatar: new URL(
"@/assets/images/avatar/1/light_indobosss.png",
import.meta.url
).toString(),
labelling: [
{
id: 1,
like: "1310",
comment: "60",
transmit: "300",
time: "2022-8-1 21:55:31",
type: "引用",
content:
"Taiwan is China. \n\nThe UN says so. \n\nThe U.S. and China have said so in three different joint communiques.\n\nIt's called the One-China policy and Nancy Pelosi has gone full neocon to violate it."
},
{
id: 2,
like: "555",
comment: "123",
transmit: "204",
time: "2022-8-1 21:55:31",
type: "引用",
content:
"US House Speaker Nancy #Pelosi office officially announced her itinerary to Asia on Sunday. It said Pelosi will lead a Congressional delegation to the Indo-Pacific region, including visits to Singapore, Malaysia, South Korea and Japan, China's #Taiwan was not mentioned. https://t.co/AK6X0lm8OU"
}
]
}
]
})
})

View File

@ -4,7 +4,8 @@ import { ref, computed } from "vue";
export const useKeyNodeStore1 = defineStore("keyNode1", () => { export const useKeyNodeStore1 = defineStore("keyNode1", () => {
const allLeaderData = ref([ const allLeaderData = ref([
{ {
userid: "huxijin", // id: "huxijin",
id: "Hu Xijin 胡锡进",
name: "Hu Xijin", name: "Hu Xijin",
chineseName: "胡锡进", chineseName: "胡锡进",
followers: "53.8万", followers: "53.8万",
@ -43,7 +44,8 @@ export const useKeyNodeStore1 = defineStore("keyNode1", () => {
] ]
}, },
{ {
id: "levi_godman", // id: "levi_godman",
id: "Levi Godman",
name: "Levi Godman", name: "Levi Godman",
chineseName: null, chineseName: null,
followers: "4.6万", followers: "4.6万",
@ -81,6 +83,7 @@ export const useKeyNodeStore1 = defineStore("keyNode1", () => {
] ]
}, },
{ {
// id: "bidishalolo",
id: "bidishalolo", id: "bidishalolo",
name: "bidishalolo", name: "bidishalolo",
chineseName: null, chineseName: null,
@ -110,7 +113,8 @@ export const useKeyNodeStore1 = defineStore("keyNode1", () => {
] ]
}, },
{ {
id: "indopacific", // id: "indopacific",
id: "Indo-Pacific News",
name: "Indo-Pacific News", name: "Indo-Pacific News",
chineseName: null, chineseName: null,
followers: "11.5万", followers: "11.5万",
@ -149,7 +153,8 @@ export const useKeyNodeStore1 = defineStore("keyNode1", () => {
] ]
}, },
{ {
id: "spectator", // id: "spectator",
id: "The Spectator Index",
name: "The Spectator Index", name: "The Spectator Index",
chineseName: null, chineseName: null,
followers: "233.5万", followers: "233.5万",
@ -187,7 +192,8 @@ export const useKeyNodeStore1 = defineStore("keyNode1", () => {
] ]
}, },
{ {
id: "reuters", // id: "reuters",
id: "Reuters",
name: "Reuters", name: "Reuters",
chineseName: null, chineseName: null,
followers: "2575.7万", followers: "2575.7万",
@ -226,7 +232,8 @@ export const useKeyNodeStore1 = defineStore("keyNode1", () => {
] ]
}, },
{ {
id: "mickwallace", // id: "mickwallace",
id: "Mick Wallace",
name: "Mick Wallace", name: "Mick Wallace",
chineseName: null, chineseName: null,
followers: "24.8万", followers: "24.8万",
@ -264,7 +271,8 @@ export const useKeyNodeStore1 = defineStore("keyNode1", () => {
] ]
}, },
{ {
id: "jiushiniya", // id: "jiushiniya",
id: "Jiushiniya",
name: "Jiushiniya", name: "Jiushiniya",
chineseName: null, chineseName: null,
followers: "557", followers: "557",
@ -303,7 +311,8 @@ export const useKeyNodeStore1 = defineStore("keyNode1", () => {
] ]
}, },
{ {
id: "liuxiaoming", // id: "liuxiaoming",
id: "刘晓明",
name: "Liu Xiaoming", name: "Liu Xiaoming",
chineseName: "刘晓明", chineseName: "刘晓明",
followers: "33.8万", followers: "33.8万",
@ -342,7 +351,8 @@ export const useKeyNodeStore1 = defineStore("keyNode1", () => {
] ]
}, },
{ {
id: "indobosss", // id: "indobosss",
id: "Indobosss",
name: "indobosss", name: "indobosss",
chineseName: null, chineseName: null,
followers: "32", followers: "32",
@ -524,7 +534,8 @@ export const useKeyNodeStore1 = defineStore("keyNode1", () => {
leaderOriginInfo: { leaderOriginInfo: {
avatar: leader.avatar, avatar: leader.avatar,
followers: leader.followers, followers: leader.followers,
posts: posts.value posts: leader.posts,
labelling: posts.value
.filter((p) => p.author === leader.id) .filter((p) => p.author === leader.id)
.map((p) => ({ .map((p) => ({
id: p.id, id: p.id,

View File

@ -52,20 +52,24 @@
/> />
</div> </div>
<div class="timeline-container"> <div class="timeline-container">
<!-- 时间开始标签 -->
<span class="time-label">2023.10.07 00:00:00</span> <span class="time-label">2023.10.07 00:00:00</span>
<div class="timeline-track"> <div class="timeline-track">
<div <div
v-for="point in store.timePoints" v-for="point in store.timePoints"
:key="point.id" :key="point.id"
class="timeline-point-wrapper" class="timeline-point-wrapper"
:style="{ left: `${pointPositions[point.id]}%`}"
@click="store.setActiveTimePoint(point.id)" @click="store.setActiveTimePoint(point.id)"
> >
<!-- 时间点提示框 -->
<el-tooltip <el-tooltip
class="timePoint-box-item" class="timePoint-box-item"
effect="light" effect="light"
:content="point.timestamp" :content="point.timestamp"
placement="bottom" placement="bottom"
> >
<!-- 时间点节点 -->
<div class="timeline-point" :class="{ active: store.activeTimePoint === point.id }"> <div class="timeline-point" :class="{ active: store.activeTimePoint === point.id }">
<el-popover <el-popover
v-if="store.activeTimePoint === point.id" v-if="store.activeTimePoint === point.id"
@ -84,6 +88,7 @@
</el-tooltip> </el-tooltip>
</div> </div>
</div> </div>
<!-- 时间结束标签 -->
<span class="time-label">2023.10.15 00:00:00</span> <span class="time-label">2023.10.15 00:00:00</span>
</div> </div>
</div> </div>
@ -95,6 +100,7 @@
import { ref, defineExpose } from 'vue'; import { ref, defineExpose } from 'vue';
import { useKeyNodeStore1 } from '@/store/keyNodeStore1'; import { useKeyNodeStore1 } from '@/store/keyNodeStore1';
import DynamicGraph from "./graph/dynamicGraph.vue"; import DynamicGraph from "./graph/dynamicGraph.vue";
import { watch } from 'vue'
const store = useKeyNodeStore1(); const store = useKeyNodeStore1();
const leaderGraphRef = ref(null); const leaderGraphRef = ref(null);
@ -108,6 +114,63 @@ const highlightNode = (leaderId) => {
leaderGraphRef.value.highlightNode(leaderId); leaderGraphRef.value.highlightNode(leaderId);
} }
}; };
//
const calculatePositions = (timestamp) => {
// : 2022.07.31 00:00:00 2022.08.01 00:00:00
const startTime = new Date('2022-07-31T00:00:00').getTime()
const endTime = new Date('2022-08-01T00:00:00').getTime()
const timeRange = endTime - startTime;
//
const sortedPoints = [...store.timePoints].sort((a, b) => {
return new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime();
});
//
const pointPositions = {};
sortedPoints.forEach(point => {
const pointTime = new Date(point.timestamp).getTime();
const position = ((pointTime - startTime) / timeRange) * 100;
pointPositions[point.id] = Math.max(0, Math.min(100, position));
});
// (20px)
const pointWidthPercentage = 5; //
const minSpacing = pointWidthPercentage; //
//
for (let i = 1; i < sortedPoints.length; i++) {
const prevPoint = sortedPoints[i - 1];
const currPoint = sortedPoints[i];
const prevPosition = pointPositions[prevPoint.id];
const currPosition = pointPositions[currPoint.id];
//
if (currPosition - prevPosition < minSpacing) {
//
pointPositions[currPoint.id] = prevPosition + minSpacing;
//
if (pointPositions[currPoint.id] > 100) {
pointPositions[currPoint.id] = 100;
}
}
}
return pointPositions;
}
//
const pointPositions = ref({});
//
watch(
() => store.timePoints,
() => {
pointPositions.value = calculatePositions();
},
{ immediate: true, deep: true }
);
defineExpose({ highlightNode }); defineExpose({ highlightNode });
</script> </script>
@ -168,7 +231,7 @@ defineExpose({ highlightNode });
margin: 0 15px; margin: 0 15px;
position: relative; position: relative;
display: flex; display: flex;
justify-content: space-between; /* justify-content: space-between; */
align-items: center; align-items: center;
} }
.timeline-point-wrapper { .timeline-point-wrapper {
@ -177,31 +240,48 @@ defineExpose({ highlightNode });
justify-content: center; justify-content: center;
height: 20px; height: 20px;
cursor: pointer; cursor: pointer;
position: absolute;
transform: translateX(-50%);
} }
.timeline-point { .timeline-point {
width: 10px; width: 18px;
height: 10px; height: 18px;
background-color: #8dc5ff; background-color: transparent;
border-radius: 50%; border-radius: 50%;
border: 1px solid #cce7ff; border: 1.6px solid #FFE5A4;
transition: transform 0.3s ease; transition: transform 0.3s ease;
position: relative; position: relative;
display: flex;
align-items: center;
justify-content: center;
} }
.timeline-point::after {
content: '';
width: 10px;
height: 10px;
background-color: #F9BD25;
border-radius: 50%;
position: absolute;
}
.timeline-point-wrapper:hover .timeline-point { .timeline-point-wrapper:hover .timeline-point {
transform: scale(1.5); transform: scale(1.5);
} }
.timeline-point.active { .timeline-point.active {
background-color: #ffc94d; background-color: transparent;
border-color: #fff; border-color: #FFE5A4;
transform: scale(1.3); transform: scale(1.3);
} }
.timeline-point.active::after {
background-color: #ffc94d; /* 活跃状态下内部圆圈仍为黄色 */
}
.active-pin { .active-pin {
width: 30px; width: 30px;
height: 34px; height: 34px;
background-image: url("@/assets/images/point.png"); background-image: url("@/assets/images/point.png");
background-size: cover; background-size: cover;
bottom: 5px; bottom: 6px;
left: -11px;
position: absolute; position: absolute;
} }
</style> </style>

View File

@ -69,12 +69,21 @@
</template> </template>
<script setup> <script setup>
import { computed } from "vue"; import { computed, watch } from "vue";
import { useKeyNodeStore1 } from "@/store/keyNodeStore1"; import { useKeyNodeStore1 } from "@/store/keyNodeStore1";
import { Icon } from "@iconify/vue"; import { Icon } from "@iconify/vue";
const store = useKeyNodeStore1(); const store = useKeyNodeStore1();
console.log('store.activeLeader:', store.activeLeader);
watch(
() => store.activeLeader,
(newValue) => {
console.log('store.activeLeader 变化:', newValue);
},
{ immediate: true } //
);
const isVisible = computed({ const isVisible = computed({
get: () => store.isLeaderDetailDialogVisible, get: () => store.isLeaderDetailDialogVisible,
set: (value) => { set: (value) => {

View File

@ -307,6 +307,7 @@ const initAllGraphData = async () => {
leaderOriginInfo: leader, leaderOriginInfo: leader,
label: { show: false } label: { show: false }
}); });
// console.log("nodes:",nodes);
const userCount = Math.floor(Math.random() * 11) + 5; // 515 const userCount = Math.floor(Math.random() * 11) + 5; // 515
for (let i = 0; i < userCount; i++) { for (let i = 0; i < userCount; i++) {
@ -568,6 +569,7 @@ const getVisibleGraphData = () => {
const edges = []; const edges = [];
for (const node of allGraphData.value.nodes) { for (const node of allGraphData.value.nodes) {
let shouldShow = false; let shouldShow = false;
// console.log('Node ID :', typeof node.id, ':', node.id);
if (leaderIds.has(node.id) || node.id.startsWith("user_splattering_")) { if (leaderIds.has(node.id) || node.id.startsWith("user_splattering_")) {
shouldShow = true; shouldShow = true;
} else if (node.id.startsWith("user_")) { } else if (node.id.startsWith("user_")) {
@ -656,6 +658,19 @@ const renderChart = () => {
}); });
}; };
const handleClickNode = () => { const handleClickNode = () => {
// params.data ,
/*
* {
id: string, // ID (leader.id)
name: string, // (leader.name)
symbol: string, // ("image://base64...")
symbolSize: number, // (8025)
category: number, // (0leader1)
value: any, // (leader.followers)
leaderOriginInfo: object, // leader
label: { show: boolean } //
}
*/
chart.value.on("click", (params) => { chart.value.on("click", (params) => {
if (params.data && params.data.category === 0) { if (params.data && params.data.category === 0) {
selectedLeaderId.value = params.data.id; selectedLeaderId.value = params.data.id;