Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
Z
zrch-risk-39
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
Administrator
zrch-risk-39
Commits
5a8e52f3
提交
5a8e52f3
authored
4月 09, 2026
作者:
liuluyu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
计划管理流转记录更新
上级
ae0a6c59
显示空白字符变更
内嵌
并排
正在显示
8 个修改的文件
包含
875 行增加
和
864 行删除
+875
-864
ShowFormModal.vue
...t-39/src/views/flowable/task/components/ShowFormModal.vue
+358
-279
Detail.vue
...39/src/views/flowable/task/finished/components/Detail.vue
+116
-159
Detail.vue
...9/src/views/flowable/task/myProcess/components/Detail.vue
+149
-169
TodoIndex.vue
...-39/src/views/flowable/task/todo/components/TodoIndex.vue
+9
-13
index.vue
zrch-risk-client-39/src/views/flowable/task/todo/index.vue
+136
-151
StPlanManList.vue
zrch-risk-client-39/src/views/project/plan/StPlanManList.vue
+9
-33
StPlanExcuteForm.vue
...39/src/views/project/plan/components/StPlanExcuteForm.vue
+24
-5
StPlanManForm.vue
...nt-39/src/views/project/plan/components/StPlanManForm.vue
+74
-55
没有找到文件。
zrch-risk-client-39/src/views/flowable/task/components/ShowFormModal.vue
浏览文件 @
5a8e52f3
<
template
>
<a-drawer
:title=
"drawerTitle"
:visible=
"visible"
:visible=
"visible
Ref
"
:width=
"drawerWidth"
:closable=
"true"
:mask-closable=
"maskClosable"
...
...
@@ -11,11 +11,7 @@
<!-- 选项卡模式 -->
<a-tabs
v-model:activeKey=
"activeTabKey"
type=
"card"
class=
"form-tabs"
>
<!-- 只读选项卡:索引小于 currentNodeIndex 的节点 -->
<a-tab-pane
v-for=
"node in readonlyNodes"
:key=
"node.id"
:tab=
"node.name"
>
<a-tab-pane
v-for=
"node in readonlyNodes"
:key=
"node.id"
:tab=
"node.name"
>
<template
#
tab
>
<span>
{{
node
.
name
}}
...
...
@@ -34,11 +30,7 @@
</a-tab-pane>
<!-- 可编辑选项卡:索引等于 currentNodeIndex 的节点 -->
<a-tab-pane
v-if=
"editableNode"
:key=
"editableNode.id"
:tab=
"editableNode.name"
>
<a-tab-pane
v-if=
"editableNode"
:key=
"editableNode.id"
:tab=
"editableNode.name"
>
<
template
#
tab
>
<span>
{{
editableNode
.
name
}}
...
...
@@ -64,321 +56,381 @@
<a-empty
description=
"未找到有效表单节点"
/>
</div>
<
template
#
footer
>
<
!-- <
template #footer>
<div class="drawer-footer">
<a-button
@
click=
"handleClose"
>
取消
</a-button>
<a-button
type=
"primary"
:loading=
"submitLoading"
@
click=
"handleSubmit"
>
提交
</a-button>
<a-button @click="handleClose">取消123</a-button>
<a-button type="primary" :loading="submitLoading" @click="handleSubmit"> 提交 </a-button>
</div>
</
template
>
</template>
-->
</a-drawer>
</template>
<
script
lang=
"ts"
setup
>
import
{
ref
,
computed
,
onMounted
,
defineAsyncComponent
,
h
,
watch
,
ComponentPublicInstance
}
from
'vue'
import
{
message
}
from
'ant-design-vue'
interface
WorkflowNode
{
id
:
string
name
:
string
formUrl
?:
string
formListUrl
?:
string
procDefId
?:
string
[
key
:
string
]:
any
}
// 表单组件实例类型
interface
FormComponentInstance
extends
ComponentPublicInstance
{
validate
?:
()
=>
Promise
<
any
>
getFormData
?:
()
=>
any
submitForm
?:
()
=>
Promise
<
any
>
// 添加 submitForm 方法类型
formData
?:
any
[
key
:
string
]:
any
}
const
props
=
defineProps
({
import
{
ref
,
computed
,
onMounted
,
defineAsyncComponent
,
h
,
watch
,
ComponentPublicInstance
,
getCurrentInstance
}
from
'vue'
;
import
{
message
}
from
'ant-design-vue'
;
import
{
useModalInner
}
from
'/@/components/Modal'
;
interface
WorkflowNode
{
id
:
string
;
name
:
string
;
formUrl
?:
string
;
formListUrl
?:
string
;
procDefId
?:
string
;
[
key
:
string
]:
any
;
}
// 表单组件实例类型
interface
FormComponentInstance
extends
ComponentPublicInstance
{
validate
?:
()
=>
Promise
<
any
>
;
getFormData
?:
()
=>
any
;
submitForm
?:
()
=>
Promise
<
any
>
;
// 添加 submitForm 方法类型
formData
?:
any
;
[
key
:
string
]:
any
;
}
const
props
=
defineProps
({
visible
:
{
type
:
Boolean
,
default
:
false
default
:
false
,
},
title
:
{
type
:
String
,
default
:
'表单处理'
default
:
'表单处理'
,
},
width
:
{
type
:
[
Number
,
String
],
default
:
720
default
:
900
,
},
maskClosable
:
{
type
:
Boolean
,
default
:
false
default
:
false
,
},
// 当前节点索引(从0开始),这个索引对应的节点是可编辑的
currentNodeIndex
:
{
type
:
Number
,
required
:
true
,
default
:
2
default
:
2
,
},
workflowNodes
:
{
type
:
Array
as
()
=>
WorkflowNode
[],
required
:
true
,
default
:
()
=>
[]
default
:
()
=>
[],
},
externalFormData
:
{
type
:
Object
as
()
=>
Record
<
string
,
any
>
,
default
:
()
=>
({})
default
:
()
=>
({}),
},
procDefId
:
{
type
:
String
,
default
:
''
}
})
const
emit
=
defineEmits
([
'update:visible'
,
'submit'
,
'close'
,
'form-data-update'
])
// 组件缓存
const
componentCache
=
new
Map
()
const
modules
=
import
.
meta
.
glob
(
'@/views/**/*.vue'
)
// 状态
const
loading
=
ref
(
false
)
const
submitLoading
=
ref
(
false
)
// 使用数组来存储表单组件实例
const
editableFormRefs
=
ref
<
FormComponentInstance
[]
>
([])
const
currentFormData
=
ref
<
any
>
({})
const
formDataMap
=
ref
<
Record
<
string
,
any
>>
({})
const
activeTabKey
=
ref
<
string
>
(
''
)
// 计算属性
const
drawerTitle
=
computed
(()
=>
props
.
title
)
const
drawerWidth
=
computed
(()
=>
props
.
width
)
// 只读节点:索引小于 currentNodeIndex 的节点
const
readonlyNodes
=
computed
(()
=>
{
if
(
!
props
.
workflowNodes
||
props
.
workflowNodes
.
length
===
0
)
{
return
[]
}
const
idx
=
props
.
currentNodeIndex
console
.
log
(
'只读节点 - 当前索引:'
,
idx
)
console
.
log
(
'只读节点 - 所有节点:'
,
props
.
workflowNodes
.
map
((
n
,
i
)
=>
`
${
i
}
:
${
n
.
name
}
`
))
if
(
idx
<=
0
)
return
[]
const
nodes
=
props
.
workflowNodes
.
slice
(
0
,
idx
)
console
.
log
(
'只读节点:'
,
nodes
.
map
(
n
=>
n
.
name
))
return
nodes
})
// 可编辑节点:索引等于 currentNodeIndex 的节点
const
editableNode
=
computed
(()
=>
{
if
(
!
props
.
workflowNodes
||
props
.
workflowNodes
.
length
===
0
)
{
return
null
}
const
idx
=
props
.
currentNodeIndex
if
(
idx
<
0
||
idx
>=
props
.
workflowNodes
.
length
)
{
console
.
warn
(
'可编辑节点索引无效:'
,
idx
)
return
null
}
const
node
=
props
.
workflowNodes
[
idx
]
console
.
log
(
'可编辑节点:'
,
node
?.
name
,
'索引:'
,
idx
)
return
node
})
// 设置表单组件 ref 的方法
function
setEditableFormRef
(
el
:
any
)
{
default
:
''
,
},
});
const
emit
=
defineEmits
([
'update:visible'
,
'submit'
,
'close'
,
'form-data-update'
,
'register'
]);
// expose minimal modal methods so useModal can register this drawer
const
instance
=
getCurrentInstance
();
const
modalMethods
=
{
setModalProps
:
(
props
:
Record
<
string
,
any
>
)
=>
{
if
(
Reflect
.
has
(
props
,
'open'
))
{
visibleRef
.
value
=
!!
props
.
open
;
emit
(
'update:visible'
,
!!
props
.
open
);
}
if
(
Reflect
.
has
(
props
,
'visible'
))
{
visibleRef
.
value
=
!!
props
.
visible
;
emit
(
'update:visible'
,
!!
props
.
visible
);
}
if
(
Reflect
.
has
(
props
,
'loading'
))
{
submitLoading
.
value
=
!!
props
.
loading
;
}
},
// allow parent to read current form data programmatically
getFormData
:
async
()
=>
{
try
{
const
data
=
await
getFormDataFromComponent
();
return
data
;
}
catch
(
e
)
{
console
.
error
(
'getFormData error:'
,
e
);
return
null
;
}
},
// will be set by useModal.register
emitVisible
:
undefined
,
redoModalHeight
:
()
=>
{},
};
// internal editable inputs provided via openModal data
const
innerWorkflowNodes
=
ref
<
any
[]
>
(
props
.
workflowNodes
||
[]);
const
innerCurrentNodeIndex
=
ref
<
number
>
(
props
.
currentNodeIndex
||
0
);
const
innerExternalFormData
=
ref
<
Record
<
string
,
any
>>
(
props
.
externalFormData
||
{});
const
innerTitle
=
ref
<
string
>
(
props
.
title
||
'表单处理'
);
const
innerProcDefId
=
ref
<
string
>
(
props
.
procDefId
||
''
);
// useModalInner receives data written by useModal.openModal
const
[
registerInner
,
{
setModalProps
:
innerSetModalProps
}]
=
useModalInner
(
async
(
data
:
any
)
=>
{
if
(
!
data
)
return
;
if
(
data
.
workflowNodes
)
innerWorkflowNodes
.
value
=
data
.
workflowNodes
;
if
(
data
.
currentNodeIndex
!==
undefined
)
innerCurrentNodeIndex
.
value
=
Number
(
data
.
currentNodeIndex
);
if
(
data
.
externalFormData
)
innerExternalFormData
.
value
=
data
.
externalFormData
;
if
(
data
.
procDefId
)
innerProcDefId
.
value
=
data
.
procDefId
;
if
(
data
.
title
)
innerTitle
.
value
=
data
.
title
;
// ensure drawer opens
visibleRef
.
value
=
true
;
// reset form data for new nodes/data
resetFormData
();
preloadComponents
();
});
// 组件缓存
const
componentCache
=
new
Map
();
const
modules
=
import
.
meta
.
glob
(
'@/views/**/*.vue'
);
// 状态
const
loading
=
ref
(
false
);
const
submitLoading
=
ref
(
false
);
// internal visible state so parent doesn't need v-model binding
const
visibleRef
=
ref
(
false
);
// 使用数组来存储表单组件实例
const
editableFormRefs
=
ref
<
FormComponentInstance
[]
>
([]);
const
currentFormData
=
ref
<
any
>
({});
const
formDataMap
=
ref
<
Record
<
string
,
any
>>
({});
const
activeTabKey
=
ref
<
string
>
(
''
);
// 计算属性
const
drawerTitle
=
computed
(()
=>
innerTitle
.
value
||
props
.
title
);
const
drawerWidth
=
computed
(()
=>
props
.
width
);
// 只读节点:索引小于 currentNodeIndex 的节点
const
readonlyNodes
=
computed
(()
=>
{
if
(
!
innerWorkflowNodes
.
value
||
innerWorkflowNodes
.
value
.
length
===
0
)
{
return
[];
}
const
idx
=
innerCurrentNodeIndex
.
value
;
console
.
log
(
'只读节点 - 当前索引:'
,
idx
);
console
.
log
(
'只读节点 - 所有节点:'
,
innerWorkflowNodes
.
value
.
map
((
n
,
i
)
=>
`
${
i
}
:
${
n
.
name
}
`
)
);
if
(
idx
<=
0
)
return
[];
const
nodes
=
innerWorkflowNodes
.
value
.
slice
(
0
,
idx
);
console
.
log
(
'只读节点:'
,
nodes
.
map
((
n
:
any
)
=>
n
.
name
)
);
return
nodes
;
});
// 可编辑节点:索引等于 currentNodeIndex 的节点
const
editableNode
=
computed
(()
=>
{
if
(
!
innerWorkflowNodes
.
value
||
innerWorkflowNodes
.
value
.
length
===
0
)
{
return
null
;
}
const
idx
=
innerCurrentNodeIndex
.
value
;
if
(
idx
<
0
||
idx
>=
innerWorkflowNodes
.
value
.
length
)
{
console
.
warn
(
'可编辑节点索引无效:'
,
idx
);
return
null
;
}
const
node
=
innerWorkflowNodes
.
value
[
idx
];
console
.
log
(
'可编辑节点:'
,
node
?.
name
,
'索引:'
,
idx
);
return
node
;
});
// 设置表单组件 ref 的方法
function
setEditableFormRef
(
el
:
any
)
{
if
(
el
)
{
// 清除旧的引用,只保留当前激活的可编辑表单
editableFormRefs
.
value
=
[
el
]
console
.
log
(
'表单组件已挂载,组件方法:'
,
Object
.
keys
(
el
))
console
.
log
(
'是否有 submitForm 方法:'
,
typeof
el
.
submitForm
===
'function'
)
}
}
// 获取当前可编辑的表单组件实例
function
getCurrentEditableForm
():
FormComponentInstance
|
null
{
return
editableFormRefs
.
value
[
0
]
||
null
}
// 获取表单数据
function
getFormData
(
nodeId
:
string
):
any
{
const
data
=
formDataMap
.
value
[
nodeId
]
||
{}
console
.
log
(
'获取表单数据 - 节点:'
,
nodeId
,
'数据:'
,
data
)
return
data
}
// 获取或加载组件
function
getComponent
(
url
:
string
)
{
editableFormRefs
.
value
=
[
el
];
console
.
log
(
'表单组件已挂载,组件方法:'
,
Object
.
keys
(
el
));
console
.
log
(
'是否有 submitForm 方法:'
,
typeof
el
.
submitForm
===
'function'
);
}
}
// 获取当前可编辑的表单组件实例
function
getCurrentEditableForm
():
FormComponentInstance
|
null
{
return
editableFormRefs
.
value
[
0
]
||
null
;
}
// 获取表单数据
function
getFormData
(
nodeId
:
string
):
any
{
const
data
=
formDataMap
.
value
[
nodeId
]
||
{};
console
.
log
(
'获取表单数据 - 节点:'
,
nodeId
,
'数据:'
,
data
);
return
data
;
}
// 获取或加载组件
function
getComponent
(
url
:
string
)
{
if
(
!
url
)
{
console
.
warn
(
'URL为空,返回空组件'
)
return
createEmptyComponent
()
console
.
warn
(
'URL为空,返回空组件'
);
return
createEmptyComponent
();
}
if
(
componentCache
.
has
(
url
))
{
return
componentCache
.
get
(
url
)
return
componentCache
.
get
(
url
);
}
let
componentPath
=
''
let
componentPath
=
''
;
if
(
url
.
includes
(
'/views'
))
{
componentPath
=
`/src
${
url
}
`
componentPath
=
`/src
${
url
}
`
;
}
else
{
componentPath
=
`/src/views
${
url
}
`
componentPath
=
`/src/views
${
url
}
`
;
}
if
(
!
componentPath
.
match
(
/
\.(
vue|js|ts|jsx|tsx
)
$/
))
{
componentPath
+=
'.vue'
componentPath
+=
'.vue'
;
}
console
.
log
(
'加载组件路径:'
,
componentPath
)
console
.
log
(
'加载组件路径:'
,
componentPath
);
const
loader
=
modules
[
componentPath
]
const
loader
=
modules
[
componentPath
];
if
(
!
loader
)
{
console
.
error
(
'未找到组件:'
,
componentPath
)
const
ErrorComponent
=
createErrorComponent
(
`组件未找到:
${
componentPath
}
`
)
componentCache
.
set
(
url
,
ErrorComponent
)
return
ErrorComponent
console
.
error
(
'未找到组件:'
,
componentPath
);
const
ErrorComponent
=
createErrorComponent
(
`组件未找到:
${
componentPath
}
`
);
componentCache
.
set
(
url
,
ErrorComponent
);
return
ErrorComponent
;
}
const
AsyncComponent
=
defineAsyncComponent
({
loader
:
()
=>
loader
()
as
Promise
<
{
default
:
any
}
>
,
loadingComponent
:
{
render
:
()
=>
h
(
'div'
,
{
style
:
'text-align: center; padding: 20px;'
},
'加载中...'
)
render
:
()
=>
h
(
'div'
,
{
style
:
'text-align: center; padding: 20px;'
},
'加载中...'
),
},
errorComponent
:
{
render
:
()
=>
h
(
'div'
,
{
style
:
'color: red; padding: 20px;'
},
'组件加载失败'
)
render
:
()
=>
h
(
'div'
,
{
style
:
'color: red; padding: 20px;'
},
'组件加载失败'
),
},
delay
:
200
,
timeout
:
3000
})
timeout
:
3000
,
});
componentCache
.
set
(
url
,
AsyncComponent
)
return
AsyncComponent
}
componentCache
.
set
(
url
,
AsyncComponent
);
return
AsyncComponent
;
}
function
createEmptyComponent
()
{
function
createEmptyComponent
()
{
return
{
render
:
()
=>
h
(
'div'
,
{
style
:
'color: #999; padding: 20px; text-align: center;'
},
'该节点未配置表单'
)
render
:
()
=>
h
(
'div'
,
{
style
:
'color: #999; padding: 20px; text-align: center;'
},
'该节点未配置表单'
),
};
}
}
function
createErrorComponent
(
msg
:
string
)
{
function
createErrorComponent
(
msg
:
string
)
{
return
{
render
:
()
=>
h
(
'div'
,
{
style
:
'color: red; padding: 20px;'
},
msg
)
render
:
()
=>
h
(
'div'
,
{
style
:
'color: red; padding: 20px;'
},
msg
),
};
}
}
// 处理表单数据更新
function
handleFormDataUpdate
(
data
:
any
)
{
currentFormData
.
value
=
{
...
currentFormData
.
value
,
...
data
}
emit
(
'form-data-update'
,
currentFormData
.
value
)
}
// 处理表单数据更新
function
handleFormDataUpdate
(
data
:
any
)
{
currentFormData
.
value
=
{
...
currentFormData
.
value
,
...
data
};
emit
(
'form-data-update'
,
currentFormData
.
value
);
}
/**
/**
* 从表单组件获取数据
* 优先调用组件的 getFormData 方法,如果没有则返回 formData 属性或 currentFormData
*/
async
function
getFormDataFromComponent
():
Promise
<
any
>
{
const
formComponent
=
getCurrentEditableForm
()
async
function
getFormDataFromComponent
():
Promise
<
any
>
{
const
formComponent
=
getCurrentEditableForm
();
if
(
!
formComponent
)
{
console
.
warn
(
'未找到表单组件实例'
)
return
currentFormData
.
value
console
.
warn
(
'未找到表单组件实例'
);
return
currentFormData
.
value
;
}
console
.
log
(
'当前表单组件实例:'
,
formComponent
)
console
.
log
(
'组件方法列表:'
,
Object
.
keys
(
formComponent
))
console
.
log
(
'当前表单组件实例:'
,
formComponent
);
console
.
log
(
'组件方法列表:'
,
Object
.
keys
(
formComponent
));
// 方式1:调用组件的 getFormData 方法
if
(
typeof
formComponent
.
getFormData
===
'function'
)
{
try
{
const
data
=
await
formComponent
.
getFormData
()
console
.
log
(
'通过 getFormData 方法获取的数据:'
,
data
)
return
data
const
data
=
await
formComponent
.
getFormData
();
console
.
log
(
'通过 getFormData 方法获取的数据:'
,
data
);
return
data
;
}
catch
(
error
)
{
console
.
error
(
'调用 getFormData 失败:'
,
error
)
console
.
error
(
'调用 getFormData 失败:'
,
error
);
}
}
// 方式2:获取组件的 formData 属性
if
(
formComponent
.
formData
!==
undefined
)
{
console
.
log
(
'通过 formData 属性获取的数据:'
,
formComponent
.
formData
)
return
formComponent
.
formData
console
.
log
(
'通过 formData 属性获取的数据:'
,
formComponent
.
formData
);
return
formComponent
.
formData
;
}
// 方式3:如果组件有内部表单数据,尝试获取
if
(
formComponent
.
getValues
&&
typeof
formComponent
.
getValues
===
'function'
)
{
try
{
const
data
=
await
formComponent
.
getValues
()
console
.
log
(
'通过 getValues 方法获取的数据:'
,
data
)
return
data
const
data
=
await
formComponent
.
getValues
();
console
.
log
(
'通过 getValues 方法获取的数据:'
,
data
);
return
data
;
}
catch
(
error
)
{
console
.
error
(
'调用 getValues 失败:'
,
error
)
console
.
error
(
'调用 getValues 失败:'
,
error
);
}
}
// 方式4:返回本地维护的 currentFormData
console
.
log
(
'使用本地维护的 currentFormData:'
,
currentFormData
.
value
)
return
currentFormData
.
value
}
console
.
log
(
'使用本地维护的 currentFormData:'
,
currentFormData
.
value
);
return
currentFormData
.
value
;
}
/**
/**
* 验证表单数据
*/
async
function
validateForm
():
Promise
<
boolean
>
{
const
formComponent
=
getCurrentEditableForm
()
async
function
validateForm
():
Promise
<
boolean
>
{
const
formComponent
=
getCurrentEditableForm
();
if
(
!
formComponent
)
{
return
true
return
true
;
}
// 方式1:调用组件的 validate 方法
if
(
typeof
formComponent
.
validate
===
'function'
)
{
try
{
await
formComponent
.
validate
()
return
true
await
formComponent
.
validate
();
return
true
;
}
catch
(
error
)
{
console
.
error
(
'表单验证失败:'
,
error
)
return
false
console
.
error
(
'表单验证失败:'
,
error
);
return
false
;
}
}
// 方式2:如果组件有 vee-validate 或其他验证库的实例
if
(
formComponent
.
v$
&&
typeof
formComponent
.
v$
.
$validate
===
'function'
)
{
try
{
const
isValid
=
await
formComponent
.
v$
.
$validate
()
return
isValid
const
isValid
=
await
formComponent
.
v$
.
$validate
();
return
isValid
;
}
catch
(
error
)
{
console
.
error
(
'验证失败:'
,
error
)
return
false
console
.
error
(
'验证失败:'
,
error
);
return
false
;
}
}
// 如果没有验证方法,默认通过
return
true
}
return
true
;
}
// 提交处理
async
function
handleSubmit
()
{
// 提交处理
async
function
handleSubmit
()
{
if
(
!
editableNode
.
value
)
{
message
.
warning
(
'没有可编辑的表单'
)
return
message
.
warning
(
'没有可编辑的表单'
);
return
;
}
submitLoading
.
value
=
true
submitLoading
.
value
=
true
;
try
{
const
formComponent
=
getCurrentEditableForm
()
const
formComponent
=
getCurrentEditableForm
();
// 🔥 优先调用子组件的 submitForm 方法
if
(
formComponent
&&
typeof
formComponent
.
submitForm
===
'function'
)
{
console
.
log
(
'调用子组件的 submitForm 方法'
)
console
.
log
(
'调用子组件的 submitForm 方法'
);
// 调用子组件的 submitForm 方法,并等待返回结果
const
result
=
await
formComponent
.
submitForm
()
const
result
=
await
formComponent
.
submitForm
();
// 如果子组件的 submitForm 返回了数据,则使用返回的数据
if
(
result
!==
undefined
)
{
console
.
log
(
'submitForm 返回的数据:'
,
result
)
console
.
log
(
'submitForm 返回的数据:'
,
result
);
// 触发提交事件
emit
(
'submit'
,
{
...
...
@@ -386,34 +438,34 @@ async function handleSubmit() {
nodeName
:
editableNode
.
value
.
name
,
formData
:
result
,
procDefId
:
props
.
procDefId
,
formComponent
:
formComponent
})
formComponent
:
formComponent
,
});
message
.
success
(
'提交成功'
)
handleClose
()
return
message
.
success
(
'提交成功'
);
handleClose
();
return
;
}
}
// 如果没有 submitForm 方法或 submitForm 没有返回数据,则使用原来的逻辑
console
.
log
(
'使用默认提交逻辑'
)
console
.
log
(
'使用默认提交逻辑'
);
// 1. 先进行表单验证
const
isValid
=
await
validateForm
()
const
isValid
=
await
validateForm
();
if
(
!
isValid
)
{
message
.
error
(
'请完善表单信息'
)
return
message
.
error
(
'请完善表单信息'
);
return
;
}
// 2. 获取表单数据
const
submitData
=
await
getFormDataFromComponent
()
const
submitData
=
await
getFormDataFromComponent
();
console
.
log
(
'最终提交数据:'
,
{
nodeId
:
editableNode
.
value
.
id
,
nodeName
:
editableNode
.
value
.
name
,
formData
:
submitData
,
procDefId
:
props
.
procDefId
})
procDefId
:
props
.
procDefId
,
});
// 3. 触发提交事件
emit
(
'submit'
,
{
...
...
@@ -421,111 +473,138 @@ async function handleSubmit() {
nodeName
:
editableNode
.
value
.
name
,
formData
:
submitData
,
procDefId
:
props
.
procDefId
,
formComponent
:
formComponent
})
formComponent
:
formComponent
,
});
message
.
success
(
'提交成功'
)
message
.
success
(
'提交成功'
);
// 提交成功后关闭抽屉
handleClose
()
handleClose
();
}
catch
(
error
:
any
)
{
console
.
error
(
'提交失败:'
,
error
)
message
.
error
(
error
?.
message
||
'提交失败,请重试'
)
console
.
error
(
'提交失败:'
,
error
);
message
.
error
(
error
?.
message
||
'提交失败,请重试'
);
}
finally
{
submitLoading
.
value
=
false
submitLoading
.
value
=
false
;
}
}
}
// 关闭抽屉
function
handleClose
()
{
emit
(
'update:visible'
,
false
)
emit
(
'close'
)
// 关闭抽屉
function
handleClose
()
{
visibleRef
.
value
=
false
;
emit
(
'update:visible'
,
false
);
emit
(
'close'
);
// 关闭后清空表单引用
editableFormRefs
.
value
=
[]
}
editableFormRefs
.
value
=
[];
}
// 重置数据
function
resetFormData
()
{
currentFormData
.
value
=
{}
// 重置数据
function
resetFormData
()
{
currentFormData
.
value
=
{};
const
newFormDataMap
:
Record
<
string
,
any
>
=
{}
readonlyNodes
.
value
.
forEach
(
node
=>
{
newFormDataMap
[
node
.
id
]
=
props
.
externalFormData
[
node
.
id
]
||
{}
})
formDataMap
.
value
=
newFormDataMap
const
newFormDataMap
:
Record
<
string
,
any
>
=
{};
readonlyNodes
.
value
.
forEach
((
node
)
=>
{
newFormDataMap
[
node
.
id
]
=
innerExternalFormData
.
value
[
node
.
id
]
||
{};
});
formDataMap
.
value
=
newFormDataMap
;
if
(
editableNode
.
value
&&
props
.
externalFormData
[
editableNode
.
value
.
id
])
{
currentFormData
.
value
=
{
...
props
.
externalFormData
[
editableNode
.
value
.
id
]
}
if
(
editableNode
.
value
&&
innerExternalFormData
.
value
[
editableNode
.
value
.
id
])
{
currentFormData
.
value
=
{
...
innerExternalFormData
.
value
[
editableNode
.
value
.
id
]
};
}
// 设置默认激活的选项卡为可编辑的选项卡
if
(
editableNode
.
value
)
{
activeTabKey
.
value
=
editableNode
.
value
.
id
console
.
log
(
'设置激活选项卡为可编辑节点:'
,
editableNode
.
value
.
name
)
activeTabKey
.
value
=
editableNode
.
value
.
id
;
console
.
log
(
'设置激活选项卡为可编辑节点:'
,
editableNode
.
value
.
name
);
}
else
if
(
readonlyNodes
.
value
.
length
>
0
)
{
activeTabKey
.
value
=
readonlyNodes
.
value
[
0
].
id
console
.
log
(
'设置激活选项卡为第一个只读节点:'
,
readonlyNodes
.
value
[
0
].
name
)
activeTabKey
.
value
=
readonlyNodes
.
value
[
0
].
id
;
console
.
log
(
'设置激活选项卡为第一个只读节点:'
,
readonlyNodes
.
value
[
0
].
name
);
}
}
}
// 预加载组件
function
preloadComponents
()
{
props
.
workflowNodes
.
forEach
(
node
=>
{
const
url
=
node
.
formUrl
||
node
.
formListUrl
// 预加载组件
function
preloadComponents
()
{
innerWorkflowNodes
.
value
.
forEach
((
node
)
=>
{
const
url
=
node
.
formUrl
||
node
.
formListUrl
;
if
(
url
)
{
getComponent
(
url
)
getComponent
(
url
);
}
});
}
})
}
// 监听抽屉打开
watch
(()
=>
props
.
visible
,
(
newVal
)
=>
{
// 监听外部 visible prop 同步到内部 visibleRef
watch
(
()
=>
props
.
visible
,
(
newVal
)
=>
{
visibleRef
.
value
=
!!
newVal
;
},
{
immediate
:
true
}
);
// 监听内部抽屉打开
watch
(
()
=>
visibleRef
.
value
,
(
newVal
)
=>
{
if
(
newVal
)
{
console
.
log
(
'抽屉打开,currentNodeIndex:'
,
props
.
currentNodeIndex
)
console
.
log
(
'所有节点:'
,
props
.
workflowNodes
)
resetFormData
()
preloadComponents
()
console
.
log
(
'抽屉打开,currentNodeIndex:'
,
innerCurrentNodeIndex
.
value
);
console
.
log
(
'所有节点:'
,
innerWorkflowNodes
.
value
);
resetFormData
();
preloadComponents
();
// 清空之前的表单引用
editableFormRefs
.
value
=
[]
editableFormRefs
.
value
=
[];
}
},
{
immediate
:
true
})
},
{
immediate
:
true
}
);
// 监听外部数据变化
watch
(()
=>
props
.
externalFormData
,
(
newData
)
=>
{
// 监听外部数据变化
watch
(
()
=>
innerExternalFormData
.
value
,
(
newData
)
=>
{
if
(
newData
&&
Object
.
keys
(
newData
).
length
>
0
)
{
console
.
log
(
'外部数据变化:'
,
newData
)
const
newFormDataMap
=
{
...
formDataMap
.
value
}
readonlyNodes
.
value
.
forEach
(
node
=>
{
console
.
log
(
'外部数据变化:'
,
newData
);
const
newFormDataMap
=
{
...
formDataMap
.
value
};
readonlyNodes
.
value
.
forEach
((
node
)
=>
{
if
(
newData
[
node
.
id
])
{
newFormDataMap
[
node
.
id
]
=
newData
[
node
.
id
]
newFormDataMap
[
node
.
id
]
=
newData
[
node
.
id
];
}
})
formDataMap
.
value
=
newFormDataMap
});
formDataMap
.
value
=
newFormDataMap
;
if
(
editableNode
.
value
&&
newData
[
editableNode
.
value
.
id
])
{
currentFormData
.
value
=
newData
[
editableNode
.
value
.
id
]
currentFormData
.
value
=
newData
[
editableNode
.
value
.
id
];
}
}
},
{
deep
:
true
})
onMounted
(()
=>
{
console
.
log
(
'组件挂载,workflowNodes:'
,
props
.
workflowNodes
)
console
.
log
(
'currentNodeIndex:'
,
props
.
currentNodeIndex
)
resetFormData
()
preloadComponents
()
})
},
{
deep
:
true
}
);
onMounted
(()
=>
{
console
.
log
(
'组件挂载,workflowNodes:'
,
props
.
workflowNodes
);
console
.
log
(
'currentNodeIndex:'
,
props
.
currentNodeIndex
);
resetFormData
();
preloadComponents
();
// register modal methods for useModal() via useModalInner.register
if
(
instance
)
{
try
{
registerInner
(
modalMethods
,
instance
.
uid
);
}
catch
(
e
)
{
// fallback to emit if registerInner not available
emit
(
'register'
,
modalMethods
,
instance
.
uid
);
}
}
});
defineExpose
({
defineExpose
({
resetFormData
,
getFormData
:
()
=>
currentFormData
.
value
,
getCurrentFormData
:
getFormDataFromComponent
,
validate
:
validateForm
,
submit
:
handleSubmit
})
submit
:
handleSubmit
,
});
</
script
>
<
style
scoped
lang=
"scss"
>
.workflow-form-drawer
{
.workflow-form-drawer
{
width
:
100%
;
height
:
100%
;
overflow-y
:
auto
;
...
...
@@ -616,9 +695,9 @@ defineExpose({
background
:
#a8a8a8
;
}
}
}
}
.drawer-footer
{
.drawer-footer
{
text-align
:
right
;
:deep
(
.ant-btn
)
{
...
...
@@ -628,15 +707,15 @@ defineExpose({
margin-left
:
0
;
}
}
}
}
:deep
(
.ant-drawer-body
)
{
:deep
(
.ant-drawer-body
)
{
padding
:
16px
;
background-color
:
#f5f7fa
;
}
}
:deep
(
.ant-drawer-footer
)
{
:deep
(
.ant-drawer-footer
)
{
padding
:
12px
16px
;
border-top
:
1px
solid
#e8eef2
;
}
}
</
style
>
zrch-risk-client-39/src/views/flowable/task/finished/components/Detail.vue
浏览文件 @
5a8e52f3
...
...
@@ -2,20 +2,20 @@
<div
class=
"app-container"
>
<a-card
class=
"box-card"
>
<template
#
title
>
<
span><FileTextOutlined
/>
待办任务
</span
>
<
!--
<span><FileTextOutlined
/>
待办任务
</span>
--
>
<div
style=
"float: right"
>
<a-tag
style=
"margin-left: 10px"
>
发起人:
{{
startUser
}}
</a-tag>
<a-tag>
任务节点:
{{
taskName
}}
</a-tag>
</div>
</
template
>
<a-tabs
v-model:activeKey=
"activeName"
@
tab
C
lick=
"handleClick"
>
<a-tabs
v-model:activeKey=
"activeName"
@
tab
-c
lick=
"handleClick"
>
<!--表单信息-->
<a-tab-pane
key=
"1"
tab=
"主表单信息"
>
<div
v-show=
"formUrl"
class=
"iframe-container"
>
<iFrame
:src=
"formUrl"
class=
"responsive-iframe"
></iFrame>
</div>
<div
v-show=
"!formUrl"
style=
"margin:
10px;width:
100%"
>
<div
v-show=
"!formUrl"
style=
"margin:
10px; width:
100%"
>
<FlowInnerForm
ref=
"refInnerForm"
></FlowInnerForm>
</div>
</a-tab-pane>
...
...
@@ -24,37 +24,19 @@
<a-tab-pane
key=
"2"
tab=
"流转记录"
>
<div
class=
"block"
>
<a-steps
direction=
"vertical"
size=
"small"
>
<a-step
v-for=
"(item, index) in flowRecordList"
:key=
"index"
:status=
"getStepStatus(item.finishTime)"
:title=
"item.taskName"
>
<a-step
v-for=
"(item, index) in flowRecordList"
:key=
"index"
:status=
"getStepStatus(item.finishTime)"
:title=
"item.taskName"
>
<
template
#
description
>
<a-card
:body-style=
"
{ padding: '0px', marginTop: '0px' }">
<a-descriptions
class=
"margin-top"
:column=
"1"
size=
"small"
bordered
>
<a-descriptions-item
v-if=
"item.assigneeName"
label=
"办理人"
>
<a-descriptions
class=
"margin-top"
:column=
"1"
size=
"small"
bordered
>
<a-descriptions-item
v-if=
"item.assigneeName"
label=
"办理人"
>
<template
#
label
>
<UserOutlined
/>
办理人
</
template
>
{{ item.assigneeName }}
<a-tag
color=
"gray"
size=
"small"
>
{{
item.deptName
}}
</a-tag>
<a-tag
color=
"gray"
size=
"small"
>
{{ item.deptName }}
</a-tag>
</a-descriptions-item>
<a-descriptions-item
v-if=
"item.candidate"
label=
"候选办理"
>
<a-descriptions-item
v-if=
"item.candidate"
label=
"候选办理"
>
<
template
#
label
>
<UserOutlined
/>
候选办理
...
...
@@ -68,30 +50,21 @@
</
template
>
{{ item.createTime }}
</a-descriptions-item>
<a-descriptions-item
v-if=
"item.finishTime"
label=
"处理时间"
>
<a-descriptions-item
v-if=
"item.finishTime"
label=
"处理时间"
>
<
template
#
label
>
<CalendarOutlined
/>
处理时间
</
template
>
{{ item.finishTime }}
</a-descriptions-item>
<a-descriptions-item
v-if=
"item.duration"
label=
"耗时"
>
<a-descriptions-item
v-if=
"item.duration"
label=
"耗时"
>
<
template
#
label
>
<ClockCircleOutlined
/>
耗时
</
template
>
{{ item.duration }}
</a-descriptions-item>
<a-descriptions-item
v-if=
"item.comment"
label=
"处理意见"
>
<a-descriptions-item
v-if=
"item.comment"
label=
"处理意见"
>
<
template
#
label
>
<FormOutlined
/>
处理意见
...
...
@@ -115,62 +88,54 @@
</template>
<
script
lang=
"ts"
setup
>
import
{
ref
,
reactive
,
nextTick
}
from
'vue'
import
{
FileTextOutlined
,
UserOutlined
,
CalendarOutlined
,
ClockCircleOutlined
,
FormOutlined
,
}
from
'@ant-design/icons-vue'
import
{
flowRecord
}
from
"/@/components/Process/api/finished"
import
{
flowXmlAndNode
}
from
"/@/components/Process/api/definition"
import
{
findFlowFormVal
}
from
"/@/components/Process/api/todo"
import
{
flowFormData
}
from
"/@/components/Process/api/process"
import
BpmnViewer
from
'/@/components/Process/viewer/index.vue'
import
FlowInnerForm
from
'/@/views/flowable/task/components/FlowInnerForm.vue'
interface
FlowRecordItem
{
taskName
:
string
finishTime
:
string
|
null
assigneeName
:
string
deptName
:
string
candidate
:
string
createTime
:
string
duration
:
string
import
{
ref
,
reactive
,
nextTick
}
from
'vue'
;
import
{
FileTextOutlined
,
UserOutlined
,
CalendarOutlined
,
ClockCircleOutlined
,
FormOutlined
}
from
'@ant-design/icons-vue'
;
import
{
flowRecord
}
from
'/@/components/Process/api/finished'
;
import
{
flowXmlAndNode
}
from
'/@/components/Process/api/definition'
;
import
{
findFlowFormVal
}
from
'/@/components/Process/api/todo'
;
import
{
flowFormData
}
from
'/@/components/Process/api/process'
;
import
BpmnViewer
from
'/@/components/Process/viewer/index.vue'
;
import
FlowInnerForm
from
'/@/views/flowable/task/components/FlowInnerForm.vue'
;
interface
FlowRecordItem
{
taskName
:
string
;
finishTime
:
string
|
null
;
assigneeName
:
string
;
deptName
:
string
;
candidate
:
string
;
createTime
:
string
;
duration
:
string
;
comment
:
{
comment
:
string
comment
:
string
;
};
}
}
interface
TaskForm
{
returnTaskShow
:
boolean
delegateTaskShow
:
boolean
defaultTaskShow
:
boolean
comment
:
string
procInsId
:
string
instanceId
:
string
deployId
:
string
taskId
:
string
procDefId
:
string
targetKey
:
string
variables
:
Record
<
string
,
any
>
executionId
?:
string
}
const
flowData
=
ref
({})
const
activeName
=
ref
(
'1'
)
const
formUrl
=
ref
();
const
refInnerForm
=
ref
();
interface
TaskForm
{
returnTaskShow
:
boolean
;
delegateTaskShow
:
boolean
;
defaultTaskShow
:
boolean
;
comment
:
string
;
procInsId
:
string
;
instanceId
:
string
;
deployId
:
string
;
taskId
:
string
;
procDefId
:
string
;
targetKey
:
string
;
variables
:
Record
<
string
,
any
>
;
executionId
?:
string
;
}
const
flowData
=
ref
({});
const
activeName
=
ref
(
'1'
);
const
formUrl
=
ref
();
const
refInnerForm
=
ref
();
// 遮罩层
const
loading
=
ref
(
true
)
const
flowRecordList
=
ref
<
FlowRecordItem
[]
>
([])
const
taskForm
=
reactive
<
TaskForm
>
({
// 遮罩层
const
loading
=
ref
(
true
);
const
flowRecordList
=
ref
<
FlowRecordItem
[]
>
([]);
const
taskForm
=
reactive
<
TaskForm
>
({
returnTaskShow
:
false
,
delegateTaskShow
:
false
,
defaultTaskShow
:
true
,
...
...
@@ -182,115 +147,107 @@ const taskForm = reactive<TaskForm>({
procDefId
:
''
,
targetKey
:
''
,
variables
:
{},
})
});
const
taskName
=
ref
<
string
|
null
>
(
null
);
// 任务节点
const
startUser
=
ref
<
string
|
null
>
(
null
);
// 发起人信息
const
taskName
=
ref
<
string
|
null
>
(
null
)
// 任务节点
const
startUser
=
ref
<
string
|
null
>
(
null
)
// 发起人信息
const
handleClick
=
(
key
:
string
)
=>
{
if
(
key
===
'3'
)
{
const
handleClick
=
(
key
:
string
)
=>
{
if
(
key
===
'3'
)
{
flowXmlAndNode
({
procInsId
:
taskForm
.
procInsId
,
deployId
:
taskForm
.
deployId
,
}).
then
((
res
)
=>
{
flowData
.
value
=
res
console
.
log
(
"xml"
,
JSON
.
stringify
(
res
))
})
flowData
.
value
=
res
;
console
.
log
(
'xml'
,
JSON
.
stringify
(
res
));
})
;
}
}
};
// 修改 setColor 方法为 getStepStatus
const
getStepStatus
=
(
finishTime
:
string
|
null
)
=>
{
// 修改 setColor 方法为 getStepStatus
const
getStepStatus
=
(
finishTime
:
string
|
null
)
=>
{
if
(
finishTime
)
{
return
'finish'
// 已完成
return
'finish'
;
// 已完成
}
else
{
return
'wait'
// 等待中
return
'wait'
;
// 等待中
}
}
};
const
setFlowRecordList
=
async
(
procInsId
:
string
,
deployId
:
string
)
=>
{
const
params
=
{
procInsId
,
deployId
}
const
setFlowRecordList
=
async
(
procInsId
:
string
,
deployId
:
string
)
=>
{
const
params
=
{
procInsId
,
deployId
};
await
flowRecord
(
params
)
.
then
((
res
)
=>
{
console
.
log
(
"flowList"
,
res
)
flowRecordList
.
value
=
res
.
flowList
console
.
log
(
'flowList'
,
res
);
flowRecordList
.
value
=
res
.
flowList
;
})
.
catch
(()
=>
{
//goBack()
})
}
const
iniData
=
async
(
data
)
=>
{
taskName
.
value
=
data
.
taskName
as
string
startUser
.
value
=
data
.
startUserName
as
string
taskForm
.
deployId
=
data
.
deployId
as
string
taskForm
.
taskId
=
data
.
taskId
as
string
taskForm
.
procInsId
=
data
.
procInsId
as
string
taskForm
.
executionId
=
data
.
executionId
as
string
taskForm
.
instanceId
=
data
.
procInsId
as
string
await
flowFormData
({
deployId
:
taskForm
.
deployId
}).
then
(
resData
=>
{
});
};
const
iniData
=
async
(
data
)
=>
{
taskName
.
value
=
data
.
taskName
as
string
;
startUser
.
value
=
data
.
startUserName
as
string
;
taskForm
.
deployId
=
data
.
deployId
as
string
;
taskForm
.
taskId
=
data
.
taskId
as
string
;
taskForm
.
procInsId
=
data
.
procInsId
as
string
;
taskForm
.
executionId
=
data
.
executionId
as
string
;
taskForm
.
instanceId
=
data
.
procInsId
as
string
;
await
flowFormData
({
deployId
:
taskForm
.
deployId
}).
then
((
resData
)
=>
{
nextTick
(()
=>
{
if
(
resData
.
formUrl
)
{
formUrl
.
value
=
resData
.
formUrl
if
(
resData
.
formUrl
)
{
formUrl
.
value
=
resData
.
formUrl
;
}
else
{
formUrl
.
value
=
""
refInnerForm
.
value
.
iniData
(
resData
)
formUrl
.
value
=
''
;
refInnerForm
.
value
.
iniData
(
resData
)
;
}
})
})
})
;
})
;
if
(
taskForm
.
taskId
)
{
await
findFlowFormVal
({
taskId
:
taskForm
.
taskId
}).
then
((
resValues
)
=>
{
if
(
taskForm
.
taskId
)
{
await
findFlowFormVal
({
taskId
:
taskForm
.
taskId
}).
then
((
resValues
)
=>
{
nextTick
(()
=>
{
refInnerForm
.
value
.
setFormData
(
resValues
)
})
})
refInnerForm
.
value
.
setFormData
(
resValues
)
;
})
;
})
;
}
setFlowRecordList
(
taskForm
.
procInsId
,
taskForm
.
deployId
)
}
setFlowRecordList
(
taskForm
.
procInsId
,
taskForm
.
deployId
);
};
defineExpose
({
defineExpose
({
iniData
,
})
});
</
script
>
<
style
lang=
"scss"
scoped
>
.clearfix
:before
,
.clearfix
:after
{
.clearfix
:before
,
.clearfix
:after
{
display
:
table
;
content
:
""
;
}
.clearfix
:after
{
clear
:
both
}
content
:
''
;
}
.clearfix
:after
{
clear
:
both
;
}
.app-container
{
.app-container
{
height
:
calc
(
100vh
-
150px
);
margin
:
0px
;
padding
:
5px
;
}
}
.my-label
{
background
:
#E1F3D
8
;
}
.my-label
{
background
:
#e1f3d
8
;
}
.iframe-container
{
.iframe-container
{
height
:
calc
(
100vh
-
200px
);
width
:
100%
;
}
.responsive-iframe
{
}
.responsive-iframe
{
width
:
100%
;
height
:
100%
;
border
:
none
;
}
}
</
style
>
zrch-risk-client-39/src/views/flowable/task/myProcess/components/Detail.vue
浏览文件 @
5a8e52f3
...
...
@@ -2,20 +2,20 @@
<div
class=
"app-container"
>
<a-card
class=
"box-card"
>
<template
#
title
>
<
span><FileTextOutlined
/>
待办任务
</span
>
<
!--
<span><FileTextOutlined
/>
待办任务
</span>
--
>
<div
style=
"float: right"
>
<a-tag
style=
"margin-left: 10px"
>
发起人:
{{
startUser
}}
</a-tag>
<a-tag>
任务节点:
{{
taskName
}}
</a-tag>
</div>
</
template
>
<a-tabs
v-model:activeKey=
"activeName"
@
tab
C
lick=
"handleClick"
>
<a-tabs
v-model:activeKey=
"activeName"
@
tab
-c
lick=
"handleClick"
>
<!--表单信息-->
<a-tab-pane
key=
"1"
tab=
"主表单信息"
>
<div
v-show=
"formUrl"
class=
"iframe-container"
>
<iFrame
:src=
"formUrl"
class=
"responsive-iframe"
></iFrame>
</div>
<div
v-show=
"!formUrl"
style=
"margin:
10px;width:
100%"
>
<div
v-show=
"!formUrl"
style=
"margin:
10px; width:
100%"
>
<FlowInnerForm
ref=
"refInnerForm"
></FlowInnerForm>
</div>
</a-tab-pane>
...
...
@@ -24,43 +24,25 @@
<a-tab-pane
key=
"2"
tab=
"流转记录"
>
<div
class=
"block"
>
<a-steps
direction=
"vertical"
size=
"small"
>
<a-step
v-for=
"(item, index) in flowRecordList"
:key=
"index"
:status=
"getStepStatus(item.finishTime)"
>
<a-step
v-for=
"(item, index) in flowRecordList"
:key=
"index"
:status=
"getStepStatus(item.finishTime)"
>
<
template
#
title
>
<div
style=
"margin: 5px"
>
<span
style=
"margin-right: 50px
;
"
>
节点名称:
{{
item
.
taskName
}}
</span>
<span
style=
"margin-right: 50px"
>
节点名称:
{{
item
.
taskName
}}
</span>
<a-button
type=
"link"
@
click=
"showNodeFormData(item)"
>
查看表单
</a-button>
</div>
</
template
>
<
template
#
description
>
<a-card
:body-style=
"
{ padding: '0px', marginTop: '0px' }">
<a-descriptions
class=
"margin-top"
:column=
"1"
size=
"small"
bordered
>
<a-descriptions-item
v-if=
"item.assigneeName"
label=
"办理人"
>
<a-descriptions
class=
"margin-top"
:column=
"1"
size=
"small"
bordered
>
<a-descriptions-item
v-if=
"item.assigneeName"
label=
"办理人"
>
<template
#
label
>
<UserOutlined
/>
办理人
</
template
>
{{ item.assigneeName }}
<a-tag
color=
"gray"
size=
"small"
>
{{
item.deptName
}}
</a-tag>
<a-tag
color=
"gray"
size=
"small"
>
{{ item.deptName }}
</a-tag>
</a-descriptions-item>
<a-descriptions-item
v-if=
"item.candidate"
label=
"候选办理"
>
<a-descriptions-item
v-if=
"item.candidate"
label=
"候选办理"
>
<
template
#
label
>
<UserOutlined
/>
候选办理
...
...
@@ -74,30 +56,21 @@
</
template
>
{{ item.createTime }}
</a-descriptions-item>
<a-descriptions-item
v-if=
"item.finishTime"
label=
"处理时间"
>
<a-descriptions-item
v-if=
"item.finishTime"
label=
"处理时间"
>
<
template
#
label
>
<CalendarOutlined
/>
处理时间
</
template
>
{{ item.finishTime }}
</a-descriptions-item>
<a-descriptions-item
v-if=
"item.duration"
label=
"耗时"
>
<a-descriptions-item
v-if=
"item.duration"
label=
"耗时"
>
<
template
#
label
>
<ClockCircleOutlined
/>
耗时
</
template
>
{{ item.duration }}
</a-descriptions-item>
<a-descriptions-item
v-if=
"item.comment?.comment"
label=
"处理意见"
>
<a-descriptions-item
v-if=
"item.comment?.comment"
label=
"处理意见"
>
<
template
#
label
>
<FormOutlined
/>
处理意见
...
...
@@ -117,70 +90,62 @@
</a-tab-pane>
</a-tabs>
</a-card>
<ShowFormModal
@
register=
"registerShowFormModal"
/>
<ShowFormModal
@
register=
"registerShowFormModal"
@
submit=
"handleShowFormSubmit"
/>
</div>
</template>
<
script
lang=
"ts"
setup
>
import
{
ref
,
reactive
,
nextTick
}
from
'vue'
import
{
FileTextOutlined
,
UserOutlined
,
CalendarOutlined
,
ClockCircleOutlined
,
FormOutlined
,
}
from
'@ant-design/icons-vue'
import
{
flowRecord
}
from
"/@/components/Process/api/finished"
import
{
flowXmlAndNode
}
from
"/@/components/Process/api/definition"
import
{
findFlowFormVal
}
from
"/@/components/Process/api/todo"
import
{
useModal
}
from
'/@/components/Modal'
;
import
{
flowFormData
}
from
"/@/components/Process/api/process"
import
BpmnViewer
from
'/@/components/Process/viewer/index.vue'
import
FlowInnerForm
from
'/@/views/flowable/task/components/FlowInnerForm.vue'
import
ShowFormModal
from
'/@/views/flowable/task/components/ShowFormModal.vue'
interface
FlowRecordItem
{
taskName
:
string
finishTime
:
string
|
null
assigneeName
:
string
deptName
:
string
candidate
:
string
createTime
:
string
duration
:
string
import
{
ref
,
reactive
,
nextTick
}
from
'vue'
;
import
{
FileTextOutlined
,
UserOutlined
,
CalendarOutlined
,
ClockCircleOutlined
,
FormOutlined
}
from
'@ant-design/icons-vue'
;
import
{
flowRecord
}
from
'/@/components/Process/api/finished'
;
import
{
flowXmlAndNode
}
from
'/@/components/Process/api/definition'
;
import
{
findFlowFormVal
}
from
'/@/components/Process/api/todo'
;
import
{
useModal
}
from
'/@/components/Modal'
;
import
{
flowFormData
}
from
'/@/components/Process/api/process'
;
import
BpmnViewer
from
'/@/components/Process/viewer/index.vue'
;
import
FlowInnerForm
from
'/@/views/flowable/task/components/FlowInnerForm.vue'
;
import
ShowFormModal
from
'/@/views/flowable/task/components/ShowFormModal.vue'
;
interface
FlowRecordItem
{
taskName
:
string
;
finishTime
:
string
|
null
;
assigneeName
:
string
;
deptName
:
string
;
candidate
:
string
;
createTime
:
string
;
duration
:
string
;
comment
:
{
comment
:
string
comment
:
string
;
};
}
}
interface
TaskForm
{
returnTaskShow
:
boolean
delegateTaskShow
:
boolean
defaultTaskShow
:
boolean
comment
:
string
procInsId
:
string
instanceId
:
string
deployId
:
string
taskId
:
string
procDefId
:
string
targetKey
:
string
variables
:
Record
<
string
,
any
>
executionId
?:
string
}
const
flowData
=
ref
({})
const
activeName
=
ref
(
'1'
)
const
formUrl
=
ref
();
const
refInnerForm
=
ref
();
interface
TaskForm
{
returnTaskShow
:
boolean
;
delegateTaskShow
:
boolean
;
defaultTaskShow
:
boolean
;
comment
:
string
;
procInsId
:
string
;
instanceId
:
string
;
deployId
:
string
;
taskId
:
string
;
procDefId
:
string
;
targetKey
:
string
;
variables
:
Record
<
string
,
any
>
;
executionId
?:
string
;
}
const
flowData
=
ref
({});
const
activeName
=
ref
(
'1'
);
const
formUrl
=
ref
();
const
refInnerForm
=
ref
();
const
[
registerShowFormModal
,
{
openModal
,
setModalProps
}
]
=
useModal
();
const
[
registerShowFormModal
,
showFormModalApi
]
=
useModal
();
// 遮罩层
const
loading
=
ref
(
true
)
const
flowRecordList
=
ref
<
FlowRecordItem
[]
>
([])
const
taskForm
=
reactive
<
TaskForm
>
({
// 遮罩层
const
loading
=
ref
(
true
);
const
flowRecordList
=
ref
<
FlowRecordItem
[]
>
([]);
const
taskForm
=
reactive
<
TaskForm
>
({
returnTaskShow
:
false
,
delegateTaskShow
:
false
,
defaultTaskShow
:
true
,
...
...
@@ -192,125 +157,140 @@ const taskForm = reactive<TaskForm>({
procDefId
:
''
,
targetKey
:
''
,
variables
:
{},
})
const
taskName
=
ref
<
string
|
null
>
(
null
)
// 任务节点
const
startUser
=
ref
<
string
|
null
>
(
null
)
// 发起人信息
});
const
taskName
=
ref
<
string
|
null
>
(
null
);
// 任务节点
const
startUser
=
ref
<
string
|
null
>
(
null
);
// 发起人信息
const
handleClick
=
(
key
:
string
)
=>
{
if
(
key
===
'3'
)
{
const
handleClick
=
(
key
:
string
)
=>
{
if
(
key
===
'3'
)
{
flowXmlAndNode
({
procInsId
:
taskForm
.
procInsId
,
deployId
:
taskForm
.
deployId
,
}).
then
((
res
)
=>
{
flowData
.
value
=
res
})
flowData
.
value
=
res
;
})
;
}
}
};
// 修改 setColor 方法为 getStepStatus
const
getStepStatus
=
(
finishTime
:
string
|
null
)
=>
{
// 修改 setColor 方法为 getStepStatus
const
getStepStatus
=
(
finishTime
:
string
|
null
)
=>
{
if
(
finishTime
)
{
return
'finish'
// 已完成
return
'finish'
;
// 已完成
}
else
{
return
'wait'
// 等待中
return
'wait'
;
// 等待中
}
}
};
const
setFlowRecordList
=
async
(
procInsId
:
string
,
deployId
:
string
)
=>
{
const
params
=
{
procInsId
,
deployId
}
const
setFlowRecordList
=
async
(
procInsId
:
string
,
deployId
:
string
)
=>
{
const
params
=
{
procInsId
,
deployId
};
await
flowRecord
(
params
)
.
then
((
res
)
=>
{
console
.
log
(
"flowList"
,
res
)
flowRecordList
.
value
=
res
.
flowList
console
.
log
(
'flowList'
,
res
);
flowRecordList
.
value
=
res
.
flowList
;
})
.
catch
(()
=>
{
//goBack()
})
}
const
taskDataObj
=
ref
()
const
iniData
=
async
(
data
)
=>
{
taskDataObj
.
value
=
data
taskName
.
value
=
data
.
taskName
as
string
startUser
.
value
=
data
.
startUserName
as
string
taskForm
.
deployId
=
data
.
deployId
as
string
taskForm
.
taskId
=
data
.
taskId
as
string
taskForm
.
procInsId
=
data
.
procInsId
as
string
taskForm
.
executionId
=
data
.
executionId
as
string
taskForm
.
instanceId
=
data
.
procInsId
as
string
});
};
const
taskDataObj
=
ref
();
const
iniData
=
async
(
data
)
=>
{
taskDataObj
.
value
=
data
;
taskName
.
value
=
data
.
taskName
as
string
;
startUser
.
value
=
data
.
startUserName
as
string
;
taskForm
.
deployId
=
data
.
deployId
as
string
;
taskForm
.
taskId
=
data
.
taskId
as
string
;
taskForm
.
procInsId
=
data
.
procInsId
as
string
;
taskForm
.
executionId
=
data
.
executionId
as
string
;
taskForm
.
instanceId
=
data
.
procInsId
as
string
;
//console.log('taskForm.taskId:', taskForm.taskId);
await
flowFormData
({
deployId
:
taskForm
.
deployId
,
taskId
:
taskForm
.
taskId
}).
then
(
resData
=>
{
await
flowFormData
({
deployId
:
taskForm
.
deployId
,
taskId
:
taskForm
.
taskId
}).
then
((
resData
)
=>
{
nextTick
(()
=>
{
if
(
resData
.
formUrl
)
{
formUrl
.
value
=
resData
.
formUrl
if
(
resData
.
formUrl
)
{
formUrl
.
value
=
resData
.
formUrl
;
}
else
{
formUrl
.
value
=
""
refInnerForm
.
value
.
iniData
(
resData
)
formUrl
.
value
=
''
;
refInnerForm
.
value
.
iniData
(
resData
)
;
}
})
})
})
;
})
;
if
(
taskForm
.
taskId
)
{
await
findFlowFormVal
({
taskId
:
taskForm
.
taskId
}).
then
((
resValues
)
=>
{
if
(
taskForm
.
taskId
)
{
await
findFlowFormVal
({
taskId
:
taskForm
.
taskId
}).
then
((
resValues
)
=>
{
nextTick
(()
=>
{
refInnerForm
.
value
.
setFormData
(
resValues
)
})
})
refInnerForm
.
value
.
setFormData
(
resValues
)
;
})
;
})
;
}
setFlowRecordList
(
taskForm
.
procInsId
,
taskForm
.
deployId
)
}
const
showNodeFormData
=
(
data
)
=>
{
openModal
(
true
,
{
setFlowRecordList
(
taskForm
.
procInsId
,
taskForm
.
deployId
);
};
const
showNodeFormData
=
(
data
)
=>
{
// Build workflowNodes list for the drawer. Adjust component paths as needed.
const
nodes
=
[
{
id
:
'stplanman'
,
name
:
'主表单'
,
formUrl
:
'/views/project/plan/components/StPlanManForm.vue'
},
{
id
:
'stplanexcute'
,
name
:
'执行表单'
,
formUrl
:
'/views/project/plan/components/StPlanExcuteForm.vue'
},
];
// pick which node to show — customize the rule as necessary
const
currentIndex
=
(
data
?.
taskName
||
''
).
includes
(
'执行'
)
?
1
:
0
;
// externalFormData: map node id -> form data object
const
externalFormData
=
{
[
nodes
[
currentIndex
].
id
]:
data
?.
data
||
{},
};
showFormModalApi
.
openModal
(
true
,
{
workflowNodes
:
nodes
,
currentNodeIndex
:
currentIndex
,
externalFormData
,
title
:
data
?.
taskName
||
'表单'
,
showFooter
:
true
,
data
});
}
};
defineExpose
({
iniData
,
})
// Handle submit event emitted from ShowFormModal
const
handleShowFormSubmit
=
(
payload
)
=>
{
console
.
log
(
'ShowFormModal submit payload:'
,
payload
);
// payload contains: { nodeId, nodeName, formData, procDefId, formComponent }
// Add your handling logic here (e.g., call API, close modal, refresh list)
};
defineExpose
({
iniData
,
});
</
script
>
<
style
lang=
"scss"
scoped
>
.clearfix
:before
,
.clearfix
:after
{
.clearfix
:before
,
.clearfix
:after
{
display
:
table
;
content
:
""
;
}
.clearfix
:after
{
clear
:
both
}
content
:
''
;
}
.clearfix
:after
{
clear
:
both
;
}
.app-container
{
.app-container
{
height
:
calc
(
100vh
-
150px
);
margin
:
0px
;
padding
:
5px
;
}
}
.my-label
{
background
:
#E1F3D
8
;
}
.my-label
{
background
:
#e1f3d
8
;
}
.iframe-container
{
.iframe-container
{
height
:
calc
(
100vh
-
200px
);
width
:
100%
;
}
.responsive-iframe
{
}
.responsive-iframe
{
width
:
100%
;
height
:
100%
;
border
:
none
;
}
}
</
style
>
zrch-risk-client-39/src/views/flowable/task/todo/components/TodoIndex.vue
浏览文件 @
5a8e52f3
...
...
@@ -57,20 +57,20 @@
<div
class=
"content-wrapper"
>
<!-- 左侧主表单 -->
<div
class=
"main-form-section"
>
<a-card
title=
"审批表单"
:bordered=
"false"
class=
"form-card"
>
<
!-- <
a-card title="审批表单" :bordered="false" class="form-card">
<template #extra>
<a-button type="link" @click="refreshForm"> <ReloadOutlined /> 刷新 </a-button>
</
template
>
</template>
-->
<div
class=
"form-content
"
>
<div
class=
"form-card
"
>
<div
v-show=
"formTp == 1"
class=
"form-wrapper"
>
<FlowInnerForm
ref=
"refCruInnerForm"
:key=
"formKey"
style=
"width
: 100%"
/>
<FlowInnerForm
ref=
"refCruInnerForm"
:key=
"formKey"
style=
"width: 100%; height
: 100%"
/>
</div>
<div
v-show=
"formTp == 2"
class=
"iframe-container"
style=
"height: 470px
"
>
<div
v-show=
"formTp == 2"
class=
"form-wrapper
"
>
<iFrame
:key=
"formKey"
:src=
"formUrl"
class=
"responsive-iframe"
style=
"width: 100%; height: 100%"
/>
</div>
</div>
<
/a-card
>
<
!-- </a-card> --
>
</div>
<!-- 右侧审批栏 -->
...
...
@@ -220,7 +220,7 @@
// API
import
{
flowRecord
}
from
'/@/components/Process/api/finished'
;
import
{
flowXmlAndNode
}
from
'/@/components/Process/api/definition'
;
import
{
complete
,
flowTaskForm
,
getNextFlowNode
,
getMyTaskFlow
,
assign
,
assignRead
}
from
'/@/components/Process/api/todo'
;
import
{
complete
,
flowTaskForm
,
getNextFlowNode
,
getMyTaskFlow
,
assign
,
assignRead
}
from
'/@/components/Process/api/todo'
;
import
{
flowTaskInfo
}
from
'/@/components/Process/api/process'
;
// 组件
...
...
@@ -765,7 +765,6 @@
const
dataName
=
formUrl
.
value
.
substring
(
startIndex
+
1
,
lastEqualIndex
);
submitData
.
values
[
'dataName'
]
=
dataName
;
// 执行发送
const
result
=
await
assign
(
submitData
);
...
...
@@ -815,8 +814,6 @@
submitData
.
values
[
'approvalType'
]
=
'role'
;
}
// 执行发送
const
result
=
await
assignRead
(
submitData
);
...
...
@@ -835,8 +832,6 @@
}
};
defineExpose
({
iniData
,
});
...
...
@@ -868,7 +863,7 @@
height
:
100vh
;
margin
:
0
;
padding
:
0
;
background
:
linear-gradient
(
135deg
,
#b0b3c2
0%
,
#764ba2
100%
);
//
background: linear-gradient(135deg, #b0b3c2 0%, #764ba2 100%);
overflow
:
hidden
;
}
...
...
@@ -945,6 +940,7 @@
}
.next-node-label
{
width
:
120px
;
color
:
#666
;
font-size
:
14px
;
}
...
...
zrch-risk-client-39/src/views/flowable/task/todo/index.vue
浏览文件 @
5a8e52f3
<
template
>
<div
class=
"app-container"
>
<vxe-grid
ref=
"xGrid"
v-bind=
"gridOptions"
@
checkbox-change=
"onSelectChange"
@
checkbox-all=
"onSelectChange"
>
<vxe-grid
ref=
"xGrid"
v-bind=
"gridOptions"
@
checkbox-change=
"onSelectChange"
@
checkbox-all=
"onSelectChange"
>
<!-- 搜索表单插槽 -->
<template
#
flowNameItem=
"
{ data }">
<vxe-input
v-model=
"data.procDefName"
placeholder=
"请输入流程名称"
clearable
@
keyup
.
enter=
"searchEvent"
></vxe-input>
...
...
@@ -35,12 +30,7 @@
</
template
>
<
template
#
action_default=
"{ row }"
>
<vxe-button
type=
"text"
icon=
"vxe-icon-edit"
status=
"primary"
@
click=
"handleProcess(row)"
>
处理
</vxe-button>
<vxe-button
type=
"text"
icon=
"vxe-icon-edit"
status=
"primary"
@
click=
"handleProcess(row)"
>
处理
</vxe-button>
</
template
>
</vxe-grid>
<div
v-if=
"isShowDrawer"
>
...
...
@@ -53,7 +43,7 @@
title=
"待办任务"
placement=
"right"
width=
"90%"
style=
"margin: 0px;
padding: 0px;
"
style=
"margin: 0px;
padding: 0px
"
>
<
template
#
extra
>
<div
style=
"float: right"
>
...
...
@@ -61,108 +51,108 @@
<a-tag>
任务节点:
{{
taskName
}}
</a-tag>
</div>
</
template
>
<TodoIndex
v-if=
"isShowDrawer"
ref=
"refTodoIndex"
@
callback=
"handleSuccess"
/>
<TodoIndex
v-if=
"isShowDrawer"
ref=
"refTodoIndex"
@
callback=
"handleSuccess"
/>
</a-drawer>
</div>
</div>
</template>
<
script
lang=
"ts"
setup
>
import
{
reactive
,
ref
,
onMounted
,
nextTick
}
from
'vue'
import
{
message
}
from
'ant-design-vue'
import
type
{
VxeGridProps
,
VxeGridInstance
}
from
'vxe-table'
import
{
todoList
,
delDeployment
}
from
'/@/components/Process/api/todo'
import
XEUtils
from
'xe-utils'
import
TodoIndex
from
'./components/TodoIndex.vue'
const
loading
=
ref
(
false
)
const
isShowDrawer
=
ref
(
false
)
const
refTodoIndex
=
ref
()
const
startUser
=
ref
()
const
taskName
=
ref
()
interface
QueryParams
{
pageNum
:
number
pageSize
:
number
procDefName
?:
string
taskName
?:
string
startTime
?:
string
}
const
queryParams
=
reactive
<
QueryParams
>
({
import
{
reactive
,
ref
,
onMounted
,
nextTick
}
from
'vue'
;
import
{
message
}
from
'ant-design-vue'
;
import
type
{
VxeGridProps
,
VxeGridInstance
}
from
'vxe-table'
;
import
{
todoList
,
delDeployment
}
from
'/@/components/Process/api/todo'
;
import
XEUtils
from
'xe-utils'
;
import
TodoIndex
from
'./components/TodoIndex.vue'
;
const
loading
=
ref
(
false
);
const
isShowDrawer
=
ref
(
false
);
const
refTodoIndex
=
ref
();
const
startUser
=
ref
();
const
taskName
=
ref
();
interface
QueryParams
{
pageNum
:
number
;
pageSize
:
number
;
procDefName
?:
string
;
taskName
?:
string
;
startTime
?:
string
;
}
const
queryParams
=
reactive
<
QueryParams
>
({
pageNum
:
1
,
pageSize
:
10
,
procDefName
:
undefined
,
taskName
:
undefined
,
startTime
:
undefined
,
})
interface
TodoItem
{
taskId
:
string
procDefName
:
string
taskName
:
string
procDefVersion
:
number
startUserName
:
string
startDeptName
:
string
createTime
:
string
procInsId
:
string
executionId
:
string
deployId
:
string
}
const
defaultData
=
reactive
({
});
interface
TodoItem
{
taskId
:
string
;
procDefName
:
string
;
taskName
:
string
;
procDefVersion
:
number
;
startUserName
:
string
;
startDeptName
:
string
;
createTime
:
string
;
procInsId
:
string
;
executionId
:
string
;
deployId
:
string
;
}
const
defaultData
=
reactive
({
procDefName
:
''
,
taskName
:
''
,
startTime
:
''
})
startTime
:
''
,
});
const
selectedRowKeys
=
ref
<
string
[]
>
([])
const
selectRecords
=
ref
<
TodoItem
[]
>
([])
const
multiple
=
ref
(
true
)
const
selectedRowKeys
=
ref
<
string
[]
>
([]);
const
selectRecords
=
ref
<
TodoItem
[]
>
([]);
const
multiple
=
ref
(
true
);
const
xGrid
=
ref
<
VxeGridInstance
>
()
const
xGrid
=
ref
<
VxeGridInstance
>
();
const
gridOptions
=
reactive
<
VxeGridProps
<
any
>>
({
const
gridOptions
=
reactive
<
VxeGridProps
<
any
>>
({
loading
:
loading
.
value
,
showOverflow
:
true
,
border
:
true
,
rowConfig
:
{
keyField
:
'taskId'
,
isHover
:
true
isHover
:
true
,
},
columnConfig
:
{
resizable
:
true
resizable
:
true
,
},
pagerConfig
:
{
enabled
:
true
,
pageSize
:
10
,
pageSizes
:
[
10
,
20
,
50
,
100
],
layouts
:
[
'PrevJump'
,
'PrevPage'
,
'Number'
,
'NextPage'
,
'NextJump'
,
'Sizes'
,
'FullJump'
,
'Total'
]
layouts
:
[
'PrevJump'
,
'PrevPage'
,
'Number'
,
'NextPage'
,
'NextJump'
,
'Sizes'
,
'FullJump'
,
'Total'
],
},
checkboxConfig
:
{
highlight
:
true
,
range
:
true
range
:
true
,
},
layouts
:
[
'Top'
,
'Form'
,
'Toolbar'
,
'Table'
,
'Bottom'
,
'Pager'
],
layouts
:
[
'Top'
,
'Form'
,
'Toolbar'
,
'Table'
,
'Bottom'
,
'Pager'
],
formConfig
:
{
data
:
XEUtils
.
clone
(
defaultData
,
true
),
items
:
[
{
field
:
'procDefName'
,
title
:
'流程名称'
,
span
:
6
,
itemRender
:
{},
slots
:
{
default
:
'flowNameItem'
}
},
{
field
:
'taskName'
,
title
:
'任务名称'
,
span
:
6
,
itemRender
:
{},
slots
:
{
default
:
'taskNameItem'
}
},
{
field
:
'startTime'
,
title
:
'开始时间'
,
span
:
6
,
itemRender
:
{},
slots
:
{
default
:
'startTimeItem'
}
},
{
span
:
6
,
align
:
'center'
,
itemRender
:
{},
slots
:
{
default
:
'actionItem'
}
}
]
{
span
:
6
,
align
:
'center'
,
itemRender
:
{},
slots
:
{
default
:
'actionItem'
}
},
],
},
proxyConfig
:
{
response
:
{
result
:
'result'
,
total
:
'page.total'
total
:
'page.total'
,
},
ajax
:
{
query
:
({
page
})
=>
{
return
findPageList
(
page
.
currentPage
,
page
.
pageSize
)
}
}
return
findPageList
(
page
.
currentPage
,
page
.
pageSize
);
},
},
},
columns
:
[
{
type
:
'checkbox'
,
width
:
60
,
fixed
:
'left'
},
...
...
@@ -179,162 +169,157 @@ const gridOptions = reactive<VxeGridProps<any>>({
width
:
120
,
fixed
:
'right'
,
align
:
'center'
,
slots
:
{
default
:
'action_default'
}
}
]
})
slots
:
{
default
:
'action_default'
},
},
],
});
const
findPageList
=
async
(
currentPage
:
number
,
pageSize
:
number
)
=>
{
queryParams
.
pageNum
=
currentPage
queryParams
.
pageSize
=
pageSize
const
findPageList
=
async
(
currentPage
:
number
,
pageSize
:
number
)
=>
{
queryParams
.
pageNum
=
currentPage
;
queryParams
.
pageSize
=
pageSize
;
if
(
gridOptions
.
formConfig
?.
data
)
{
queryParams
.
procDefName
=
gridOptions
.
formConfig
.
data
.
procDefName
queryParams
.
taskName
=
gridOptions
.
formConfig
.
data
.
taskName
queryParams
.
startTime
=
gridOptions
.
formConfig
.
data
.
startTime
queryParams
.
procDefName
=
gridOptions
.
formConfig
.
data
.
procDefName
;
queryParams
.
taskName
=
gridOptions
.
formConfig
.
data
.
taskName
;
queryParams
.
startTime
=
gridOptions
.
formConfig
.
data
.
startTime
;
}
try
{
loading
.
value
=
true
const
retData
=
await
todoList
(
queryParams
)
loading
.
value
=
true
;
const
retData
=
await
todoList
(
queryParams
);
return
{
page
:
{
total
:
retData
.
total
total
:
retData
.
total
,
},
result
:
retData
.
records
}
result
:
retData
.
records
,
};
}
catch
(
error
)
{
console
.
error
(
'查询数据失败:'
,
error
)
message
.
error
(
'查询数据失败'
)
console
.
error
(
'查询数据失败:'
,
error
);
message
.
error
(
'查询数据失败'
);
return
{
page
:
{
total
:
0
},
result
:
[]
}
result
:
[],
};
}
finally
{
loading
.
value
=
false
loading
.
value
=
false
;
}
}
};
const
searchEvent
=
async
()
=>
{
queryParams
.
pageNum
=
1
const
searchEvent
=
async
()
=>
{
queryParams
.
pageNum
=
1
;
if
(
xGrid
.
value
)
{
await
xGrid
.
value
.
commitProxy
(
'query'
)
await
xGrid
.
value
.
commitProxy
(
'query'
);
}
}
};
const
resetEvent
=
()
=>
{
const
resetEvent
=
()
=>
{
if
(
gridOptions
.
formConfig
)
{
gridOptions
.
formConfig
.
data
=
XEUtils
.
clone
(
defaultData
,
true
)
gridOptions
.
formConfig
.
data
=
XEUtils
.
clone
(
defaultData
,
true
);
}
searchEvent
()
}
searchEvent
();
};
const
onSelectChange
=
()
=>
{
const
onSelectChange
=
()
=>
{
if
(
xGrid
.
value
)
{
const
checkedRecords
=
xGrid
.
value
.
getCheckboxRecords
()
selectRecords
.
value
=
checkedRecords
selectedRowKeys
.
value
=
checkedRecords
.
map
(
item
=>
item
.
taskId
)
multiple
.
value
=
!
selectedRowKeys
.
value
.
length
const
checkedRecords
=
xGrid
.
value
.
getCheckboxRecords
();
selectRecords
.
value
=
checkedRecords
;
selectedRowKeys
.
value
=
checkedRecords
.
map
((
item
)
=>
item
.
taskId
);
multiple
.
value
=
!
selectedRowKeys
.
value
.
length
;
}
}
const
handleProcess
=
async
(
row
)
=>
{
isShowDrawer
.
value
=
true
startUser
.
value
=
row
.
startUserName
taskName
.
value
=
row
.
taskName
await
nextTick
(()
=>
{
if
(
refTodoIndex
.
value
)
{
refTodoIndex
.
value
.
iniData
(
row
)
};
const
handleProcess
=
async
(
row
)
=>
{
isShowDrawer
.
value
=
true
;
startUser
.
value
=
row
.
startUserName
;
taskName
.
value
=
row
.
taskName
;
await
nextTick
(()
=>
{
if
(
refTodoIndex
.
value
)
{
refTodoIndex
.
value
.
iniData
(
row
);
}
else
{
isShowDrawer
.
value
=
false
isShowDrawer
.
value
=
false
;
}
});
};
})
}
const
handleSuccess
=
async
()
=>
{
isShowDrawer
.
value
=
false
await
searchEvent
()
}
const
handleSuccess
=
async
()
=>
{
isShowDrawer
.
value
=
false
;
await
searchEvent
();
};
</
script
>
<
style
scoped
>
.app-container
{
.app-container
{
padding
:
16px
;
width
:
100%
;
height
:
100%
;
}
}
.user-info
{
.user-info
{
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
gap
:
8px
;
flex-wrap
:
nowrap
;
}
}
.user-name
{
.user-name
{
font-weight
:
500
;
white-space
:
nowrap
;
}
}
.dept-tag
{
.dept-tag
{
background
:
#f0f0f0
;
color
:
#666
;
padding
:
2px
6px
;
border-radius
:
4px
;
font-size
:
12px
;
white-space
:
nowrap
;
}
}
.version-tag
{
.version-tag
{
background
:
#1890ff
;
color
:
white
;
padding
:
2px
8px
;
border-radius
:
4px
;
font-size
:
12px
;
}
}
/* Vxe Grid 样式调整 */
:deep
(
.vxe-form--wrapper
)
{
/* Vxe Grid 样式调整 */
:deep
(
.vxe-form--wrapper
)
{
background
:
#fafafa
;
padding
:
16px
;
border-radius
:
4px
;
border
:
1px
solid
#e8e8e8
;
margin-bottom
:
16px
;
}
}
:deep
(
.vxe-form--item-title
)
{
:deep
(
.vxe-form--item-title
)
{
font-weight
:
500
;
color
:
#333
;
}
}
:deep
(
.vxe-grid--wrapper
)
{
:deep
(
.vxe-grid--wrapper
)
{
font-family
:
inherit
;
}
}
:deep
(
.vxe-grid--header
)
{
:deep
(
.vxe-grid--header
)
{
background-color
:
#fafafa
;
}
}
:deep
(
.vxe-grid--body
)
{
:deep
(
.vxe-grid--body
)
{
background-color
:
#fff
;
}
}
:deep
(
.vxe-cell
)
{
:deep
(
.vxe-cell
)
{
padding
:
8px
4px
;
}
}
:deep
(
.vxe-toolbar
)
{
:deep
(
.vxe-toolbar
)
{
background
:
transparent
;
padding
:
8px
0
;
margin-bottom
:
8px
;
}
}
:deep
(
.vxe-table--render-wrapper
)
{
:deep
(
.vxe-table--render-wrapper
)
{
border-radius
:
4px
;
}
}
</
style
>
zrch-risk-client-39/src/views/project/plan/StPlanManList.vue
浏览文件 @
5a8e52f3
<
template
>
<div
class=
"plan-management-page"
>
<!-- 页面头部区域 -->
<!--
<div
class=
"page-header"
>
<div
class=
"header-content"
>
<div
class=
"header-left"
>
<h1
class=
"page-title"
>
计划编制管理
</h1>
<p
class=
"page-desc"
>
统一管理和追踪所有业务计划的编制与审批流程
</p>
</div>
<div
class=
"header-stats"
>
<div
class=
"stat-item"
>
<span
class=
"stat-value"
>
--
</span>
<span
class=
"stat-label"
>
计划总数
</span>
</div>
<div
class=
"stat-item warning"
>
<span
class=
"stat-value"
>
--
</span>
<span
class=
"stat-label"
>
待处理
</span>
</div>
<div
class=
"stat-item success"
>
<span
class=
"stat-value"
>
--
</span>
<span
class=
"stat-label"
>
已完成
</span>
</div>
</div>
</div>
</div>
-->
<!-- 主内容区 -->
<div
class=
"main-content"
>
<!-- 搜索区域 -->
...
...
@@ -43,12 +19,12 @@
<JSearchSelect
placeholder=
"请选择类型"
v-model:value=
"queryParam['projectType']"
dict=
"projecttype"
/>
</a-form-item>
</a-col>
<a-col
:xl=
"
5
"
:lg=
"8"
:md=
"12"
:sm=
"24"
>
<a-col
:xl=
"
7
"
:lg=
"8"
:md=
"12"
:sm=
"24"
>
<a-form-item
label=
"执行部门"
>
<JSelectDept
placeholder=
"请选择执行部门"
v-model:value=
"queryParam['execDepCode']"
/>
</a-form-item>
</a-col>
<a-col
:xl=
"
4
"
:lg=
"8"
:md=
"12"
:sm=
"24"
>
<a-col
:xl=
"
5
"
:lg=
"8"
:md=
"12"
:sm=
"24"
>
<a-form-item
label=
"计划状态"
>
<a-select
v-model:value=
"queryParam['status']"
...
...
@@ -66,6 +42,8 @@
/>
</a-form-item>
</a-col>
</a-row>
<a-row
:gutter=
"16"
>
<a-col
:xl=
"5"
:lg=
"8"
:md=
"12"
:sm=
"24"
>
<a-form-item
label=
"计划日期"
>
<a-range-picker
...
...
@@ -76,8 +54,6 @@
/>
</a-form-item>
</a-col>
</a-row>
<a-row
:gutter=
"16"
>
<a-col
:xl=
"5"
:lg=
"8"
:md=
"12"
:sm=
"24"
>
<a-form-item
label=
"优先级"
>
<a-select
...
...
@@ -106,7 +82,7 @@
/>
</a-form-item>
</a-col>
<a-col
:xl=
"
14
"
:lg=
"16"
:md=
"24"
:sm=
"24"
>
<a-col
:xl=
"
7
"
:lg=
"16"
:md=
"24"
:sm=
"24"
>
<a-form-item
class=
"search-btn-group"
>
<a-space
:size=
"8"
>
<a-button
type=
"primary"
@
click=
"searchQuery"
>
查询
</a-button>
...
...
@@ -166,12 +142,12 @@
<!-- 待办抽屉 -->
<div
v-if=
"isShowDrawer"
>
<a-drawer
destroyOnClose
v-model:open=
"isShowDrawer"
class=
"flat-drawer"
title=
"待办任务"
placement=
"right"
width=
"90%"
>
<
template
#
extra
>
<
!-- <
template #extra>
<div class="drawer-tags">
<span class="tag">发起人: {{ startUser }}</span>
<span class="tag">任务节点: {{ taskName }}</span>
</div>
</
template
>
</template>
-->
<TodoIndex
v-if=
"isShowDrawer"
ref=
"refTodoIndex"
@
callback=
"handleSuccess"
/>
</a-drawer>
</div>
...
...
@@ -545,8 +521,8 @@
{
label
:
'待办'
,
ifShow
:
()
=>
{
console
.
log
(
"-------------record['uid'] "
,
record
[
'uid'
]);
console
.
log
(
"-------------userStore.getUserInfo.id "
,
userStore
.
getUserInfo
.
id
);
console
.
log
(
"-------------record['uid'] "
,
record
[
'uid'
]);
console
.
log
(
'-------------userStore.getUserInfo.id '
,
userStore
.
getUserInfo
.
id
);
if
(
record
[
'bpmStatus'
]
==
'2'
&&
record
[
'uid'
]
==
userStore
.
getUserInfo
.
id
)
return
true
;
else
return
false
;
},
...
...
zrch-risk-client-39/src/views/project/plan/components/StPlanExcuteForm.vue
浏览文件 @
5a8e52f3
...
...
@@ -73,7 +73,7 @@
</
template
>
<
script
setup
lang=
"ts"
>
import
{
ref
,
reactive
,
onMounted
,
watch
,
nextTick
}
from
'vue'
;
import
{
ref
,
reactive
,
onMounted
,
watch
,
nextTick
,
toRaw
}
from
'vue'
;
import
{
message
}
from
'ant-design-vue'
;
import
dayjs
from
'dayjs'
;
import
{
saveOrUpdate
}
from
'../StPlanMan.api'
;
...
...
@@ -107,6 +107,25 @@
attachments
:
[]
as
any
[],
});
// accept external formData prop from parent modal
const
props
=
defineProps
({
formData
:
{
type
:
Object
,
default
:
()
=>
({}),
},
});
// sync incoming prop into internal reactive formData
watch
(
()
=>
props
.
formData
,
(
v
)
=>
{
if
(
v
&&
Object
.
keys
(
v
).
length
>
0
)
{
Object
.
assign
(
formData
,
v
);
}
},
{
immediate
:
true
,
deep
:
true
}
);
// 监听formData变化,用于调试
watch
(
...
...
@@ -272,7 +291,8 @@
const
response
=
await
saveOrUpdate
(
submitData
,
true
);
if
(
response
)
{
message
.
success
(
'保存成功'
);
// message.success('保存成功');
console
.
log
(
'保存成功:'
);
// 更新缓存
planFormStore
.
updateFormDataCache
(
formData
);
console
.
log
(
response
);
...
...
@@ -355,6 +375,7 @@
resetForm
,
initFormData
,
isInitialized
,
getFormData
:
()
=>
toRaw
(
formData
),
});
</
script
>
...
...
@@ -489,10 +510,8 @@
/* ==================== 表单底部按钮 ==================== */
.form-footer {
padding: 14px 32px;
background: var(--color-bg-section);
border-top: 1px solid var(--color-border);
display: flex;
justify-content:
flex-end
;
justify-content:
center
;
}
/* ==================== 上传区域 ==================== */
...
...
zrch-risk-client-39/src/views/project/plan/components/StPlanManForm.vue
浏览文件 @
5a8e52f3
...
...
@@ -13,12 +13,7 @@
<template
#
planBasis=
"
{ model, field }">
<div
class=
"basis-container"
v-if=
"model[field]"
>
<div
v-if=
"isValidJson(model[field])"
class=
"basis-tags"
>
<a-tag
v-for=
"item in safeJsonParse(model[field])"
@
click=
"viewBasisDetail(item)"
:key=
"item.id"
class=
"basis-tag"
>
<a-tag
v-for=
"item in safeJsonParse(model[field])"
@
click=
"viewBasisDetail(item)"
:key=
"item.id"
class=
"basis-tag"
>
{{
item
.
name
}}
</a-tag>
</div>
...
...
@@ -46,7 +41,7 @@
<
script
lang=
"ts"
setup
>
import
{
BasicForm
,
useForm
}
from
'/@/components/Form/index'
;
import
{
computed
,
ref
,
onMounted
,
watchEffect
,
toRaw
}
from
'vue'
;
import
{
computed
,
ref
,
onMounted
,
watchEffect
,
toRaw
,
watch
}
from
'vue'
;
import
{
defHttp
}
from
'/@/utils/http/axios'
;
import
{
getBpmFormSchema
}
from
'../StPlanMan.data'
;
import
{
saveOrUpdate
}
from
'../StPlanMan.api'
;
...
...
@@ -79,6 +74,22 @@
baseColProps
:
{
span
:
24
},
});
// watch incoming prop and populate the form when provided
watch
(
()
=>
props
.
formData
,
(
v
)
=>
{
if
(
v
&&
Object
.
keys
(
v
).
length
>
0
)
{
formData
.
value
=
{
...
v
};
try
{
setFieldsValue
(
v
);
}
catch
(
e
)
{
console
.
warn
(
'setFieldsValue failed:'
,
e
);
}
}
},
{
immediate
:
true
,
deep
:
true
}
);
const
formDisabled
=
computed
(()
=>
{
return
props
.
formData
?.
disabled
!==
false
;
});
...
...
@@ -186,11 +197,19 @@
onMounted
(()
=>
{
initFormData
();
});
// expose getFormData so parent modal can read current values
defineExpose
({
submitForm
,
// resetForm,
initFormData
,
getFormData
:
()
=>
toRaw
(
formData
.
value
),
});
</
script
>
<
style
scoped
lang=
"less"
>
/* ==================== 柔和中性风格 - CSS 变量 ==================== */
.plan-form-container {
/* ==================== 柔和中性风格 - CSS 变量 ==================== */
.plan-form-container {
--color-primary: #3b5bdb;
--color-primary-hover: #364fc7;
--color-primary-light: #e8ecfd;
...
...
@@ -210,49 +229,49 @@
background: var(--color-bg-white);
min-height: 100vh;
font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif;
}
}
/* ==================== 表单头部 ==================== */
.form-header {
/* ==================== 表单头部 ==================== */
.form-header {
background: var(--color-bg-white);
border-bottom: 1px solid var(--color-border);
padding: 20px 32px;
border-left: 3px solid var(--color-primary);
padding-left: 28px;
}
}
.form-title {
.form-title {
font-size: 18px;
font-weight: 600;
color: var(--color-text-primary);
margin: 0 0 3px 0;
letter-spacing: -0.2px;
}
}
.form-subtitle {
.form-subtitle {
font-size: 13px;
color: var(--color-text-muted);
margin: 0;
}
}
/* ==================== 表单主体 ==================== */
.form-body {
/* ==================== 表单主体 ==================== */
.form-body {
padding: 24px 32px;
background: var(--color-bg-white);
}
}
/* 依据标签样式 */
.basis-container {
/* 依据标签样式 */
.basis-container {
padding: 8px 0;
}
}
.basis-tags {
.basis-tags {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
}
.basis-tag {
.basis-tag {
display: inline-flex;
align-items: center;
padding: 4px 10px;
...
...
@@ -267,43 +286,43 @@
&:hover {
background: #d0d9f8;
}
}
}
.basis-alert {
.basis-alert {
border-radius: var(--radius);
}
}
.basis-empty {
.basis-empty {
padding: 16px;
background: var(--color-bg-section);
border-radius: var(--radius);
border: 1px dashed var(--color-border-strong);
}
}
/* ==================== 表单底部按钮 ==================== */
.form-footer {
/* ==================== 表单底部按钮 ==================== */
.form-footer {
padding: 14px 32px;
background: var(--color-bg-section);
border-top: 1px solid var(--color-border);
display: flex;
justify-content: flex-end;
}
}
/* ==================== 表单控件样式覆盖 ==================== */
:deep(.ant-form-item) {
/* ==================== 表单控件样式覆盖 ==================== */
:deep(.ant-form-item) {
margin-bottom: 18px;
}
}
:deep(.ant-form-item-label > label) {
:deep(.ant-form-item-label > label) {
font-size: 13px;
font-weight: 500;
color: var(--color-text-secondary);
}
}
:deep(.ant-input),
:deep(.ant-select-selector),
:deep(.ant-picker),
:deep(.ant-input-textarea textarea) {
:deep(.ant-input),
:deep(.ant-select-selector),
:deep(.ant-picker),
:deep(.ant-input-textarea textarea) {
border-radius: var(--radius) !important;
border-color: var(--color-border) !important;
font-size: 13px;
...
...
@@ -318,15 +337,15 @@
border-color: var(--color-primary) !important;
box-shadow: 0 0 0 2px var(--color-primary-light) !important;
}
}
}
:deep(.ant-select-focused .ant-select-selector) {
:deep(.ant-select-focused .ant-select-selector) {
border-color: var(--color-primary) !important;
box-shadow: 0 0 0 2px var(--color-primary-light) !important;
}
}
/* ==================== 按钮样式 ==================== */
:deep(.ant-btn) {
/* ==================== 按钮样式 ==================== */
:deep(.ant-btn) {
border-radius: var(--radius);
font-weight: 500;
font-size: 13px;
...
...
@@ -355,15 +374,15 @@
background: var(--color-primary-light);
}
}
}
}
/* ==================== 加载状态 ==================== */
:deep(.ant-spin-container) {
/* ==================== 加载状态 ==================== */
:deep(.ant-spin-container) {
min-height: 400px;
}
}
/* ==================== 响应式设计 ==================== */
@media (max-width: 768px) {
/* ==================== 响应式设计 ==================== */
@media (max-width: 768px) {
.form-header {
padding: 16px 20px;
}
...
...
@@ -375,5 +394,5 @@
.form-footer {
padding: 12px 20px;
}
}
}
</
style
>
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论