@ -1,5 +1,13 @@ |
|||||||
# 变量必须以 VITE_ 为前缀才能暴露给外部读取 |
# 变量必须以 VITE_ 为前缀才能暴露给外部读取 |
||||||
NODE_ENV = 'development' |
NODE_ENV = 'development' |
||||||
VITE_APP_TITLE = '无糖运营平台' |
VITE_APP_TITLE = '无糖运营平台' |
||||||
|
<<<<<<< HEAD |
||||||
# VITE_APP_BASE_API = 'http://39.106.16.162:8080' |
# VITE_APP_BASE_API = 'http://39.106.16.162:8080' |
||||||
VITE_APP_BASE_API = 'http://127.0.0.1:8080' |
VITE_APP_BASE_API = 'http://127.0.0.1:8080' |
||||||
|
======= |
||||||
|
<<<<<<< HEAD |
||||||
|
VITE_APP_BASE_API = 'http://127.0.0.1:8008' |
||||||
|
======= |
||||||
|
VITE_APP_BASE_API = 'http://39.106.16.162:8080' |
||||||
|
>>>>>>> 991fa5ab08c56c84c5a276226f8fbc2ec78f859a |
||||||
|
>>>>>>> 894c303b9a3a43c874f982d2f3256440b2296d26 |
||||||
|
@ -1,4 +0,0 @@ |
|||||||
# 变量必须以 VITE_ 为前缀才能暴露给外部读取 |
|
||||||
NODE_ENV = 'development' |
|
||||||
VITE_APP_TITLE = '无糖运营平台' |
|
||||||
VITE_APP_BASE_API = '/api' |
|
@ -1,2 +0,0 @@ |
|||||||
NODE_ENV = 'production' |
|
||||||
VITE_APP_TITLE = '无糖运营平台' |
|
@ -1,4 +0,0 @@ |
|||||||
# 变量必须以 VITE_ 为前缀才能暴露给外部读取 |
|
||||||
NODE_ENV = 'test' |
|
||||||
VITE_APP_TITLE = '无糖运营平台' |
|
||||||
VITE_APP_BASE_API = '/test-api' |
|
@ -1,65 +0,0 @@ |
|||||||
// @see https://eslint.bootcss.com/docs/rules/ |
|
||||||
|
|
||||||
module.exports = { |
|
||||||
env: { |
|
||||||
browser: true, |
|
||||||
es2021: true, |
|
||||||
node: true, |
|
||||||
jest: true, |
|
||||||
}, |
|
||||||
globals: { |
|
||||||
VANTA: 'readonly', //VANTA 已经cdn引入 这里拒绝eslint报错 全局声明一下 |
|
||||||
ElMessage: 'readonly', |
|
||||||
ElMessageBox: 'readonly', |
|
||||||
ElLoading: 'readonly', |
|
||||||
}, |
|
||||||
/* 指定如何解析语法 */ |
|
||||||
parser: 'vue-eslint-parser', |
|
||||||
/** 优先级低于 parse 的语法解析配置 */ |
|
||||||
parserOptions: { |
|
||||||
ecmaVersion: 'latest', |
|
||||||
sourceType: 'module', |
|
||||||
parser: '@typescript-eslint/parser', |
|
||||||
jsxPragma: 'React', |
|
||||||
ecmaFeatures: { |
|
||||||
jsx: true, |
|
||||||
}, |
|
||||||
}, |
|
||||||
/* 继承已有的规则 */ |
|
||||||
extends: [ |
|
||||||
'eslint:recommended', |
|
||||||
'plugin:vue/vue3-essential', |
|
||||||
'plugin:@typescript-eslint/recommended', |
|
||||||
'plugin:prettier/recommended', |
|
||||||
], |
|
||||||
plugins: ['vue', '@typescript-eslint'], |
|
||||||
/* |
|
||||||
* "off" 或 0 ==> 关闭规则 |
|
||||||
* "warn" 或 1 ==> 打开的规则作为警告(不影响代码执行) |
|
||||||
* "error" 或 2 ==> 规则作为一个错误(代码不能执行,界面报错) |
|
||||||
*/ |
|
||||||
rules: { |
|
||||||
// eslint(https://eslint.bootcss.com/docs/rules/) |
|
||||||
'no-var': 'off', // 要求使用 let 或 const 而不是 var |
|
||||||
'no-multiple-empty-lines': ['off', { max: 1 }], // 不允许多个空行 |
|
||||||
'no-console': process.env.NODE_ENV === 'production' ? 'off' : 'off', |
|
||||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'off' : 'off', |
|
||||||
'no-unexpected-multiline': 'off', // 禁止空余的多行 |
|
||||||
'no-useless-escape': 'off', // 禁止不必要的转义字符 |
|
||||||
|
|
||||||
// typeScript (https://typescript-eslint.io/rules) |
|
||||||
'@typescript-eslint/no-unused-vars': 'off', // 禁止定义未使用的变量 |
|
||||||
'@typescript-eslint/prefer-ts-expect-off': 'off', // 禁止使用 @ts-ignore |
|
||||||
'@typescript-eslint/ban-ts-ignore': 'off', |
|
||||||
'@typescript-eslint/no-explicit-any': 'off', // 禁止使用 any 类型 |
|
||||||
'@typescript-eslint/no-non-null-assertion': 'off', |
|
||||||
'@typescript-eslint/no-namespace': 'off', // 禁止使用自定义 TypeScript 模块和命名空间。 |
|
||||||
'@typescript-eslint/semi': 'off', |
|
||||||
|
|
||||||
// eslint-plugin-vue (https://eslint.vuejs.org/rules/) |
|
||||||
'vue/multi-word-component-names': 'off', // 要求组件名称始终为 “-” 链接的单词 |
|
||||||
'vue/script-setup-uses-vars': 'off', // 防止<script setup>使用的变量<template>被标记为未使用 |
|
||||||
'vue/no-mutating-props': 'off', // 不允许组件 prop的改变 |
|
||||||
'vue/attribute-hyphenation': 'off', // 对模板中的自定义组件强制执行属性命名样式 |
|
||||||
}, |
|
||||||
} |
|
@ -1,9 +0,0 @@ |
|||||||
{ |
|
||||||
"singleQuote": true, |
|
||||||
"semi": false, |
|
||||||
"bracketSpacing": true, |
|
||||||
"htmlWhitespaceSensitivity": "ignore", |
|
||||||
"endOfLine": "auto", |
|
||||||
"trailingComma": "all", |
|
||||||
"tabWidth": 2 |
|
||||||
} |
|
@ -1,53 +0,0 @@ |
|||||||
// @see https://stylelint.bootcss.com/ |
|
||||||
|
|
||||||
module.exports = { |
|
||||||
extends: [ |
|
||||||
'stylelint-config-standard', // 配置stylelint拓展插件 |
|
||||||
'stylelint-config-standard-vue', // 配置 vue 中 template 样式格式化 |
|
||||||
'stylelint-config-standard-scss', // 配置stylelint scss插件 |
|
||||||
'stylelint-config-recommended-vue/scss', // 配置 vue 中 scss 样式格式化 |
|
||||||
'stylelint-config-recess-order', // 配置stylelint css属性书写顺序插件, |
|
||||||
'stylelint-config-prettier', // 配置stylelint和prettier兼容 |
|
||||||
], |
|
||||||
overrides: [ |
|
||||||
{ |
|
||||||
files: ['**/*.(scss|css|vue|html)'], |
|
||||||
customSyntax: 'postcss-scss', |
|
||||||
}, |
|
||||||
{ |
|
||||||
files: ['**/*.(html|vue)'], |
|
||||||
customSyntax: 'postcss-html', |
|
||||||
}, |
|
||||||
], |
|
||||||
ignoreFiles: [ |
|
||||||
'**/*.js', |
|
||||||
'**/*.jsx', |
|
||||||
'**/*.tsx', |
|
||||||
'**/*.ts', |
|
||||||
'**/*.json', |
|
||||||
'**/*.md', |
|
||||||
'**/*.yaml', |
|
||||||
], |
|
||||||
/** |
|
||||||
* null => 关闭该规则 |
|
||||||
* always => 必须 |
|
||||||
*/ |
|
||||||
rules: { |
|
||||||
'value-keyword-case': null, // 在 css 中使用 v-bind,不报错 |
|
||||||
'no-descending-specificity': null, // 禁止在具有较高优先级的选择器后出现被其覆盖的较低优先级的选择器 |
|
||||||
'function-url-quotes': 'always', // 要求或禁止 URL 的引号 "always(必须加上引号)"|"never(没有引号)" |
|
||||||
'no-empty-source': null, // 关闭禁止空源码 |
|
||||||
'selector-class-pattern': null, // 关闭强制选择器类名的格式 |
|
||||||
'property-no-unknown': null, // 禁止未知的属性(true 为不允许) |
|
||||||
'block-opening-brace-space-before': 'always', //大括号之前必须有一个空格或不能有空白符 |
|
||||||
'value-no-vendor-prefix': null, // 关闭 属性值前缀 --webkit-box |
|
||||||
'property-no-vendor-prefix': null, // 关闭 属性前缀 -webkit-mask |
|
||||||
'selector-pseudo-class-no-unknown': [ |
|
||||||
// 不允许未知的选择器 |
|
||||||
true, |
|
||||||
{ |
|
||||||
ignorePseudoClasses: ['global', 'v-deep', 'deep'], // 忽略属性,修改element默认样式的时候能使用到 |
|
||||||
}, |
|
||||||
], |
|
||||||
}, |
|
||||||
} |
|
@ -1,2 +0,0 @@ |
|||||||
dist |
|
||||||
node_modules |
|
@ -1,24 +0,0 @@ |
|||||||
# Logs |
|
||||||
logs |
|
||||||
*.log |
|
||||||
npm-debug.log* |
|
||||||
yarn-debug.log* |
|
||||||
yarn-error.log* |
|
||||||
pnpm-debug.log* |
|
||||||
lerna-debug.log* |
|
||||||
|
|
||||||
node_modules |
|
||||||
dist |
|
||||||
dist-ssr |
|
||||||
*.local |
|
||||||
|
|
||||||
# Editor directories and files |
|
||||||
.vscode/* |
|
||||||
!.vscode/extensions.json |
|
||||||
.idea |
|
||||||
.DS_Store |
|
||||||
*.suo |
|
||||||
*.ntvs* |
|
||||||
*.njsproj |
|
||||||
*.sln |
|
||||||
*.sw? |
|
@ -1,4 +0,0 @@ |
|||||||
/node_modules/* |
|
||||||
/dist/* |
|
||||||
/html/* |
|
||||||
/public/* |
|
@ -1,15 +0,0 @@ |
|||||||
<!doctype html> |
|
||||||
<html lang="en"> |
|
||||||
<head> |
|
||||||
<meta charset="UTF-8" /> |
|
||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> |
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
|
||||||
<title>教学一体化后师生后台</title> |
|
||||||
</head> |
|
||||||
<body> |
|
||||||
<div id="app"></div> |
|
||||||
<script type="module" src="/src/main.ts"></script> |
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r134/three.min.js"></script> |
|
||||||
<script src="https://cdn.jsdelivr.net/npm/vanta@latest/dist/vanta.globe.min.js"></script> |
|
||||||
</body> |
|
||||||
</html> |
|
After Width: | Height: | Size: 640 KiB |
After Width: | Height: | Size: 1.3 MiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 210 KiB |
After Width: | Height: | Size: 131 KiB |
After Width: | Height: | Size: 78 KiB |
After Width: | Height: | Size: 99 KiB |
After Width: | Height: | Size: 94 KiB |
After Width: | Height: | Size: 206 KiB |
After Width: | Height: | Size: 180 KiB |
After Width: | Height: | Size: 166 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 142 KiB |
After Width: | Height: | Size: 359 KiB |
After Width: | Height: | Size: 277 KiB |
After Width: | Height: | Size: 609 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 557 KiB |
After Width: | Height: | Size: 122 KiB |
@ -0,0 +1,430 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
|
||||||
|
<div class="container"> |
||||||
|
<div class="goto" @click="goBack"> |
||||||
|
<p>返回</p> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script lang="ts" > |
||||||
|
import * as d3 from 'd3'; |
||||||
|
import { useRouter } from 'vue-router' |
||||||
|
// import portal from './portal/LearningPathRecommendations.vue' |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// import { onMounted } from 'vue'; |
||||||
|
|
||||||
|
export default { |
||||||
|
name: 'courseHomepage', |
||||||
|
data() { |
||||||
|
return { |
||||||
|
svgArea: null, |
||||||
|
links: [], |
||||||
|
nodes: [], |
||||||
|
nodesName: [], |
||||||
|
linksName: [], |
||||||
|
simulation: null, |
||||||
|
scale: 1, |
||||||
|
width: 800, |
||||||
|
height: 635, |
||||||
|
colorList: ['#91CC75', '#5470C6', '#FAC858', '#EE6666', '#73C0DE', '#EA7CCC', '#5577FF', '#5577FF', '#9DBFFF', '#78A7FF'], |
||||||
|
// colorList: ['#E5A1D6', '#A893F5', '#D0A4FB', '#C3ACF6', '#FBBABB', '#8B81F7', '#A893F5', '#D0A4FB', '#C3ACF6', '#FBBABB'], |
||||||
|
testGraph: { |
||||||
|
"nodes": [], |
||||||
|
"links": [] |
||||||
|
// "nodes": [ |
||||||
|
// { "id": "Myriel", "group": 8 }, |
||||||
|
// { "id": "Napoleon", "group": 2 }, |
||||||
|
// { "id": "Mlle.Baptistine", "group": 3 }, |
||||||
|
// { "id": "Mme.Magloire", "group": 1 }, |
||||||
|
// { "id": "CountessdeLo", "group": 5 }, |
||||||
|
// { "id": "Geborand", "group": 5 }, |
||||||
|
// { "id": "Champtercier", "group": 6 }, |
||||||
|
// { "id": "Cravatte", "group": 7 }, |
||||||
|
// { "id": "Count", "group": 8 }, |
||||||
|
// { "id": "OldMan", "group": 9 }, |
||||||
|
// { "id": "Labarre", "group": 5 }, |
||||||
|
// { "id": "Valjean", "group": 1 }, |
||||||
|
// { "id": "Marguerite", "group": 3 }, |
||||||
|
// { "id": "Mme.deR", "group": 2 }, |
||||||
|
// { "id": "Isabeau", "group": 5 }, |
||||||
|
// { "id": "Gervais", "group": 9 }, |
||||||
|
// { "id": "Tholomyes", "group": 8 }, |
||||||
|
// { "id": "Listolier", "group": 7 }, |
||||||
|
// { "id": "Fameuil", "group": 6 }, |
||||||
|
// { "id": "Blacheville", "group": 5 }, |
||||||
|
// { "id": "Favourite", "group": 4 }, |
||||||
|
// { "id": "Dahlia", "group": 3 }, |
||||||
|
// { "id": "Zephine", "group": 9 }, |
||||||
|
// { "id": "Fantine", "group": 3 }, |
||||||
|
// { "id": "Mme.Thenardier", "group": 4 }, |
||||||
|
// { "id": "Thenardier", "group": 4 }, |
||||||
|
// { "id": "Cosette", "group": 5 }, |
||||||
|
// { "id": "Javert", "group": 4 }, |
||||||
|
// { "id": "Fauchelevent", "group": 0 }, |
||||||
|
// { "id": "Bamatabois", "group": 2 }, |
||||||
|
|
||||||
|
// // { "id": "Mme.Hucheloup", "group": 8 } |
||||||
|
// ], |
||||||
|
// "links": [ |
||||||
|
// { "source": "Napoleon", "target": "Myriel", "value": 7 }, |
||||||
|
// { "source": "Mlle.Baptistine", "target": "Myriel", "value": 7 }, |
||||||
|
// { "source": "Mme.Magloire", "target": "Myriel", "value": 7 }, |
||||||
|
// { "source": "Mme.Magloire", "target": "Mlle.Baptistine", "value": 7 }, |
||||||
|
// { "source": "CountessdeLo", "target": "Myriel", "value": 7 }, |
||||||
|
// { "source": "Geborand", "target": "Myriel", "value": 7 }, |
||||||
|
// { "source": "Champtercier", "target": "Myriel", "value": 7 }, |
||||||
|
// { "source": "Cravatte", "target": "Myriel", "value": 7 }, |
||||||
|
// { "source": "Count", "target": "Myriel", "value": 7 }, |
||||||
|
// { "source": "OldMan", "target": "Myriel", "value": 7 }, |
||||||
|
// { "source": "Valjean", "target": "Labarre", "value": 7 }, |
||||||
|
// { "source": "Valjean", "target": "Mme.Magloire", "value": 7 }, |
||||||
|
// { "source": "Valjean", "target": "Mlle.Baptistine", "value": 3 }, |
||||||
|
// { "source": "Valjean", "target": "Myriel", "value": 5 }, |
||||||
|
// { "source": "Marguerite", "target": "Valjean", "value": 1 }, |
||||||
|
// { "source": "Mme.deR", "target": "Valjean", "value": 1 }, |
||||||
|
// { "source": "Isabeau", "target": "Valjean", "value": 1 }, |
||||||
|
// { "source": "Gervais", "target": "Valjean", "value": 1 }, |
||||||
|
// { "source": "Listolier", "target": "Tholomyes", "value": 4 }, |
||||||
|
// { "source": "Fameuil", "target": "Tholomyes", "value": 4 }, |
||||||
|
// { "source": "Fameuil", "target": "Listolier", "value": 4 }, |
||||||
|
// { "source": "Blacheville", "target": "Tholomyes", "value": 4 }, |
||||||
|
// { "source": "Blacheville", "target": "Listolier", "value": 4 }, |
||||||
|
// { "source": "Blacheville", "target": "Fameuil", "value": 4 }, |
||||||
|
// { "source": "Favourite", "target": "Tholomyes", "value": 3 }, |
||||||
|
// { "source": "Favourite", "target": "Listolier", "value": 3 }, |
||||||
|
// { "source": "Favourite", "target": "Fameuil", "value": 3 }, |
||||||
|
// { "source": "Favourite", "target": "Blacheville", "value": 4 }, |
||||||
|
// { "source": "Dahlia", "target": "Tholomyes", "value": 3 }, |
||||||
|
// { "source": "Dahlia", "target": "Listolier", "value": 3 }, |
||||||
|
// { "source": "Dahlia", "target": "Fameuil", "value": 3 }, |
||||||
|
// { "source": "Dahlia", "target": "Blacheville", "value": 3 }, |
||||||
|
// { "source": "Dahlia", "target": "Favourite", "value": 5 }, |
||||||
|
// { "source": "Zephine", "target": "Tholomyes", "value": 3 }, |
||||||
|
// { "source": "Zephine", "target": "Listolier", "value": 3 }, |
||||||
|
// { "source": "Zephine", "target": "Fameuil", "value": 3 }, |
||||||
|
|
||||||
|
// // { "source": "Mme.Hucheloup", "target": "Enjolras", "value": 1 } |
||||||
|
// ] |
||||||
|
// "links":[] |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
}, |
||||||
|
created() { |
||||||
|
this.getGraphData() |
||||||
|
}, |
||||||
|
// mounted() { |
||||||
|
|
||||||
|
// this.initGraph(this.testGraph); |
||||||
|
|
||||||
|
// }, |
||||||
|
methods: { |
||||||
|
getGraphData(){ |
||||||
|
var _this = this |
||||||
|
this.axios.get("person/"+'Rob Reiner') |
||||||
|
// this.axios.get("person/all") |
||||||
|
.then(function (response: { data: any; }) { |
||||||
|
console.log(response) |
||||||
|
_this.testGraph["nodes"] = [response.data] |
||||||
|
_this.initGraph(_this.testGraph) |
||||||
|
}) |
||||||
|
.catch(function (error: any) { |
||||||
|
console.log(error) |
||||||
|
}) |
||||||
|
}, |
||||||
|
|
||||||
|
initGraph(data: { |
||||||
|
nodes: { id: string; group: number; }[]; links: { // import { onMounted } from 'vue'; |
||||||
|
source: string; target: string; value: number; |
||||||
|
}[]; |
||||||
|
}) { |
||||||
|
const _this = this; |
||||||
|
|
||||||
|
|
||||||
|
const links = data.links; |
||||||
|
const nodes = data.nodes; |
||||||
|
|
||||||
|
|
||||||
|
const simulation = d3.forceSimulation(nodes) |
||||||
|
.force("link", d3.forceLink(links).id((d: { id: any; }) => d.id)) |
||||||
|
|
||||||
|
.force("collide", d3.forceCollide().radius(() => 40)) |
||||||
|
.force("charge", d3.forceManyBody().strength(30)) |
||||||
|
.force("center", d3.forceCenter(_this.width / 2, _this.height / 2)); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const svg = d3.select(".container") |
||||||
|
.append("svg") |
||||||
|
.attr("viewBox", `0 0 ${_this.width} ${_this.height}`) |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 初始化阶段之外单独创建线性渐变 |
||||||
|
const defs = svg.append("defs"); |
||||||
|
|
||||||
|
// 在 initGraph 方法中,为每条链接创建线性渐变 |
||||||
|
for (let i = 0; i < links.length; i++) { |
||||||
|
const linearGradient = defs.append("linearGradient") |
||||||
|
.attr("id", `line-gradient-${i}`) |
||||||
|
.attr("x1", "0%") |
||||||
|
.attr("y1", "0%") |
||||||
|
.attr("x2", "100%") |
||||||
|
.attr("y2", "100%"); |
||||||
|
|
||||||
|
linearGradient.append("stop") |
||||||
|
.attr("offset", "0%") |
||||||
|
.attr("stop-color", "#6C9DFC"); |
||||||
|
|
||||||
|
linearGradient.append("stop") |
||||||
|
.attr("offset", "50%") |
||||||
|
.attr("stop-color", "#9BAAFA"); |
||||||
|
|
||||||
|
linearGradient.append("stop") |
||||||
|
.attr("offset", "100%") |
||||||
|
.attr("stop-color", "#F3B1BC"); |
||||||
|
} |
||||||
|
const g = svg.append("g") |
||||||
|
// 线段 |
||||||
|
const link = g.append("g") |
||||||
|
.attr("stroke-opacity", 0.6) |
||||||
|
.selectAll("line") |
||||||
|
.data(links) |
||||||
|
.join("line") |
||||||
|
.style("stroke", (_d: any, i: any) => `url(#line-gradient-${i})`) // 使用线性渐变设置描边颜色 |
||||||
|
.style("stroke-width", (d: { value: number; }) => Math.sqrt(d.value)) |
||||||
|
.attr("class", "link") |
||||||
|
.attr("marker-end", "url(#arrow)"); |
||||||
|
|
||||||
|
|
||||||
|
// // 创建箭头 |
||||||
|
// const marker = defs.append("marker") |
||||||
|
// .attr("id", "arrow") |
||||||
|
// .attr("viewBox", "0 -5 10 10") |
||||||
|
// .attr("refX", 31) |
||||||
|
// .attr("refY", 0) |
||||||
|
// .attr("markerWidth", 6) |
||||||
|
// .attr("markerHeight", 6) |
||||||
|
// .attr("orient", "auto") |
||||||
|
// .append("path") |
||||||
|
// .attr("d", "M0,-5L10,0L0,5") |
||||||
|
// .attr("fill", "#E0AAED"); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
svg.call(d3.zoom().on("zoom", function () { |
||||||
|
g.attr("transform", d3.event.transform) |
||||||
|
})) |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 设置节点之间的距离 |
||||||
|
const linkForce = d3.forceLink(links) |
||||||
|
.id((d: { id: any; }) => d.id) |
||||||
|
.distance(100); // 设置节点之间的距离 |
||||||
|
|
||||||
|
simulation.force("link", linkForce); |
||||||
|
|
||||||
|
//小球的可视化范围的修改 |
||||||
|
|
||||||
|
const node = g.append("g") |
||||||
|
.selectAll("circle") |
||||||
|
.data(nodes) |
||||||
|
.join("circle") |
||||||
|
.attr("r", 15) |
||||||
|
.attr("class", "node") |
||||||
|
.attr("fill", (d: { id: any; }) => { |
||||||
|
return `url(#node-gradient-${d.id})`; |
||||||
|
}) |
||||||
|
// .attr("fill", _this.color) |
||||||
|
.on("click", _this.queryTest) |
||||||
|
.call(_this.drag(simulation)); |
||||||
|
|
||||||
|
// 在 initGraph 方法中为每个小球创建线性渐变 |
||||||
|
for (let i = 0; i < nodes.length; i++) { |
||||||
|
const linearGradient = defs.append("linearGradient") |
||||||
|
.attr("id", `node-gradient-${nodes[i].id}`) |
||||||
|
.attr("x1", "0%") |
||||||
|
.attr("y1", "0%") |
||||||
|
.attr("x2", "0%") |
||||||
|
.attr("y2", "100%"); |
||||||
|
|
||||||
|
linearGradient.append("stop") |
||||||
|
.attr("offset", "0%") |
||||||
|
.attr("stop-color", _this.colorList[nodes[i].group]); |
||||||
|
|
||||||
|
linearGradient.append("stop") |
||||||
|
.attr("offset", "100%") |
||||||
|
.attr("stop-color", "#9BBCFC"); |
||||||
|
} |
||||||
|
|
||||||
|
node.append("title") |
||||||
|
.text((d: { id: any; }) => d.id); |
||||||
|
|
||||||
|
const nodeNameText = g.append("g") |
||||||
|
.selectAll("text") |
||||||
|
.data(nodes) |
||||||
|
.join("text") |
||||||
|
.text(function (d: { id: any; }) { |
||||||
|
return d.id |
||||||
|
}) |
||||||
|
.attr("fill", "white") |
||||||
|
// .attr("dx", function () { |
||||||
|
// return this.getBoundingClientRect().width / 2 * (-1) |
||||||
|
// }) |
||||||
|
.attr('x', (d: { x: any; }) => d.x) |
||||||
|
.attr("y", 50) |
||||||
|
.attr('text-anchor', 'middle') |
||||||
|
.attr('alignment-baseline', 'middle') |
||||||
|
.attr("class", "node-name") |
||||||
|
.style('pointer-events', 'none') |
||||||
|
.style('font-size', '15px') |
||||||
|
.style('font-family', 'Arial') |
||||||
|
.style('text-shadow', '1px 1px 1px #0052FF') |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
node.on("mouseover", function (_d: any, _i: any) { |
||||||
|
d3.select(this) |
||||||
|
.attr("stroke", "white") // 添加白色边框 |
||||||
|
.attr("stroke-width", 5); // 设置边框宽度 |
||||||
|
}) |
||||||
|
.on("mouseout", function (_d: any, _i: any) { |
||||||
|
d3.select(this) |
||||||
|
.attr("stroke", "none"); // 移出时恢复原始样式 |
||||||
|
}); |
||||||
|
|
||||||
|
|
||||||
|
simulation.on("tick", () => { |
||||||
|
link |
||||||
|
.attr("x1", (d: { source: { x: any; }; }) => d.source.x) |
||||||
|
.attr("y1", (d: { source: { y: any; }; }) => d.source.y) |
||||||
|
.attr("x2", (d: { target: { x: any; }; }) => d.target.x) |
||||||
|
.attr("y2", (d: { target: { y: any; }; }) => d.target.y); |
||||||
|
|
||||||
|
node |
||||||
|
.attr("cx", (d: { x: any; }) => d.x) |
||||||
|
.attr("cy", (d: { y: any; }) => d.y); |
||||||
|
|
||||||
|
nodeNameText |
||||||
|
.attr("x", (d: { x: any; }) => d.x) |
||||||
|
.attr("y", (d: { y: any; }) => d.y); |
||||||
|
|
||||||
|
}); |
||||||
|
}, |
||||||
|
updateGraph(data: { links: any[]; }) { |
||||||
|
// var _this = this |
||||||
|
const links = data.links.map((d: object | null) => Object.create(d)); |
||||||
|
const nodes = data.nodes.map((d: object | null) => Object.create(d)); |
||||||
|
}, |
||||||
|
color(d: { group: string | number; }) { |
||||||
|
return this.colorList[d.group] |
||||||
|
// const scale = d3.scaleOrdinal(d3.schemeCategory10); |
||||||
|
// return (d: { group: any; }) => scale(d.group); |
||||||
|
}, |
||||||
|
drag(simulation: { alphaTarget: (arg0: number) => { (): any; new(): any; restart: { (): void; new(): any; }; }; }) { |
||||||
|
function dragstarted(event: { active: any; }) { |
||||||
|
if (!event.active) simulation.alphaTarget(0.3).restart(); |
||||||
|
d3.event.subject.fx = d3.event.x; |
||||||
|
d3.event.subject.fy = d3.event.y; |
||||||
|
} |
||||||
|
|
||||||
|
function dragged(_event: any) { |
||||||
|
d3.event.subject.fx = d3.event.x; |
||||||
|
d3.event.subject.fy = d3.event.y; |
||||||
|
} |
||||||
|
|
||||||
|
function dragended(event: { active: any; }) { |
||||||
|
if (!event.active) simulation.alphaTarget(0); |
||||||
|
d3.event.subject.fx = null; |
||||||
|
d3.event.subject.fy = null; |
||||||
|
} |
||||||
|
|
||||||
|
return d3.drag() |
||||||
|
.on("start", dragstarted) |
||||||
|
.on("drag", dragged) |
||||||
|
.on("end", dragended); |
||||||
|
}, |
||||||
|
queryTest(d: { id: any; }) { |
||||||
|
// var _this = this |
||||||
|
console.log(d.id) |
||||||
|
} |
||||||
|
|
||||||
|
}, |
||||||
|
setup() { |
||||||
|
const router = useRouter(); |
||||||
|
|
||||||
|
const goBack = () => { |
||||||
|
router.go(-1); |
||||||
|
}; |
||||||
|
|
||||||
|
return { |
||||||
|
goBack |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
|
||||||
|
// d3 |
||||||
|
.container { |
||||||
|
// width: 1000px; |
||||||
|
// height: 950px; |
||||||
|
// border: 1px solid #2c3e50; |
||||||
|
// border-radius: 8px; |
||||||
|
// margin-top: 40px; |
||||||
|
// margin-left: auto; |
||||||
|
// border-radius: 90%; |
||||||
|
// margin-right: auto; |
||||||
|
|
||||||
|
border: 1px solid #CFD9EA; |
||||||
|
background: linear-gradient(#d5e1f6, #a9c6ff, #d5e1f6); |
||||||
|
background-image: url('/src/assets/images/106.jpg'); |
||||||
|
// background-size: 100% 80%; |
||||||
|
background-size: 100% ; |
||||||
|
|
||||||
|
background-attachment: fixed; |
||||||
|
// border-radius: 50%; // 左下、右下圆角处理 |
||||||
|
// background-color: rgba(0, 0, 0, 0); /* 50% 的透明度 */ |
||||||
|
|
||||||
|
} |
||||||
|
.goto { |
||||||
|
width: 4.5%; |
||||||
|
height: 3.4%; |
||||||
|
background-color: rgb(255, 255, 255,0.5); |
||||||
|
// background-image: url('/src/assets/images/screen (1).png'); |
||||||
|
// background-size: 100% 100%; |
||||||
|
border-radius: 8px; |
||||||
|
position: absolute; |
||||||
|
top: 5%; |
||||||
|
margin-left: 94%; |
||||||
|
z-index: 5; |
||||||
|
cursor: pointer; |
||||||
|
} |
||||||
|
.goto p{ |
||||||
|
text-align: center; |
||||||
|
color: #ffffff; |
||||||
|
line-height: 30px; |
||||||
|
font-size: 14px; |
||||||
|
} |
||||||
|
// .goto :hover{ |
||||||
|
// background-color: #a2abbb; |
||||||
|
// border-radius: 8px; |
||||||
|
// width: 4.5%; |
||||||
|
// height: 3.4%; |
||||||
|
// } |
||||||
|
|
||||||
|
</style> |
||||||
|
|