Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
R
relation-graph
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
郭铭瑶
relation-graph
Commits
6ddd03b6
Commit
6ddd03b6
authored
Aug 25, 2021
by
郭铭瑶
🤘
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
主体客体区分形状&编辑节点&添加标签
parent
a5189eeb
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
409 additions
and
80 deletions
+409
-80
api.js
src/ajax/api.js
+4
-2
edit.svg
src/assets/images/edit.svg
+1
-0
d3.vue
src/components/d3.vue
+42
-23
main.vue
src/components/main.vue
+220
-20
main.js
src/main.js
+2
-0
useD3.js
src/util/useD3.js
+140
-35
No files found.
src/ajax/api.js
View file @
6ddd03b6
...
...
@@ -8,14 +8,16 @@ switch (process.env.NODE_ENV) {
export
default
{
BASE_URL
,
GET_SUBJECTS
:
'/subjects/v2'
,
PUT_SUBJECT
:
'/subject/{id}'
,
GET_RELATIONS
:
'/relations'
,
POST_SUBJECT
:
'/subject'
,
POST_NODE
:
'/node/relation/v2'
,
DELETE_RELATION
:
'/node/relation/{id}'
,
GET_NODES
:
'/node/relations'
,
DELETE_NODE
:
'/node/{id}'
,
PUT_NODE
:
'/node/{nodeType}/{id}'
,
GET_SYSTEMS
:
'/systems'
,
POST_LINK_SUBJECTS
:
'/node/relations'
,
GET_TAGS
:
'/label/classification'
,
GET_TAG_CLASS
:
'/label/classification'
,
GET_TAGS
:
'/labels'
,
POST_TAGS
:
'/node/labels'
,
}
src/assets/images/edit.svg
0 → 100644
View file @
6ddd03b6
<?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=
"1629870391503"
class=
"icon"
viewBox=
"0 0 1024 1024"
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
p-id=
"2057"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
width=
"200"
height=
"200"
><defs><style
type=
"text/css"
></style></defs><path
d=
"M729.483636 995.607273H218.996364A127.301818 127.301818 0 0 1 91.810909 868.421818V233.658182A127.301818 127.301818 0 0 1 218.996364 106.472727h382.952727a29.090909 29.090909 0 1 1 0 58.181818H218.996364a69.003636 69.003636 0 0 0-69.003637 69.003637v634.763636a69.003636 69.003636 0 0 0 69.003637 69.003637h510.487272a69.003636 69.003636 0 0 0 69.003637-69.003637v-400.290909a29.090909 29.090909 0 0 1 58.181818 0v400.290909a127.301818 127.301818 0 0 1-127.185455 127.185455z"
fill=
"#ffffff"
p-id=
"2058"
></path><path
d=
"M514.792727 569.250909a29.090909 29.090909 0 0 1-28.974545-31.883636C488.727273 506.298182 500.363636 402.269091 529.105455 368.290909l254.836363-303.709091a99.607273 99.607273 0 1 1 152.552727 128l-254.836363 303.709091c-28.509091 33.978182-129.047273 63.767273-159.185455 72.029091a28.974545 28.974545 0 0 1-7.68 0.930909zM860.16 87.156364a41.309091 41.309091 0 0 0-31.650909 14.778181l-254.836364 303.709091c-8.494545 10.123636-18.036364 50.734545-24.552727 93.090909 41.192727-13.847273 79.476364-30.254545 87.970909-40.378181l254.836364-303.709091a41.309091 41.309091 0 0 0-31.650909-67.956364z"
fill=
"#ffffff"
p-id=
"2059"
></path></svg>
\ No newline at end of file
src/components/d3.vue
View file @
6ddd03b6
...
...
@@ -40,6 +40,7 @@ import branch from '@/assets/images/branch.svg'
import
link
from
'@/assets/images/link.svg'
import
add
from
'@/assets/images/add.svg'
import
del
from
'@/assets/images/delete.svg'
import
edit
from
'@/assets/images/edit.svg'
export
default
{
name
:
'D3'
,
props
:
{
...
...
@@ -54,7 +55,7 @@ export default {
}
,
}
,
}
,
emits
:
[
'link'
,
'add'
,
'del'
,
'branch'
,
'curNode'
,
'del-link'
],
emits
:
[
'link'
,
'add'
,
'del'
,
'
edit'
,
'
branch'
,
'curNode'
,
'del-link'
],
setup
(
props
,
ctx
)
{
const
colorList
=
{
default
:
'skyblue'
,
...
...
@@ -76,6 +77,12 @@ export default {
// action: (d) => ctx.emit('branch', d),
// title: '分支',
//
}
,
{
key
:
'edit'
,
icon
:
edit
,
action
:
(
d
)
=>
ctx
.
emit
(
'edit'
,
d
),
title
:
'编辑'
,
}
,
{
key
:
'link'
,
icon
:
link
,
...
...
@@ -96,27 +103,49 @@ export default {
}
,
]
const
curTagKey
=
ref
(
null
)
const
setCurNode
=
(
typ
e
)
=>
{
if
(
typ
e
.
nodeLabel
!==
'Subject'
)
{
const
setCurNode
=
(
nod
e
)
=>
{
if
(
nod
e
.
nodeLabel
!==
'Subject'
)
{
curTagKey
.
value
=
null
}
ctx
.
emit
(
'curNode'
,
typ
e
)
ctx
.
emit
(
'curNode'
,
nod
e
)
}
const
handleLinkClick
=
(
d
)
=>
{
if
(
d
.
target
.
nodeLabel
===
'System'
)
{
const
{
nodeLabel
}
=
d
.
target
if
(
nodeLabel
===
'System'
||
nodeLabel
===
'Subject'
)
{
ctx
.
emit
(
'del-link'
,
d
)
}
}
const
showBranch
=
(
d
)
=>
{
ctx
.
emit
(
'branch'
,
d
)
}
function
init
()
{
if
(
!
container
.
value
)
return
const
data
=
{
links
:
props
.
data
.
links
,
nodes
:
props
.
data
.
nodes
.
map
((
node
)
=>
{
const
data
=
transData
(
props
.
data
)
if
(
instance
)
{
updateGraph
(
props
.
data
)
}
else
{
instance
=
new
RelationGraph
(
container
.
value
,
data
,
props
.
config
,
menuData
,
colorList
,
setCurNode
,
handleLinkClick
,
showBranch
)
}
setLegend
(
data
)
}
function
transData
(
data
)
{
return
{
links
:
data
.
links
,
nodes
:
data
.
nodes
.
map
((
node
)
=>
{
let
key
=
node
.
nodeLabel
if
(
key
===
'Property'
)
{
const
relation
=
props
.
data
.
links
.
find
((
link
)
=>
{
...
...
@@ -134,21 +163,10 @@ export default {
return
node
}
),
}
if
(
instance
)
{
instance
.
update
(
data
)
}
else
{
instance
=
new
RelationGraph
(
container
.
value
,
data
,
props
.
config
,
menuData
,
colorList
,
setCurNode
,
handleLinkClick
,
showBranch
)
}
setLegend
(
data
)
}
function
updateGraph
(
data
)
{
instance
.
update
(
transData
(
data
))
}
function
setKey
(
key
)
{
...
...
@@ -269,6 +287,7 @@ export default {
colorList
,
container
,
setKey
,
updateGraph
,
nodeList
,
linkList
,
defaultColor
:
{
...
...
src/components/main.vue
View file @
6ddd03b6
...
...
@@ -9,6 +9,7 @@
@
add=
"openAddDrawer"
@
curNode=
"curNode = $event"
@
del=
"deleteNode"
@
edit=
"openEditDrawer"
@
link=
"openLinkDrawer"
@
del-link=
"deleteLink"
/>
...
...
@@ -50,7 +51,30 @@
:options=
"relationOptions"
/>
</n-form-item>
<n-form-item
label=
"所属系统"
path=
"systemId"
>
<template
v-if=
"getTagName(data.relationId) === '标签'"
>
<n-form-item
label=
"标签分类"
path=
"classification"
>
<n-select
v-model:value=
"data.classification"
placeholder=
"请选择"
:options=
"tagClassOptions"
/>
</n-form-item>
<n-form-item
label=
"标签名称"
path=
"tag"
>
<n-select
v-model:value=
"data.tag"
placeholder=
"请选择"
filterable
tag
:options=
"tagOptions"
/>
</n-form-item>
<n-form-item
path=
"isPositive"
:show-label=
"false"
>
<n-checkbox
v-model:checked=
"data.isPositive"
>
是否为积极的标签
</n-checkbox
>
</n-form-item>
</
template
>
<n-form-item
v-else
label=
"所属系统"
path=
"systemId"
>
<n-select
v-model:value=
"data.systemIds"
placeholder=
"请选择"
...
...
@@ -141,7 +165,7 @@
</n-drawer-content>
</n-drawer>
<n-drawer
v-model:show=
"showLinkDrawer"
:width=
"340"
placement=
"left"
>
<n-drawer-content
title=
"
连接
要素"
closable
>
<n-drawer-content
title=
"
关联
要素"
closable
>
<n-form
ref=
"linkFormRef"
:model=
"linkData"
:rules=
"rules"
size=
"small"
>
<n-form-item
path=
"sourceNodeId"
label=
"源要素"
>
<n-select
...
...
@@ -171,6 +195,50 @@
</n-form>
</n-drawer-content>
</n-drawer>
<n-drawer
v-model:show=
"showEditDrawer"
:width=
"340"
placement=
"left"
>
<n-drawer-content
title=
"编辑节点"
closable
>
<n-form
ref=
"editFormRef"
:model=
"editData"
:rules=
"rules"
size=
"small"
>
<
template
v-if=
"curNode.nodeLabel === 'Subject'"
>
<n-form-item
path=
"subjectName"
label=
"名称"
>
<n-input
v-model:value=
"editData.subjectName"
placeholder=
"请输入"
@
keydown
.
enter
.
prevent
/>
</n-form-item>
<n-form-item
path=
"subjectType"
label=
"类型"
>
<n-select
v-model:value=
"editData.subjectType"
placeholder=
"请选择"
:options=
"[
{ label: '主体', value: '1' },
{ label: '客体', value: '2' },
]"
/>
</n-form-item>
</
template
>
<
template
v-else-if=
"curNode.nodeLabel === 'Property'"
>
<n-form-item
label=
"节点名称"
path=
"propertyName"
>
<n-input
v-model:value=
"editData.propertyName"
placeholder=
"请输入"
@
keydown
.
enter
.
prevent
/>
</n-form-item>
</
template
>
<n-space
justify=
"end"
>
<n-button
:loading=
"isLoading"
size=
"small"
type=
"primary"
@
click=
"editNode"
>
提交
</n-button>
</n-space>
</n-form>
</n-drawer-content>
</n-drawer>
</template>
<
script
setup
>
...
...
@@ -219,13 +287,30 @@ function fetchSubjects() {
}
fetchSubjects
()
const
tagClassOptions
=
ref
([])
const
tagOptions
=
ref
([])
function
fetchTags
()
{
ajax
.
get
({
url
:
api
.
GET_TAG_CLASS
,
})
.
then
((
res
)
=>
{
const
data
=
res
.
data
.
content
tagClassOptions
.
value
=
data
.
map
((
e
)
=>
({
label
:
e
.
classification
,
value
:
e
.
classification
,
}))
})
ajax
.
get
({
url
:
api
.
GET_TAGS
,
})
.
then
((
res
)
=>
{
console
.
log
(
'tags'
,
res
.
data
.
content
)
const
data
=
(
res
.
data
&&
res
.
data
.
content
)
||
[]
tagOptions
.
value
=
data
.
map
((
e
)
=>
({
label
:
e
.
labelName
,
value
:
e
.
id
,
}))
})
}
fetchTags
()
...
...
@@ -302,31 +387,80 @@ function setLabelKey(key) {
d3Ref
.
value
.
setKey
(
key
)
}
function
getTagName
(
relationId
)
{
if
(
!
relationId
)
return
null
const
tag
=
relationOptions
.
value
.
find
((
e
)
=>
e
.
value
===
relationId
)
return
tag
&&
tag
.
label
}
function
submitNewNode
(
e
)
{
e
.
preventDefault
()
formRef
.
value
.
validate
((
errors
)
=>
{
formRef
.
value
.
validate
(
async
(
errors
)
=>
{
if
(
!
errors
)
{
isLoading
.
value
=
true
const
{
nodeId
,
subjectName
,
subjectType
}
=
curSubject
.
value
ajax
.
post
({
const
tagData
=
[]
const
otherData
=
[]
formData
.
value
.
forEach
((
item
)
=>
{
if
(
getTagName
(
item
.
relationId
)
===
'标签'
)
{
tagData
.
push
(
item
)
}
else
{
otherData
.
push
(
item
)
}
})
if
(
otherData
.
length
>
0
)
{
await
ajax
.
post
({
url
:
api
.
POST_NODE
,
params
:
{
subjectId
:
nodeId
,
subjectName
,
subjectType
,
propertyList
:
formData
.
value
,
propertyList
:
otherData
.
map
((
item
)
=>
({
propertyName
:
item
.
propertyName
,
systemIds
:
item
.
systemIds
,
relationId
:
item
.
relationId
,
})),
},
})
.
then
(()
=>
{
fetchSubordinates
({
nodeId
:
nodeId
,
nodeLabel
:
'Subject'
,
})
isLoading
.
value
=
false
showDrawer
.
value
=
false
message
.
success
(
'提交成功'
)
}
if
(
tagData
.
length
>
0
)
{
await
ajax
.
post
({
url
:
api
.
POST_TAGS
,
params
:
{
subjectId
:
nodeId
,
subjectName
,
subjectType
,
relationId
:
tagData
[
0
].
relationId
,
labelList
:
tagData
.
map
((
item
)
=>
{
let
obj
=
{
id
:
null
,
labelName
:
item
.
tag
,
}
if
(
tagOptions
.
value
.
findIndex
((
e
)
=>
e
.
value
==
item
.
tag
)
>=
0
)
{
obj
=
{
id
:
item
.
tag
,
labelName
:
null
,
}
}
return
{
classification
:
item
.
classification
,
isPositive
:
item
.
isPositive
,
...
obj
,
}
}),
},
})
}
fetchSubordinates
({
nodeId
,
nodeLabel
:
'Subject'
,
})
isLoading
.
value
=
false
showDrawer
.
value
=
false
message
.
success
(
'新增成功'
)
}
})
}
...
...
@@ -366,9 +500,12 @@ function deleteNode(data) {
function
deleteLink
(
data
)
{
const
{
source
,
target
}
=
data
const
name
=
`'
${
source
.
propertyName
||
target
.
subjectName
}
_
${
target
.
systemName
||
source
.
subjectName
}
'`
dialog
.
error
({
title
:
'删除关联'
,
content
:
`确定是否删除
'
${
source
.
propertyName
}
_
${
target
.
systemName
}
'
关联关系?`
,
content
:
`确定是否删除
${
name
}
关联关系?`
,
positiveText
:
'确定'
,
negativeText
:
'取消'
,
maskClosable
:
false
,
...
...
@@ -410,7 +547,7 @@ const addSubject = (e) => {
fetchSubjects
()
isLoading
.
value
=
false
showSubjectDrawer
.
value
=
false
message
.
success
(
'
提交
成功'
)
message
.
success
(
'
新增
成功'
)
})
}
})
...
...
@@ -467,7 +604,7 @@ const linkSubject = (e) => {
})
isLoading
.
value
=
false
showLinkDrawer
.
value
=
false
message
.
success
(
'
提交
成功'
)
message
.
success
(
'
关联
成功'
)
})
}
})
...
...
@@ -497,7 +634,21 @@ const rules = {
relationId
:
[
{
required
:
true
,
message
:
'请选择从属类型'
,
message
:
'请选择从属关系'
,
trigger
:
[
'change'
,
'blur'
],
},
],
classification
:
[
{
required
:
true
,
message
:
'请选择标签分类'
,
trigger
:
[
'change'
,
'blur'
],
},
],
tag
:
[
{
required
:
true
,
message
:
'请选择标签名称'
,
trigger
:
[
'change'
,
'blur'
],
},
],
...
...
@@ -553,7 +704,7 @@ function openSubjectDrawer() {
function
openLinkDrawer
()
{
showLinkDrawer
.
value
=
true
linkData
.
value
=
{
sourceNodeId
:
null
,
sourceNodeId
:
curSubject
.
value
.
nodeId
,
targetNodeId
:
null
,
}
}
...
...
@@ -567,6 +718,55 @@ function addNewItem() {
function
deleteItem
(
i
)
{
formData
.
value
.
splice
(
i
,
1
)
}
const
editData
=
ref
(
null
)
const
showEditDrawer
=
ref
(
false
)
const
editFormRef
=
ref
(
null
)
function
openEditDrawer
(
d
)
{
editData
.
value
=
d
showEditDrawer
.
value
=
true
}
function
editNode
(
e
)
{
e
.
preventDefault
()
editFormRef
.
value
.
validate
((
errors
)
=>
{
if
(
!
errors
)
{
isLoading
.
value
=
true
const
{
nodeLabel
,
nodeId
}
=
curNode
.
value
let
params
=
{}
if
(
nodeLabel
===
'Subject'
)
{
params
=
{
subjectName
:
editData
.
value
.
subjectName
,
subjectType
:
editData
.
value
.
subjectType
,
}
}
else
if
(
nodeLabel
===
'Property'
)
{
params
=
{
propertyName
:
editData
.
value
.
propertyName
,
}
}
ajax
.
put
({
url
:
api
.
PUT_NODE
.
replace
(
'{nodeType}'
,
nodeLabel
).
replace
(
'{id}'
,
nodeId
),
params
,
})
.
then
(()
=>
{
graphData
.
value
.
nodes
.
forEach
((
node
)
=>
{
if
(
node
.
nodeId
===
nodeId
)
{
for
(
const
key
in
params
)
{
node
[
key
]
=
params
[
key
]
}
}
})
d3Ref
.
value
.
updateGraph
(
graphData
.
value
)
isLoading
.
value
=
false
showEditDrawer
.
value
=
false
message
.
success
(
'编辑成功'
)
})
}
})
}
</
script
>
<
style
lang=
"stylus"
scoped
>
...
...
src/main.js
View file @
6ddd03b6
...
...
@@ -11,6 +11,7 @@ import {
NForm
,
NFormItem
,
NInput
,
NCheckbox
,
NInputGroup
,
NSelect
,
NMessageProvider
,
...
...
@@ -29,6 +30,7 @@ const naive = create({
NForm
,
NFormItem
,
NInput
,
NCheckbox
,
NInputGroup
,
NSelect
,
NMessageProvider
,
...
...
src/util/useD3.js
View file @
6ddd03b6
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment