ww 5 months ago
commit 2a9bdecef6
  1. 6
      .env.development
  2. 4
      .env_1.development
  3. 2
      .env_1.production
  4. 4
      .env_1.test
  5. 65
      .eslintrc_1.cjs
  6. 9
      .prettierrc_1.json
  7. 53
      .stylelintrc_1.cjs
  8. 2
      _1.eslintignore
  9. 24
      _1.gitignore
  10. 4
      _1.stylelintignore
  11. BIN
      dist.zip
  12. 15
      index_1.html
  13. 9
      pnpm-lock.yaml
  14. 14
      src/api/courseChaptersApi.ts
  15. BIN
      src/assets/images/100.png
  16. BIN
      src/assets/images/101.jpg
  17. BIN
      src/assets/images/102.jpg
  18. BIN
      src/assets/images/103.jpg
  19. BIN
      src/assets/images/104.jpg
  20. BIN
      src/assets/images/105.jpg
  21. BIN
      src/assets/images/106.jpg
  22. BIN
      src/assets/images/107.jpg
  23. BIN
      src/assets/images/108.jpg
  24. BIN
      src/assets/images/109.jpg
  25. BIN
      src/assets/images/110.jpg
  26. BIN
      src/assets/images/141.png
  27. BIN
      src/assets/images/142.png
  28. BIN
      src/assets/images/4c.jpeg
  29. BIN
      src/assets/images/R-C.png
  30. BIN
      src/assets/images/a.png
  31. BIN
      src/assets/images/o.jpg
  32. BIN
      src/assets/images/screen (1).png
  33. BIN
      src/assets/images/screen.png
  34. BIN
      src/assets/images/yt.png
  35. BIN
      src/assets/images/zstp.jpg
  36. 10
      src/router/routers.ts
  37. 181
      src/views/course/CourseObjectives.vue
  38. 6
      src/views/course/basicCourseInformation.vue
  39. 9
      src/views/course/components/courseEdit.vue
  40. 430
      src/views/course/largeScreen.vue
  41. 1371
      src/views/portal/LearningPathRecommendations.vue

@ -1,4 +1,8 @@
# 变量必须以 VITE_ 为前缀才能暴露给外部读取
NODE_ENV = 'development'
VITE_APP_TITLE = '无糖运营平台'
VITE_APP_BASE_API = 'http://39.106.16.162:8080'
<<<<<<< HEAD
VITE_APP_BASE_API = 'http://127.0.0.1:8008'
=======
VITE_APP_BASE_API = 'http://39.106.16.162:8080'
>>>>>>> 991fa5ab08c56c84c5a276226f8fbc2ec78f859a

@ -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

24
_1.gitignore vendored

@ -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/*

Binary file not shown.

@ -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>

@ -1,8 +1,17 @@
lockfileVersion: '6.0'
<<<<<<< HEAD
=======
<<<<<<< HEAD
>>>>>>> 991fa5ab08c56c84c5a276226f8fbc2ec78f859a
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
<<<<<<< HEAD
=======
=======
>>>>>>> 1a620e19de970965f426e07348b1dbc4be900eaf
>>>>>>> 991fa5ab08c56c84c5a276226f8fbc2ec78f859a
dependencies:
3d-force-graph:

@ -65,14 +65,14 @@ export function getOrogramObjectiveApi() {
// 获取课程列表
export const getCourseList = (params: any) => {
return request({
url: '/course_objectives/list/' + params.id,
url: '/api/course_objectives/list/' + params.id,
params,
})
}
// 添加分目标
export const addCourse = (data: any) => {
return request({
url: '/objective_contents/addcontent',
url: '/api/objective_contents/addcontent',
method: 'POST',
data,
})
@ -80,7 +80,7 @@ export const addCourse = (data: any) => {
// 编辑目标
export const editCourse = (data: any) => {
return request({
url: '/objective_contents/update',
url: '/api/objective_contents/update',
method: 'PUT',
data,
})
@ -88,7 +88,7 @@ export const editCourse = (data: any) => {
//删除课程目标
export const deleteCourse = (params: any) => {
return request({
url: '/objective_contents/' + params.id,
url: '/api/objective_contents/' + params.id,
method: 'DELETE',
})
}
@ -96,8 +96,8 @@ export const deleteCourse = (params: any) => {
// 获取详情
export const getCourseInfo = (params: any) => {
return request({
url: '/objective_contents/' + params.id,
method: 'get',
params,
url: 'api/objective_contents/' + params.id,
method: "get",
// params
})
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 640 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 359 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 277 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 609 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 557 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

@ -299,4 +299,14 @@ export const constantRoute: any = [
},
],
},
{
path: '/curriculumCenter/largeScreen',
component: () => import('@/views/course/largeScreen.vue'),
name: 'LargeScreen', // name 要与权限一致
meta: {
title: '课程图谱',
hidden: true,
icon: 'Notebook',
},
}
]

@ -3,7 +3,9 @@ import { ref, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { id } from 'element-plus/es/locales.mjs'
import * as echarts from 'echarts'
import { useRoute } from 'vue-router'
// import { useRoute } from 'vue-router'
import {
getCourseList,
addCourse,
@ -11,7 +13,9 @@ import {
deleteCourse,
getCourseInfo,
} from '@/api/courseChaptersApi'
import { useRoute, useRouter } from 'vue-router'
const route = useRoute()
const router = useRouter()
// id id
// targetId
@ -56,7 +60,7 @@ const handleClose = () => {
const submit = async () => {
if (flog.value) {
await editCourse({
id: activeIndex.value,
...editdata.value,
content: formData.value.description,
})
} else {
@ -110,11 +114,13 @@ const filterTarger = (target) => {
return res.label
}
const editdata = ref({ id: '', objectiveId:'' })
//
const flog = ref(false)
const editBook = async (obj) => {
const res = await getCourseInfo({ id: obj.id })
editdata.value.id = res.data.id
editdata.value.objectiveId = res.data.objectiveId
flog.value = true
console.log(obj)
activeIndex.value = res.data.id
@ -154,6 +160,9 @@ const getList = async () => {
const data = ref({})
const courseId = ref(0)
onMounted(async () => {
if (!Object.keys(route.query).length) {
return router.push('/curriculumCenter/basicCourseInformation')
}
courseId.value = route.query.id
console.log(courseId.value)
getList()
@ -162,35 +171,155 @@ onMounted(async () => {
let myChart = echarts.init(chartDom)
let option
option = {
title: {
text: '分目标',
},
legend: {
data: ['Allocated Budget', 'Actual Spending'],
},
radar: {
// shape: 'circle',
indicator: [
{ name: 'Sales', max: 6500 },
{ name: 'Administration', max: 16000 },
{ name: 'Information Technology', max: 30000 },
{ name: 'Customer Support', max: 38000 },
{ name: 'Development', max: 52000 },
{ name: 'Marketing', max: 25000 },
],
},
radar: [
{
nameGap: 20,
indicator: [
{
text: '目标一\n',
max: 100,
},
{
text: '目标五\n\n',
max: 100,
},
{
text: '目标四\n\n',
max: 100,
},
{
text: '目标三\n\n',
max: 100,
},
{
text: '目标二\n\n',
max: 100,
},
],
center: ['50%', '50%'],
radius: 100,
startAngle: 90,
splitNumber: 6,
shape: 'circle',
name: {
formatter: '{value}',
textStyle: {
color: '#333333',
fontSize: 20,
},
gap: 60,
},
splitArea: {
areaStyle: {
color: [
'transparent',
'transparent',
'rgba(114, 172, 209, 0)',
'transparent',
'rgba(114, 172, 209, 0)',
],
},
},
// 线
axisLine: {
lineStyle: {
color: '#C8D9FF',
},
},
splitLine: {
lineStyle: {
color: '#DADADA',
width: 3,
type: 'dashed', //dashed solid dotted 线线 线
},
},
},
{
nameGap: 20,
indicator: [
{
text: '达成度',
max: 100,
},
{
text: '达成度',
max: 100,
},
{
text: '达成度',
max: 100,
},
{
text: '达成度',
max: 100,
},
{
text: '达成度',
max: 100,
},
],
center: ['50%', '50%'],
radius: 100,
startAngle: 90,
splitNumber: 1,
shape: 'circle',
splitArea: {
show: false,
},
axisLine: {
show: false,
},
name: {
formatter: '{value}',
textStyle: {
color: 'rgba(0,0,0,0.4)',
fontSize: 18,
},
},
splitLine: {
lineStyle: {
color: '#6093FF',
type: 'solid',
width: 8,
},
},
},
],
series: [
{
name: 'Budget vs spending',
type: 'radar',
emphasis: {
lineStyle: {
width: 50,
},
},
symbol: 'none',
data: [
{
value: [4200, 3000, 20000, 35000, 50000, 18000],
name: 'Allocated Budget',
value: [74, 60, 80, 60, 74],
name: 'Data C',
areaStyle: {
color: '#DBE4F9',
},
},
],
},
{
type: 'radar',
emphasis: {
lineStyle: {
width: 50,
},
},
symbol: 'none',
data: [
{
value: [5000, 14000, 28000, 26000, 42000, 21000],
name: 'Actual Spending',
value: [74, 60, 80, 40, 74],
name: 'Data B',
areaStyle: {
color: '#0052FF',
},
},
],
},
@ -332,7 +461,7 @@ const li
<style lang="scss" scoped>
#main {
padding: 15px;
padding: 10px;
width: 100%;
height: 100%;
}

@ -33,6 +33,7 @@ const total = ref(0)
const params = ref({
pageNo: 1,
pageSize: 7,
// username: 'qiuqiu',
username: userStore.userName,
assessmenttype: '',
category: '',
@ -43,7 +44,10 @@ const loading = ref(false)
//
const getCourseList = async () => {
loading.value = true
console.log(params.value, '11')
// console.log(params.value, '11')
if (userStore.userInfo.roleId === 2) {
params.value.pageSize = 8
}
const res = await getCourseListApi(params.value)
courseList.value = res.data.list

@ -7,6 +7,9 @@ import { addCourseApi } from '../../../api/user/crouse'
import { getCourseListApi, getCourseDetailApi } from '../../../api/user/crouse'
import request from '../../../utils/request'
import { tool, client } from '../../../utils/alioss.js'
import useUserStore from '@/store/modules/user'
// import { useRoute } from 'vue-router'
const userStore = useUserStore()
//
const visibleDrawer = ref(false)
//
@ -175,8 +178,8 @@ const onSubmit = async () => {
ElMessage.success('添加成功')
//
emit('CloseCouresNameChange')
emit('ClosecreditChange')
emit('CloseclasshoursChange')
// emit('ClosecreditChange')
// emit('CloseclasshoursChange')
}
formModel.value = { ...defaultForm }
imgUrl.value = ''
@ -382,7 +385,7 @@ const upload = async (option: any) => {
</el-form>
<template #footer>
<span class="dialog-footer">
<span class="dialog-footer" v-if="userStore.userInfo.roleId === 1">
<el-button @click="handleClose" size="large">取消</el-button>
<el-button type="primary" size="large" @click="onSubmit()">
确认

@ -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>

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save