diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..d251d2e --- /dev/null +++ b/.prettierignore @@ -0,0 +1,9 @@ +/dist/* +.local +.output.js +/node_modules/** + +**/*.svg +**/*.sh + +/public/* \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..02fc07a --- /dev/null +++ b/.prettierrc @@ -0,0 +1,9 @@ +{ + "semi": true, + "singleQuote": false, + "printWidth":100, + "trailingComma": "none", + "tabWidth": 2, + "endOfLine": "auto", + "arrowParens": "always" +} \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json index a7cea0b..3228867 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,3 +1,4 @@ { - "recommendations": ["Vue.volar"] + "recommendations": ["Vue.volar"], + } diff --git a/package-lock.json b/package-lock.json index 4e8aec2..90acc97 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ }, "devDependencies": { "@vitejs/plugin-vue": "^5.2.3", + "prettier": "^3.6.0", "vite": "^6.3.5" } }, @@ -1323,6 +1324,22 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/prettier": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.0.tgz", + "integrity": "sha512-ujSB9uXHJKzM/2GBuE0hBOUgC77CN3Bnpqa+g80bkv3T3A93wL/xlzDATHhnhkzifz/UE2SNOvmbTz5hSkDlHw==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/rollup": { "version": "4.41.1", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.41.1.tgz", diff --git a/package.json b/package.json index ce20a3e..e246327 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ }, "devDependencies": { "@vitejs/plugin-vue": "^5.2.3", + "prettier": "^3.6.0", "vite": "^6.3.5" } } diff --git a/src/assets/images/Andy.png b/src/assets/images/Andy.png new file mode 100644 index 0000000..78ac85f Binary files /dev/null and b/src/assets/images/Andy.png differ diff --git a/src/assets/images/Antony.png b/src/assets/images/Antony.png new file mode 100644 index 0000000..428786d Binary files /dev/null and b/src/assets/images/Antony.png differ diff --git a/src/assets/images/Biden.png b/src/assets/images/Biden.png new file mode 100644 index 0000000..596bf51 Binary files /dev/null and b/src/assets/images/Biden.png differ diff --git a/src/assets/images/Emmanuel.png b/src/assets/images/Emmanuel.png new file mode 100644 index 0000000..fa6b924 Binary files /dev/null and b/src/assets/images/Emmanuel.png differ diff --git a/src/assets/images/Golding.png b/src/assets/images/Golding.png new file mode 100644 index 0000000..1cc3ca9 Binary files /dev/null and b/src/assets/images/Golding.png differ diff --git a/src/assets/images/Israel.png b/src/assets/images/Israel.png new file mode 100644 index 0000000..b7b86ca Binary files /dev/null and b/src/assets/images/Israel.png differ diff --git a/src/assets/images/Jackson.png b/src/assets/images/Jackson.png new file mode 100644 index 0000000..e4f216b Binary files /dev/null and b/src/assets/images/Jackson.png differ diff --git a/src/assets/images/Matt.png b/src/assets/images/Matt.png new file mode 100644 index 0000000..bd2325d Binary files /dev/null and b/src/assets/images/Matt.png differ diff --git a/src/assets/images/OSINTdefender.png b/src/assets/images/OSINTdefender.png new file mode 100644 index 0000000..3dc1041 Binary files /dev/null and b/src/assets/images/OSINTdefender.png differ diff --git a/src/assets/images/Truzman.png b/src/assets/images/Truzman.png new file mode 100644 index 0000000..c2ff9a9 Binary files /dev/null and b/src/assets/images/Truzman.png differ diff --git a/src/utils/transform.js b/src/utils/transform.js new file mode 100644 index 0000000..a39c9fe --- /dev/null +++ b/src/utils/transform.js @@ -0,0 +1,23 @@ +// 将图片裁剪为圆形并返回 base64 +export function cropImageToCircle(url, size = 100) { + return new Promise((resolve) => { + const img = new window.Image(); + img.crossOrigin = "anonymous"; + img.onload = function () { + const canvas = document.createElement("canvas"); + canvas.width = size; + canvas.height = size; + const ctx = canvas.getContext("2d"); + ctx.clearRect(0, 0, size, size); + ctx.save(); + ctx.beginPath(); + ctx.arc(size / 2, size / 2, size / 2, 0, Math.PI * 2, false); + ctx.closePath(); + ctx.clip(); + ctx.drawImage(img, 0, 0, size, size); + ctx.restore(); + resolve(canvas.toDataURL("image/png")); + }; + img.src = url; + }); +} diff --git a/src/views/KeyNodeRecognition1.vue b/src/views/KeyNodeRecognition1.vue index abde8bd..53df9bb 100644 --- a/src/views/KeyNodeRecognition1.vue +++ b/src/views/KeyNodeRecognition1.vue @@ -1,105 +1,144 @@ \ No newline at end of file +.intruduction { + width: 100%; + margin-top: 0px; + border-radius: 2px; +} +.leader-containner1, +.leader-containner2 { + display: flex; + flex-direction: row; + gap: 10px; +} +.leader-containner2 { + margin-top: 10px; +} +.left-panel { + width: 350px; + flex-shrink: 0; + background-color: rgba(6, 45, 90, 0.3); + border: 1px solid #1a8bff; + display: flex; + flex-direction: column; + padding: 15px; +} +.panel-title { + font-size: 18px; + font-weight: bold; + text-align: center; + padding: 10px; + margin: 0 0 15px 0; + background: linear-gradient( + to right, + rgba(58, 161, 248, 0), + rgba(58, 161, 248, 0.3), + rgba(58, 161, 248, 0) + ); + border-top: 1px solid #3aa1f8; + border-bottom: 1px solid #3aa1f8; + color: #fff; +} +.tabs { + display: flex; + margin-bottom: 15px; + border-bottom: 2px solid #1a5a9c; +} +.tabs button { + background: none; + border: none; + color: #a9c2e0; + padding: 8px 16px; + font-size: 14px; + cursor: pointer; + transition: all 0.3s ease; + position: relative; +} +.tabs button.active { + color: #fff; + font-weight: bold; +} +.tabs button.active::after { + content: ""; + position: absolute; + bottom: -2px; + left: 0; + width: 100%; + height: 2px; + background-color: #3aa1f8; +} +.leader-list { + width: 100%; + height: 410px; + flex-grow: 1; + overflow: auto; + scrollbar-width: none; + color: #fff; +} +.leader-list::-webkit-scrollbar { + width: 4px; +} +.leader-list::-webkit-scrollbar-track { + background: transparent; +} +.leader-list::-webkit-scrollbar-thumb { + background: #3aa1f8; + border-radius: 2px; +} +.leader-item { + display: flex; + align-items: center; + padding: 10px 5px; + border-bottom: 1px solid rgba(58, 161, 248, 0.2); +} +.avatar { + width: 50px; + height: 50px; + border-radius: 50%; + margin-right: 15px; + flex-shrink: 0; +} +.info { + display: flex; + flex-direction: column; + gap: 5px; +} +.name { + display: flex; + align-items: baseline; + gap: 8px; +} +.en-name { + font-size: 16px; + font-weight: bold; +} +.cn-name { + font-size: 14px; + color: #a9c2e0; +} +.stats { + font-size: 12px; + color: #a9c2e0; + display: flex; + gap: 20px; +} +.right-panel { + flex-grow: 1; + position: relative; +} +.key-node-recognition { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} +.background-svg-wrapper { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 1; +} +.content-wrapper { + position: relative; + z-index: 2; + display: flex; + flex-direction: column; + height: 100%; + padding: 15px 20px; + box-sizing: border-box; +} +.graph-title { + text-align: center; + font-size: 20px; + font-weight: bold; + color: #cce7ff; + letter-spacing: 2px; + margin: 0 0 5px 0; + text-shadow: 0 0 5px rgba(58, 161, 248, 0.5); +} +.chart-container { + flex-grow: 1; + width: 100%; + height: calc(100% - 100px); +} +.timeline-container { + width: 100%; + height: 50px; + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 10px; + box-sizing: border-box; +} +.time-label { + font-size: 12px; + color: #a9c2e0; +} +.timeline-track { + flex-grow: 1; + height: 4px; + background: linear-gradient(90deg, #1b62a9, #3aa1f8, #1b62a9); + margin: 0 15px; + position: relative; + display: flex; + justify-content: space-between; + align-items: center; +} +.timeline-point-wrapper { + display: flex; + align-items: center; + justify-content: center; + height: 20px; + cursor: pointer; +} +.timeline-point { + width: 10px; + height: 10px; + background-color: #8dc5ff; + border-radius: 50%; + border: 1px solid #cce7ff; + transition: transform 0.3s ease; + position: relative; +} +.timeline-point-wrapper:hover .timeline-point { + transform: scale(1.5); +} +.timeline-point.active { + background-color: #ffc94d; + border-color: #fff; + transform: scale(1.3); +} +.active-pin { + width: 20px; + height: 24px; + background-image: url('data:image/svg+xml;utf8,'); + position: absolute; + bottom: 5px; + left: 50%; + transform: translateX(-50%); +} +.modal-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.7); + display: flex; + justify-content: center; + align-items: center; + z-index: 1000; +} +.modal-content { + position: relative; + background-color: #0d1b38; + padding: 20px; + border-radius: 8px; + border: 1px solid #3a95ff; + box-shadow: 0 0 25px rgba(58, 149, 255, 0.5); + width: 50vw; + height: 45vh; + display: flex; + flex-direction: column; +} +.close-btn { + position: absolute; + width: 20px; + height: 20px; + + display: flex; + align-items: center; + justify-content: center; + top: 10px; + right: 15px; + border: none; + color: #a7c5d4; + background: none; + font-size: 24px; + cursor: pointer; +} +.details-chart-container { + width: 100%; + flex-grow: 1; +} + diff --git a/src/views/KeyNodeRecognition2.vue b/src/views/KeyNodeRecognition2.vue index de9baa0..b1a8d77 100644 --- a/src/views/KeyNodeRecognition2.vue +++ b/src/views/KeyNodeRecognition2.vue @@ -1,90 +1,486 @@