Commit c4768c68 authored by 郭铭瑶's avatar 郭铭瑶 🤘

连接subject功能&去除拖拽物理作用力

parent cee5ea2c
......@@ -15,4 +15,5 @@ export default {
GET_NODES: '/node/relations',
DELETE_NODE: '/node/{id}',
GET_SYSTEMS: '/systems',
POST_LINK_SUBJECTS: '/node/relations',
}
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1629110949117" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2116" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M529.322667 635.946667a42.666667 42.666667 0 0 0-23.168 55.765333 42.666667 42.666667 0 0 1-9.258667 46.506667l-120.661333 120.704a85.333333 85.333333 0 0 1-120.661334 0L165.034667 768.426667a85.333333 85.333333 0 0 1 0-120.704L285.866667 527.061333a43.221333 43.221333 0 0 1 46.549333-9.258666 42.666667 42.666667 0 0 0 32.554667-78.890667 129.450667 129.450667 0 0 0-139.434667 27.818667l-120.832 120.661333a170.922667 170.922667 0 0 0 0 241.365333l90.538667 90.496a170.666667 170.666667 0 0 0 241.322666 0l120.704-120.661333a128.341333 128.341333 0 0 0 27.776-139.52 42.666667 42.666667 0 0 0-55.722666-23.125333z" p-id="2117" fill="#ffffff"></path><path d="M330.965333 692.949333a43.136 43.136 0 0 0 60.330667 0l331.904-331.861333a42.666667 42.666667 0 0 0-60.330667-60.330667l-331.904 331.861334a42.666667 42.666667 0 0 0 0 60.330666z" p-id="2118" fill="#ffffff"></path><path d="M919.296 195.157333l-90.496-90.496a170.922667 170.922667 0 0 0-241.365333 0l-120.704 120.661334a128.256 128.256 0 0 0-27.776 139.477333 42.666667 42.666667 0 1 0 78.890666-32.597333 42.666667 42.666667 0 0 1 9.258667-46.336l120.661333-120.661334a85.333333 85.333333 0 0 1 120.704 0l90.496 90.496a85.333333 85.333333 0 0 1 0 120.704L738.133333 496.853333a43.306667 43.306667 0 0 1-46.549333 9.258667 42.666667 42.666667 0 0 0-32.64 78.890667 129.109333 129.109333 0 0 0 139.52-27.776l120.661333-120.661334a170.965333 170.965333 0 0 0 0.170667-241.408z" p-id="2119" fill="#ffffff"></path></svg>
\ No newline at end of file
......@@ -31,7 +31,7 @@
import RelationGraph from '@/util/useD3.js'
import { watch, ref } from 'vue'
import branch from '@/assets/images/branch.svg'
import more from '@/assets/images/more.svg'
import link from '@/assets/images/link.svg'
import add from '@/assets/images/add.svg'
import del from '@/assets/images/delete.svg'
export default {
......@@ -48,7 +48,7 @@ export default {
},
},
},
emits: ['more', 'add', 'del', 'branch', 'curNode'],
emits: ['link', 'add', 'del', 'branch', 'curNode'],
setup(props, ctx) {
const colorList = {
default: 'skyblue',
......@@ -70,12 +70,12 @@ export default {
action: (d) => ctx.emit('branch', d),
title: '分支',
},
// {
// key: 'more',
// icon: more,
// action: (d) => ctx.emit('more', d),
// title: '更多',
// },
{
key: 'link',
icon: link,
action: (d) => ctx.emit('link', d),
title: '连接',
},
{
key: 'add',
icon: add,
......
......@@ -10,6 +10,7 @@
@add="openAddDrawer"
@curNode="curNode = $event"
@del="deleteNode"
@link="showLinkDrawer = true"
/>
<Side style="grid-area: side" />
<Footer
......@@ -22,7 +23,7 @@
/>
</div>
<n-drawer v-model:show="showDrawer" :width="400" placement="left">
<n-drawer-content title="新增节点">
<n-drawer-content title="新增附属节点">
<n-form ref="formRef" :model="formData" :rules="rules">
<n-form-item path="propertyName" label="节点名称">
<n-input
......@@ -54,7 +55,7 @@
</n-drawer-content>
</n-drawer>
<n-drawer v-model:show="showSubjectDrawer" :width="400" placement="left">
<n-drawer-content title="新增Suject">
<n-drawer-content title="新增主体">
<n-form ref="subjectFormRef" :model="subjectData" :rules="rules">
<n-form-item path="subjectName" label="名称">
<n-input
......@@ -71,6 +72,32 @@
</n-form>
</n-drawer-content>
</n-drawer>
<n-drawer v-model:show="showLinkDrawer" :width="400" placement="left">
<n-drawer-content title="连接主体">
<n-form ref="linkFormRef" :model="linkData" :rules="rules">
<n-form-item path="sourceNodeId" label="源主体">
<n-select
v-model:value="linkData.sourceNodeId"
placeholder="请选择"
:options="subjectOptions"
disabled
/>
</n-form-item>
<n-form-item path="targetNodeId" label="目标主体">
<n-select
v-model:value="linkData.targetNodeId"
placeholder="请选择"
:options="subjectOptions"
/>
</n-form-item>
<n-space justify="end">
<n-button :loading="isLoading" type="primary" @click="linkSubject">
提交
</n-button>
</n-space>
</n-form>
</n-drawer-content>
</n-drawer>
</template>
<script>
......@@ -79,10 +106,9 @@ import Nav from './nav.vue'
import Side from './side.vue'
import Footer from './footer.vue'
import mockData from '@/util/mock.js'
import { ref } from 'vue'
import { ref, watch } from 'vue'
import { ajax, api } from '@/ajax'
import { useMessage, useDialog } from 'naive-ui'
export default {
name: 'Main',
components: { D3, Nav, Side, Footer },
......@@ -102,7 +128,7 @@ export default {
const relationOptions = ref([])
const systemOptions = ref([])
const graphData = ref({ nodes: [], links: [] })
const subjectNodes = ref([])
const subjectOptions = ref([])
function fetchSubjects() {
ajax
......@@ -111,9 +137,13 @@ export default {
})
.then((res) => {
console.log('subject', res.data.content)
subjectNodes.value = res.data.content
const data = res.data.content
subjectOptions.value = data.map((item) => ({
label: item.subjectName,
value: item.nodeId,
}))
graphData.value = {
nodes: [...subjectNodes.value],
nodes: [...data],
links: [],
}
})
......@@ -289,6 +319,95 @@ export default {
graphData.value = res.data.content
})
}
const showLinkDrawer = ref(false)
const linkData = ref({
sourceNodeId: null,
targetNodeId: null,
})
watch(
() => curNode.value,
(cur) => {
linkData.value = {
sourceNodeId: cur && cur.nodeId,
targetNodeId: null,
}
}
)
const linkFormRef = ref(null)
const linkSubject = (e) => {
e.preventDefault()
linkFormRef.value.validate((errors) => {
if (!errors) {
isLoading.value = true
ajax
.post({
url: api.POST_LINK_SUBJECTS,
params: linkData.value,
})
.then(() => {
fetchSubordinates({
nodeId: linkData.value.sourceNodeId,
nodeLabel: 'Subject',
})
isLoading.value = false
showLinkDrawer.value = false
message.success('提交成功')
})
}
})
}
const rules = {
subjectName: [
{
required: true,
message: '请输入名称',
trigger: ['input', 'blur'],
},
],
propertyName: [
{
required: true,
message: '请输入节点名称',
trigger: ['input', 'blur'],
},
],
relationId: [
{
required: true,
message: '请选择从属类型',
trigger: ['change', 'blur'],
},
],
systemId: [
{
required: true,
message: '请选择所属系统',
trigger: ['change', 'blur'],
},
],
sourceNodeId: [
{
required: true,
message: '请选择源主体',
trigger: ['change', 'blur'],
},
],
targetNodeId: [
{
required: true,
message: '请选择目标主体',
trigger: ['change', 'blur'],
},
{
validator(_, value) {
return value !== linkData.value.sourceNodeId
},
trigger: ['blur', 'change'],
message: '目标主体不能与源主体相同',
},
],
}
return {
formRef,
formData,
......@@ -303,36 +422,7 @@ export default {
openAddDrawer,
d3Ref,
setLabelKey,
rules: {
subjectName: [
{
required: true,
message: '请输入名称',
trigger: ['input', 'blur'],
},
],
propertyName: [
{
required: true,
message: '请输入节点名称',
trigger: ['input', 'blur'],
},
],
relationId: [
{
required: true,
message: '请选择从属类型',
trigger: ['input', 'blur'],
},
],
systemId: [
{
required: true,
message: '请选择所属系统',
trigger: ['input', 'blur'],
},
],
},
rules,
curNode,
deleteNode,
showSubjectDrawer,
......@@ -340,6 +430,11 @@ export default {
subjectData,
addSubject,
searchNodes,
showLinkDrawer,
linkFormRef,
linkData,
linkSubject,
subjectOptions,
}
},
}
......
......@@ -34,10 +34,19 @@ function textWrap(text, width) {
text.each(function () {
const text = d3.select(this),
words = text.text().split('').reverse(),
lineHeight = 1, // ems
x = text.attr('x'),
y = text.attr('y'),
dy = 0
lineHeight = 1.2, // ems
dy = 0,
x = text.attr('x')
let y = text.attr('y')
if (words.length > 4 && words.length <= 8) {
y = +y - 4
} else if (words.length > 8 && words.length <= 10) {
y = +y - 8
} else if (words.length > 10) {
y = +y - 12
}
let word,
line = [],
......@@ -73,11 +82,11 @@ const defaultConfig = {
links: [], // 线数组
isHighLight: true, // 是否启动 鼠标 hover 到节点上高亮与节点有关的节点,其他无关节点透明的功能
isScale: true, // 是否启用缩放平移zoom功能
scaleExtent: [0.2, 1.5], // 缩放的比例尺
scaleExtent: [0.6, 1.5], // 缩放的比例尺
chargeStrength: -100, // 万有引力
collide: 80, // 碰撞力的大小 (节点之间的间距)
alphaDecay: 0.4, // 控制力学模拟衰减率
r: 34, // 圈圈的半径 [30 - 45]
r: 36, // 圈圈的半径 [30 - 45]
nodeColor: 'skyblue', // 圈圈节点背景颜色
fontColor: '#2c3e50', // 圈圈内文字的颜色
linkSrc: 30, // 划线时候的弧度
......@@ -191,8 +200,9 @@ export default class RelationGraph {
.attr('y', this.config.r) // edit
.attr('text-anchor', 'middle')
.attr('dominant-baseline', 'middle')
.attr('fill', this.config.fontColor)
.style('font-size', this.config.r / 3.8)
.attr('fill', '#000')
.style('font-size', 12)
.style('font-weight', 'normal')
.text((d) => d[d.nodeLabel.toLowerCase() + 'Name'])
}
......@@ -271,8 +281,7 @@ export default class RelationGraph {
.enter()
.append('g')
.attr('class', 'circle-wrapper')
// .merge(this.circlesWrapper)
this.circlesWrapper.exit().remove()
// 6.关系图添加用于显示圈圈的节点
this.circles = this.circlesWrapper
.append('circle')
......@@ -399,16 +408,25 @@ export default class RelationGraph {
this.initLinks()
this.initCircles()
const { x = this.config.width / 2, y = this.config.height / 2 } =
this.curActiveNode || {}
this.simulation
.force('link', d3.forceLink(this.config.links))
.nodes(this.config.nodes)
.force('link', d3.forceLink(this.config.links))
.force('charge', null)
.force('center', d3.forceCenter(x, y))
.alpha(1)
.restart()
const timer = setTimeout(() => {
this.simulation.force('link', null)
clearTimeout(timer)
}, 200)
}
openMenu(self, d, types) {
this.setCurNode(d)
this.curActiveNode = d
menu = new RadialMenu().radius(38).thickness(30).appendTo(self.parentNode)
if (!types) {
menu.show(this.menuData, d)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment