Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
admin
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
9459a729
authored
Dec 09, 2024
by
GoldenZqqqq
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 流程模型新增/修改/设计合为一个页面基本切换tab逻辑校验与页面样式优化
parent
5063db47
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
179 additions
and
85 deletions
+179
-85
src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue
+46
-23
src/views/bpm/model/CategoryDraggableModel.vue
+1
-1
src/views/bpm/model/CreateUpdate.vue
+60
-26
src/views/bpm/model/editor/index.vue
+61
-31
src/views/bpm/simple/SimpleModelDesign.vue
+11
-4
No files found.
src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue
View file @
9459a729
...
@@ -38,12 +38,21 @@ import * as UserGroupApi from '@/api/bpm/userGroup'
...
@@ -38,12 +38,21 @@ import * as UserGroupApi from '@/api/bpm/userGroup'
defineOptions
({
defineOptions
({
name
:
'SimpleProcessDesigner'
name
:
'SimpleProcessDesigner'
})
})
const
emits
=
defineEmits
([
'success'
])
// 保存成功事件
const
emits
=
defineEmits
([
'success'
])
// 保存成功事件
const
props
=
defineProps
({
const
props
=
defineProps
({
modelId
:
{
modelId
:
{
type
:
String
,
type
:
String
,
required
:
true
required
:
false
},
modelKey
:
{
type
:
String
,
required
:
false
},
modelName
:
{
type
:
String
,
required
:
false
}
}
})
})
...
@@ -69,6 +78,7 @@ const message = useMessage() // 国际化
...
@@ -69,6 +78,7 @@ const message = useMessage() // 国际化
const
processNodeTree
=
ref
<
SimpleFlowNode
|
undefined
>
()
const
processNodeTree
=
ref
<
SimpleFlowNode
|
undefined
>
()
const
errorDialogVisible
=
ref
(
false
)
const
errorDialogVisible
=
ref
(
false
)
let
errorNodes
:
SimpleFlowNode
[]
=
[]
let
errorNodes
:
SimpleFlowNode
[]
=
[]
const
saveSimpleFlowModel
=
async
(
simpleModelNode
:
SimpleFlowNode
)
=>
{
const
saveSimpleFlowModel
=
async
(
simpleModelNode
:
SimpleFlowNode
)
=>
{
if
(
!
simpleModelNode
)
{
if
(
!
simpleModelNode
)
{
message
.
error
(
'模型数据为空'
)
message
.
error
(
'模型数据为空'
)
...
@@ -76,21 +86,28 @@ const saveSimpleFlowModel = async (simpleModelNode: SimpleFlowNode) => {
...
@@ -76,21 +86,28 @@ const saveSimpleFlowModel = async (simpleModelNode: SimpleFlowNode) => {
}
}
try
{
try
{
loading
.
value
=
true
loading
.
value
=
true
const
data
=
{
if
(
props
.
modelId
)
{
id
:
props
.
modelId
,
// 编辑模式
simpleModel
:
simpleModelNode
const
data
=
{
}
id
:
props
.
modelId
,
const
result
=
await
updateBpmSimpleModel
(
data
)
simpleModel
:
simpleModelNode
if
(
result
)
{
}
message
.
success
(
'修改成功'
)
const
result
=
await
updateBpmSimpleModel
(
data
)
emits
(
'success'
)
if
(
result
)
{
message
.
success
(
'修改成功'
)
emits
(
'success'
)
}
else
{
message
.
alert
(
'修改失败'
)
}
}
else
{
}
else
{
message
.
alert
(
'修改失败'
)
// 新建模式,直接返回数据
emits
(
'success'
,
simpleModelNode
)
}
}
}
finally
{
}
finally
{
loading
.
value
=
false
loading
.
value
=
false
}
}
}
}
// 校验节点设置。 暂时以 showText 为空 未节点错误配置
// 校验节点设置。 暂时以 showText 为空 未节点错误配置
const
validateNode
=
(
node
:
SimpleFlowNode
|
undefined
,
errorNodes
:
SimpleFlowNode
[])
=>
{
const
validateNode
=
(
node
:
SimpleFlowNode
|
undefined
,
errorNodes
:
SimpleFlowNode
[])
=>
{
if
(
node
)
{
if
(
node
)
{
...
@@ -134,12 +151,14 @@ onMounted(async () => {
...
@@ -134,12 +151,14 @@ onMounted(async () => {
try
{
try
{
loading
.
value
=
true
loading
.
value
=
true
// 获取表单字段
// 获取表单字段
const
bpmnModel
=
await
getModel
(
props
.
modelId
)
if
(
props
.
modelId
)
{
if
(
bpmnModel
)
{
const
bpmnModel
=
await
getModel
(
props
.
modelId
)
formType
.
value
=
bpmnModel
.
formType
if
(
bpmnModel
)
{
if
(
formType
.
value
===
10
)
{
formType
.
value
=
bpmnModel
.
formType
const
bpmnForm
=
(
await
getForm
(
bpmnModel
.
formId
))
as
unknown
as
FormVO
if
(
formType
.
value
===
10
)
{
formFields
.
value
=
bpmnForm
?.
fields
const
bpmnForm
=
(
await
getForm
(
bpmnModel
.
formId
))
as
unknown
as
FormVO
formFields
.
value
=
bpmnForm
?.
fields
}
}
}
}
}
// 获得角色列表
// 获得角色列表
...
@@ -155,14 +174,18 @@ onMounted(async () => {
...
@@ -155,14 +174,18 @@ onMounted(async () => {
// 获取用户组列表
// 获取用户组列表
userGroupOptions
.
value
=
await
UserGroupApi
.
getUserGroupSimpleList
()
userGroupOptions
.
value
=
await
UserGroupApi
.
getUserGroupSimpleList
()
//获取 SIMPLE 设计器模型
if
(
props
.
modelId
)
{
const
result
=
await
getBpmSimpleModel
(
props
.
modelId
)
//获取 SIMPLE 设计器模型
if
(
result
)
{
const
result
=
await
getBpmSimpleModel
(
props
.
modelId
)
processNodeTree
.
value
=
result
if
(
result
)
{
}
else
{
processNodeTree
.
value
=
result
// 初始值
}
}
// 如果没有现有模型,创建初始模型
if
(
!
processNodeTree
.
value
)
{
processNodeTree
.
value
=
{
processNodeTree
.
value
=
{
name
:
'发起人'
,
name
:
props
.
modelName
||
'发起人'
,
type
:
NodeType
.
START_USER_NODE
,
type
:
NodeType
.
START_USER_NODE
,
id
:
NodeId
.
START_USER_NODE_ID
,
id
:
NodeId
.
START_USER_NODE_ID
,
childNode
:
{
childNode
:
{
...
...
src/views/bpm/model/CategoryDraggableModel.vue
View file @
9459a729
...
@@ -249,7 +249,7 @@ import { formatDate } from '@/utils/formatTime'
...
@@ -249,7 +249,7 @@ import { formatDate } from '@/utils/formatTime'
import
*
as
ModelApi
from
'@/api/bpm/model'
import
*
as
ModelApi
from
'@/api/bpm/model'
import
*
as
FormApi
from
'@/api/bpm/form'
import
*
as
FormApi
from
'@/api/bpm/form'
import
{
setConfAndFields2
}
from
'@/utils/formCreate'
import
{
setConfAndFields2
}
from
'@/utils/formCreate'
import
{
BpmModelFormType
,
BpmModelType
}
from
'@/utils/constants'
import
{
BpmModelFormType
}
from
'@/utils/constants'
import
{
checkPermi
}
from
'@/utils/permission'
import
{
checkPermi
}
from
'@/utils/permission'
import
{
useUserStoreWithOut
}
from
'@/store/modules/user'
import
{
useUserStoreWithOut
}
from
'@/store/modules/user'
import
{
useAppStore
}
from
'@/store/modules/app'
import
{
useAppStore
}
from
'@/store/modules/app'
...
...
src/views/bpm/model/CreateUpdate.vue
View file @
9459a729
<
template
>
<
template
>
<!-- 头部导航栏 -->
<!-- 头部导航栏 -->
<div
<div
class=
"absolute top-0 left-0 right-0 h-50px bg-white border-bottom z-10 flex items-center
justify-between
px-20px"
class=
"absolute top-0 left-0 right-0 h-50px bg-white border-bottom z-10 flex items-center px-20px"
>
>
<div
class=
"flex items-center"
>
<!-- 左侧标题,固定宽度 -->
<Icon
icon=
"ep:arrow-left"
class=
"cursor-pointer"
@
click=
"router.back()"
/>
<div
class=
"w-200px flex items-center overflow-hidden"
>
<span
class=
"ml-10px text-16px"
>
{{
formData
.
name
||
'创建流程'
}}
</span>
<Icon
icon=
"ep:arrow-left"
class=
"cursor-pointer flex-shrink-0"
@
click=
"router.back()"
/>
<span
class=
"ml-10px text-16px truncate"
:title=
"formData.name || '创建流程'"
>
{{
formData
.
name
||
'创建流程'
}}
</span>
</div>
</div>
<!-- 步骤条 -->
<!-- 步骤条
,固定在中间
-->
<div
class=
"flex-1 flex items-center justify-center h-full"
>
<div
class=
"flex-1 flex items-center justify-center h-full"
>
<div
<div
class=
"w-400px flex items-center justify-between h-full"
>
v-for=
"(step, index) in steps"
:key=
"index"
class=
"flex items-center cursor-pointer mx-15px relative h-full"
:class=
"[
currentStep === index
? 'text-[#3473ff] border-[#3473ff] border-b-2 border-b-solid'
: 'text-gray-500'
]"
@
click=
"currentStep = index"
>
<div
<div
class=
"w-28px h-28px rounded-full flex items-center justify-center mr-8px border-2 border-solid text-15px"
v-for=
"(step, index) in steps"
:key=
"index"
class=
"flex items-center cursor-pointer mx-15px relative h-full"
:class=
"[
:class=
"[
currentStep === index
currentStep === index
? '
bg-[#3473ff] text-white
'
? '
text-[#3473ff] border-[#3473ff] border-b-2 border-b-solid
'
: '
border-gray-300 bg-white
text-gray-500'
: 'text-gray-500'
]"
]"
@
click=
"handleStepClick(index)"
>
>
{{
index
+
1
}}
<div
class=
"w-28px h-28px rounded-full flex items-center justify-center mr-8px border-2 border-solid text-15px"
:class=
"[
currentStep === index
? 'bg-[#3473ff] text-white border-[#3473ff]'
: 'border-gray-300 bg-white text-gray-500'
]"
>
{{
index
+
1
}}
</div>
<span
class=
"text-16px font-bold whitespace-nowrap"
>
{{
step
.
title
}}
</span>
</div>
</div>
<span
class=
"text-16px font-bold"
>
{{
step
.
title
}}
</span>
</div>
</div>
</div>
</div>
<!--
操作按钮
-->
<!--
右侧按钮,固定宽度
-->
<div
class=
"
flex items-center gap-1
"
>
<div
class=
"
w-200px flex items-center justify-end gap-2
"
>
<el-button
@
click=
"handleSave"
>
保 存
</el-button>
<el-button
@
click=
"handleSave"
>
保 存
</el-button>
<el-button
type=
"primary"
@
click=
"handleDeploy"
>
发 布
</el-button>
<el-button
type=
"primary"
@
click=
"handleDeploy"
>
发 布
</el-button>
</div>
</div>
...
@@ -264,15 +269,26 @@
...
@@ -264,15 +269,26 @@
</el-form>
</el-form>
</div>
</div>
<!-- 第三步:流程设计 -->
<div
v-show=
"currentStep === 2"
>
<div
v-show=
"currentStep === 2"
>
<!-- BPMN设计器 -->
<!-- BPMN设计器 -->
<template
v-if=
"formData.type === BpmModelType.BPMN"
>
<template
v-if=
"formData.type === BpmModelType.BPMN"
>
<BpmModelEditor
:model-id=
"formData.id"
@
success=
"handleDesignSuccess"
/>
<BpmModelEditor
:model-id=
"formData.id"
:model-key=
"formData.key"
:model-name=
"formData.name"
@
success=
"handleDesignSuccess"
/>
</
template
>
</
template
>
<!-- Simple设计器 -->
<!-- Simple设计器 -->
<
template
v-else
>
<
template
v-else
>
<SimpleModelDesign
:model-id=
"formData.id"
@
success=
"handleDesignSuccess"
/>
<SimpleModelDesign
:model-id=
"formData.id"
:model-key=
"formData.key"
:model-name=
"formData.name"
@
success=
"handleDesignSuccess"
/>
</
template
>
</
template
>
</div>
</div>
</ContentWrap>
</ContentWrap>
...
@@ -520,9 +536,27 @@ const steps = [
...
@@ -520,9 +536,27 @@ const steps = [
]
]
// 处理设计器保存成功
// 处理设计器保存成功
const
handleDesignSuccess
=
()
=>
{
const
handleDesignSuccess
=
(
bpmnXml
?:
string
)
=>
{
if
(
bpmnXml
)
{
// 新建时,保存设计器生成的XML
formData
.
value
.
bpmnXml
=
bpmnXml
}
message
.
success
(
'保存成功'
)
message
.
success
(
'保存成功'
)
}
}
// 步骤切换处理
const
handleStepClick
=
async
(
index
:
number
)
=>
{
// 如果是切换到第三步(流程设计),需要校验key和name
if
(
index
===
2
&&
!
formData
.
value
.
id
)
{
// 新增时才校验
if
(
!
formData
.
value
.
key
||
!
formData
.
value
.
name
)
{
message
.
warning
(
'请先填写流程标识和流程名称'
)
return
}
}
currentStep
.
value
=
index
}
</
script
>
</
script
>
<
style
lang=
"scss"
scoped
>
<
style
lang=
"scss"
scoped
>
...
...
src/views/bpm/model/editor/index.vue
View file @
9459a729
...
@@ -11,6 +11,7 @@
...
@@ -11,6 +11,7 @@
ref=
"processDesigner"
ref=
"processDesigner"
@
init-finished=
"initModeler"
@
init-finished=
"initModeler"
:additionalModel=
"controlForm.additionalModel"
:additionalModel=
"controlForm.additionalModel"
:model=
"model"
@
save=
"save"
@
save=
"save"
/>
/>
<!-- 流程属性器,负责编辑每个流程节点的属性 -->
<!-- 流程属性器,负责编辑每个流程节点的属性 -->
...
@@ -35,14 +36,15 @@ import * as ModelApi from '@/api/bpm/model'
...
@@ -35,14 +36,15 @@ import * as ModelApi from '@/api/bpm/model'
defineOptions
({
name
:
'BpmModelEditor'
})
defineOptions
({
name
:
'BpmModelEditor'
})
const
props
=
defineProps
<
{
const
props
=
defineProps
<
{
modelId
:
string
modelId
?:
string
modelKey
?:
string
modelName
?:
string
}
>
()
}
>
()
const
emit
=
defineEmits
([
'success'
])
const
emit
=
defineEmits
([
'success'
])
const
router
=
useRouter
()
// 路由
const
{
query
}
=
useRoute
()
// 路由的查询
const
message
=
useMessage
()
// 国际化
const
message
=
useMessage
()
// 国际化
const
xmlString
=
ref
(
undefined
)
// BPMN XML
const
xmlString
=
ref
<
string
>
(
)
// BPMN XML
const
modeler
=
ref
(
null
)
// BPMN Modeler
const
modeler
=
ref
(
null
)
// BPMN Modeler
const
controlForm
=
ref
({
const
controlForm
=
ref
({
simulation
:
true
,
simulation
:
true
,
...
@@ -61,16 +63,32 @@ const initModeler = (item) => {
...
@@ -61,16 +63,32 @@ const initModeler = (item) => {
},
10
)
},
10
)
}
}
/** 获取默认的BPMN XML */
const
getDefaultBpmnXml
=
(
key
:
string
,
name
:
string
)
=>
{
return
`<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.activiti.org/processdef">
<process id="
${
key
}
" name="
${
name
}
" isExecutable="true" />
<bpmndi:BPMNDiagram id="BPMNDiagram">
<bpmndi:BPMNPlane id="
${
key
}
_di" bpmnElement="
${
key
}
" />
</bpmndi:BPMNDiagram>
</definitions>`
}
/** 添加/修改模型 */
/** 添加/修改模型 */
const
save
=
async
(
bpmnXml
:
string
)
=>
{
const
save
=
async
(
bpmnXml
:
string
)
=>
{
try
{
try
{
const
data
=
{
if
(
props
.
modelId
)
{
...
model
.
value
,
// 编辑模式
bpmnXml
:
bpmnXml
const
data
=
{
}
as
unknown
as
ModelApi
.
ModelVO
...
model
.
value
,
// 提交
bpmnXml
:
bpmnXml
await
ModelApi
.
updateModelBpmn
(
data
)
}
as
unknown
as
ModelApi
.
ModelVO
emit
(
'success'
)
await
ModelApi
.
updateModelBpmn
(
data
)
emit
(
'success'
)
}
else
{
// 新建模式,直接返回XML
emit
(
'success'
,
bpmnXml
)
}
}
catch
(
error
)
{
}
catch
(
error
)
{
console
.
error
(
'保存失败:'
,
error
)
console
.
error
(
'保存失败:'
,
error
)
message
.
error
(
'保存失败'
)
message
.
error
(
'保存失败'
)
...
@@ -79,28 +97,40 @@ const save = async (bpmnXml: string) => {
...
@@ -79,28 +97,40 @@ const save = async (bpmnXml: string) => {
/** 初始化 */
/** 初始化 */
onMounted
(
async
()
=>
{
onMounted
(
async
()
=>
{
if
(
!
props
.
modelId
)
{
if
(
props
.
modelId
)
{
message
.
error
(
'缺少模型 modelId 编号'
)
// 编辑模式
return
try
{
// 查询模型
const
data
=
await
ModelApi
.
getModel
(
props
.
modelId
)
model
.
value
=
{
...
data
,
bpmnXml
:
undefined
// 清空 bpmnXml 属性
}
xmlString
.
value
=
data
.
bpmnXml
||
getDefaultBpmnXml
(
data
.
key
,
data
.
name
)
}
catch
(
error
)
{
console
.
error
(
'获取模型失败:'
,
error
)
message
.
error
(
'获取模型失败'
)
}
}
else
if
(
props
.
modelKey
&&
props
.
modelName
)
{
// 新建模式,使用传入的key和name创建默认XML
xmlString
.
value
=
getDefaultBpmnXml
(
props
.
modelKey
,
props
.
modelName
)
model
.
value
=
{
key
:
props
.
modelKey
,
name
:
props
.
modelName
}
as
ModelApi
.
ModelVO
}
}
// 查询模型
const
data
=
await
ModelApi
.
getModel
(
String
(
props
.
modelId
))
if
(
!
data
.
bpmnXml
)
{
// 首次创建的 Model 模型,它是没有 bpmnXml,此时需要给它一个默认的
data
.
bpmnXml
=
` <?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.activiti.org/processdef">
<process id="
${
data
.
key
}
" name="
${
data
.
name
}
" isExecutable="true" />
<bpmndi:BPMNDiagram id="BPMNDiagram">
<bpmndi:BPMNPlane id="
${
data
.
key
}
_di" bpmnElement="
${
data
.
key
}
" />
</bpmndi:BPMNDiagram>
</definitions>`
}
model
.
value
=
{
...
data
,
bpmnXml
:
undefined
// 清空 bpmnXml 属性
}
xmlString
.
value
=
data
.
bpmnXml
})
})
// 监听key和name的变化
watch
([()
=>
props
.
modelKey
,
()
=>
props
.
modelName
],
([
newKey
,
newName
])
=>
{
if
(
!
props
.
modelId
&&
newKey
&&
newName
)
{
xmlString
.
value
=
getDefaultBpmnXml
(
newKey
,
newName
)
model
.
value
=
{
key
:
newKey
,
name
:
newName
}
as
ModelApi
.
ModelVO
}
},
{
immediate
:
true
})
</
script
>
</
script
>
<
style
lang=
"scss"
>
<
style
lang=
"scss"
>
.process-panel__container
{
.process-panel__container
{
...
...
src/views/bpm/simple/SimpleModelDesign.vue
View file @
9459a729
<
template
>
<
template
>
<ContentWrap
:bodyStyle=
"
{ padding: '20px 16px' }">
<ContentWrap
:bodyStyle=
"
{ padding: '20px 16px' }">
<SimpleProcessDesigner
:model-id=
"modelId"
@
success=
"handleSuccess"
/>
<SimpleProcessDesigner
:model-id=
"modelId"
:model-key=
"modelKey"
:model-name=
"modelName"
@
success=
"handleSuccess"
/>
</ContentWrap>
</ContentWrap>
</
template
>
</
template
>
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
...
@@ -11,14 +16,16 @@ defineOptions({
...
@@ -11,14 +16,16 @@ defineOptions({
})
})
defineProps
<
{
defineProps
<
{
modelId
:
string
modelId
?:
string
modelKey
?:
string
modelName
?:
string
}
>
()
}
>
()
const
emit
=
defineEmits
([
'success'
])
const
emit
=
defineEmits
([
'success'
])
// 修改成功回调
// 修改成功回调
const
handleSuccess
=
()
=>
{
const
handleSuccess
=
(
data
?:
any
)
=>
{
emit
(
'success'
)
emit
(
'success'
,
data
)
}
}
</
script
>
</
script
>
<
style
lang=
"scss"
scoped
></
style
>
<
style
lang=
"scss"
scoped
></
style
>
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