diff --git a/.prettierrc b/.prettierrc
index 02fc07a..20047b2 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -1,9 +1,9 @@
{
"semi": true,
"singleQuote": false,
- "printWidth":100,
+ "printWidth": 100,
"trailingComma": "none",
"tabWidth": 2,
"endOfLine": "auto",
"arrowParens": "always"
-}
\ No newline at end of file
+}
diff --git a/Readme.md b/Readme.md
deleted file mode 100644
index 1511959..0000000
--- a/Readme.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# Vue 3 + Vite
-
-This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 `
+const props = defineProps({
+ wordsCloudList: {
+ type: Array,
+ default: () => []
+ }
+});
+
+const scanAngle = ref(0);
+const scanTimer = ref(null);
+const containerWidth = 370;
+const containerHeight = 276;
+
+const words = ref(props.wordsCloudList);
+
+const prepareWords = () => {
+ const centerX = containerWidth / 2;
+ const centerY = containerHeight / 2;
+ words.value = words.value.map((word) => {
+ const wordCenterX = word.left + word.width / 2;
+ const wordCenterY = word.top + word.height / 2;
+ const vecX = wordCenterX - centerX;
+ const vecY = wordCenterY - centerY;
+ let angleRad = Math.atan2(vecY, vecX);
+ let angleDeg = angleRad * (180 / Math.PI);
+ let scanAngle = angleDeg + 90;
+ if (scanAngle < 0) {
+ scanAngle += 360;
+ }
+ return {
+ ...word,
+ angle: scanAngle,
+ visible: false
+ };
+ });
+};
+
+const startScan = () => {
+ const duration = 20000;
+ let startTime = null;
+
+ const animate = (timestamp) => {
+ if (!startTime) {
+ startTime = timestamp;
+ }
+ const elapsedTime = timestamp - startTime;
+ const progress = (elapsedTime / duration) % 1;
+ const newScanAngle = progress * 360;
+
+ if (newScanAngle < scanAngle.value) {
+ words.value.forEach((w) => (w.visible = false));
+ startTime = timestamp;
+ }
+ scanAngle.value = newScanAngle;
+
+ words.value.forEach((word) => {
+ if (!word.visible && scanAngle.value >= word.angle) {
+ word.visible = true;
+ }
+ });
+
+ scanTimer.value = requestAnimationFrame(animate);
+ };
+ scanTimer.value = requestAnimationFrame(animate);
+};
+
+const getWordStyle = (word) => {
+ return {
+ top: `${word.top}px`,
+ left: `${word.left}px`,
+ width: `${word.width}px`,
+ height: `${word.height}px`,
+ borderRadius: `${word.height / 2}px`,
+ fontSize: `${word.fontSize}px`,
+ paddingLeft: `${word.fontSize * 0.8}px`,
+ paddingRight: "10px"
+ };
+};
+
+onMounted(() => {
+ prepareWords();
+ startScan();
+});
+
+onBeforeUnmount(() => {
+ if (scanTimer.value) cancelAnimationFrame(scanTimer.value);
+});
+
+
+
diff --git a/src/views/LinkPrediction/components/graph.vue b/src/views/LinkPrediction/components/graph.vue
index 74da15a..6eea0ee 100644
--- a/src/views/LinkPrediction/components/graph.vue
+++ b/src/views/LinkPrediction/components/graph.vue
@@ -1,7 +1,46 @@
-
+
+
![]()
+
+
+
+
-
+
-
+
diff --git a/src/views/LinkPrediction/components/postList.vue b/src/views/LinkPrediction/components/postList.vue
index 1809db8..f26d872 100644
--- a/src/views/LinkPrediction/components/postList.vue
+++ b/src/views/LinkPrediction/components/postList.vue
@@ -1,7 +1,268 @@
-
+
+

+
+
+
+
+
{{ post.timestamp }}
+
【{{ post.author }}】发布了帖文
+
+
互动: {{ post.influence }}
+
+
+
+
+
+
-
+
+
+
diff --git a/src/views/LinkPrediction/components/userChart.vue b/src/views/LinkPrediction/components/userChart.vue
index e0c1823..48ee0bf 100644
--- a/src/views/LinkPrediction/components/userChart.vue
+++ b/src/views/LinkPrediction/components/userChart.vue
@@ -1,7 +1,146 @@
-
+
+
![]()
+
+
+
+
+
+
![]()
+
+
+
+
+
+
-
+
-
+
diff --git a/src/views/LinkPrediction/components/userPanel.vue b/src/views/LinkPrediction/components/userPanel.vue
index 0880b9f..b9556c5 100644
--- a/src/views/LinkPrediction/components/userPanel.vue
+++ b/src/views/LinkPrediction/components/userPanel.vue
@@ -1,12 +1,40 @@
![]()
+
+
+
+
+
![]()
+
+
{{ child.name }}
+
+
+ 粉丝数:
+
{{ child.fancy }}
+
+
+ 发帖数:
+
{{ child.post }}
+
+
+
+
+
+
+