Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
Z
zrch-risk-39
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
Administrator
zrch-risk-39
Commits
4996e66f
提交
4996e66f
authored
3月 27, 2026
作者:
kxjia
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
问题管理
上级
4fa74ba6
显示空白字符变更
内嵌
并排
正在显示
9 个修改的文件
包含
948 行增加
和
40 行删除
+948
-40
definition.js
zrch-risk-client-39/src/components/Process/api/definition.js
+1
-0
process.js
zrch-risk-client-39/src/components/Process/api/process.js
+0
-1
WorkFlowForm.vue
zrch-risk-client-39/src/views/common/WorkFlowForm.vue
+302
-0
WorkFlowFormDrawer.vue
zrch-risk-client-39/src/views/common/WorkFlowFormDrawer.vue
+504
-0
StProblemCheck.data.ts
...-39/src/views/project/problemCheck/StProblemCheck.data.ts
+3
-2
StProblemCheckList.vue
...-39/src/views/project/problemCheck/StProblemCheckList.vue
+9
-5
StProblemIndex.vue
...ient-39/src/views/project/problemCheck/StProblemIndex.vue
+126
-23
StProblemPlanList.vue
...t-39/src/views/project/problemCheck/StProblemPlanList.vue
+2
-8
StProblemCheckForm.vue
...ws/project/problemCheck/components/StProblemCheckForm.vue
+1
-1
没有找到文件。
zrch-risk-client-39/src/components/Process/api/definition.js
浏览文件 @
4996e66f
...
...
@@ -14,6 +14,7 @@ export const listDefinition = async (params) => {
// 部署流程实例
export
function
definitionStart
(
procDefId
,
data
)
{
alert
(
JSON
.
stringify
(
procDefId
))
return
defHttp
.
post
({
url
:
'/flowable/definition/startByProcDefId'
,
data
:
{
...
...
zrch-risk-client-39/src/components/Process/api/process.js
浏览文件 @
4996e66f
...
...
@@ -10,7 +10,6 @@ export function myProcessList(query) {
}
export
function
flowFormData
(
query
)
{
alert
(
JSON
.
stringify
(
query
))
return
defHttp
.
get
({
url
:
'/flowable/task/flowFormData'
,
params
:
query
...
...
zrch-risk-client-39/src/views/common/WorkFlowForm.vue
0 → 100644
浏览文件 @
4996e66f
<
template
>
<div
class=
"multi-form-preview"
>
<!-- 只读表单列表:前 N-1 个 -->
<div
v-for=
"(node, idx) in previousNodes"
:key=
"`readonly-$
{idx}`" class="form-readonly-item">
<div
class=
"form-header"
>
<span
class=
"form-name"
>
{{
node
.
name
}}
</span>
<a-tag
color=
"blue"
class=
"readonly-tag"
>
只读
</a-tag>
</div>
<div
class=
"form-content readonly"
>
<component
:is=
"loadComponent(node.formUrl)"
:disabled=
"true"
:readonly=
"true"
:form-data=
"formDataMap[node.id]"
:current-flow-node=
"node"
/>
</div>
</div>
<!-- 可编辑表单:第 N 个(当前节点) -->
<div
v-if=
"currentNode"
class=
"form-editable-item"
>
<div
class=
"form-header"
>
<span
class=
"form-name"
>
{{
currentNode
.
name
}}
</span>
<a-tag
color=
"green"
>
可编辑
</a-tag>
</div>
<div
class=
"form-content editable"
>
<component
:is=
"loadComponent(currentNode.formUrl)"
:disabled=
"false"
:readonly=
"false"
:form-data=
"currentFormData"
:current-flow-node=
"currentNode"
@
update:form-data=
"handleFormDataUpdate"
@
submit=
"handleSubmit"
/>
</div>
</div>
<!-- 加载错误提示 -->
<a-empty
v-if=
"!currentNode && previousNodes.length === 0"
description=
"未找到有效表单节点"
/>
</div>
</
template
>
<
script
lang=
"ts"
setup
>
import
{
ref
,
computed
,
onMounted
,
defineAsyncComponent
,
h
,
watch
}
from
'vue'
;
import
{
message
}
from
'ant-design-vue'
;
// 定义组件属性
const
props
=
defineProps
({
// 当前节点在 workflowNodes 中的索引(从 0 开始)
currentNodeIndex
:
{
type
:
Number
,
required
:
true
,
default
:
2
// 默认第三个(索引2)
},
// 工作流节点列表(从父组件传入)
workflowNodes
:
{
type
:
Array
as
()
=>
Array
<
any
>
,
required
:
true
,
default
:
()
=>
[]
},
// 外部传入的表单数据(用于回显)
externalFormData
:
{
type
:
Object
,
default
:
()
=>
({})
}
});
// 定义事件
const
emit
=
defineEmits
([
'form-data-update'
,
'submit'
]);
// 组件缓存
const
componentCache
=
new
Map
();
// 使用 import.meta.glob 预加载所有可能的组件
const
modules
=
import
.
meta
.
glob
(
'@/views/**/*.vue'
);
// 当前节点的表单数据(可编辑)
const
currentFormData
=
ref
<
any
>
({});
// 只读节点的表单数据映射(按节点id存储)
const
formDataMap
=
ref
<
Record
<
string
,
any
>>
({});
// 获取前 N 个节点(只读部分)
const
previousNodes
=
computed
(()
=>
{
if
(
!
props
.
workflowNodes
||
props
.
workflowNodes
.
length
===
0
)
return
[];
const
idx
=
props
.
currentNodeIndex
;
// 取索引小于 idx 的节点(即当前节点之前的所有节点)
return
props
.
workflowNodes
.
slice
(
0
,
idx
);
});
// 获取当前节点(第 N 个,可编辑)
const
currentNode
=
computed
(()
=>
{
if
(
!
props
.
workflowNodes
||
props
.
workflowNodes
.
length
===
0
)
return
null
;
const
idx
=
props
.
currentNodeIndex
;
if
(
idx
<
0
||
idx
>=
props
.
workflowNodes
.
length
)
return
null
;
return
props
.
workflowNodes
[
idx
];
});
// 将 URL 转换为正确的导入路径并动态加载组件
function
loadComponent
(
url
:
string
)
{
if
(
!
url
)
{
console
.
warn
(
'formUrl 为空'
);
return
createEmptyComponent
();
}
if
(
componentCache
.
has
(
url
))
{
return
componentCache
.
get
(
url
);
}
// 构建组件路径(使用 /@/ 格式)
let
componentPath
=
''
;
if
(
url
.
includes
(
'/views'
))
{
componentPath
=
`/src
${
url
}
`
;
}
else
{
componentPath
=
`/src/views
${
url
}
`
;
}
// 确保有文件后缀
if
(
!
componentPath
.
match
(
/
\.(
vue|js|ts|jsx|tsx
)
$/
))
{
componentPath
+=
'.vue'
;
}
console
.
log
(
'加载组件路径:'
,
componentPath
);
// 从预加载的 modules 中获取加载器
let
loader
=
modules
[
componentPath
];
if
(
!
loader
)
{
console
.
error
(
'未找到组件:'
,
componentPath
);
console
.
log
(
'可用路径示例:'
,
Object
.
keys
(
modules
).
slice
(
0
,
5
));
const
ErrorComponent
=
createErrorComponent
(
`组件未找到:
${
componentPath
}
`
);
componentCache
.
set
(
url
,
ErrorComponent
);
return
ErrorComponent
;
}
// 创建异步组件,并注入额外的 props(disabled/readonly 等)
const
AsyncComponent
=
defineAsyncComponent
({
loader
:
()
=>
loader
()
as
Promise
<
{
default
:
any
}
>
,
loadingComponent
:
{
render
:
()
=>
h
(
'div'
,
{
style
:
'text-align: center; padding: 20px;'
},
'加载中...'
)
},
errorComponent
:
{
render
:
()
=>
h
(
'div'
,
{
style
:
'color: red; padding: 20px;'
},
'组件加载失败,请刷新页面重试'
)
},
delay
:
200
,
timeout
:
3000
,
onError
(
error
)
{
console
.
error
(
'异步组件加载错误:'
,
error
);
}
});
componentCache
.
set
(
url
,
AsyncComponent
);
return
AsyncComponent
;
}
// 创建空组件(当 formUrl 为空时使用)
function
createEmptyComponent
()
{
return
{
render
:
()
=>
h
(
'div'
,
{
style
:
'color: #999; padding: 20px; text-align: center;'
},
'该节点未配置表单'
)
};
}
// 创建错误组件
function
createErrorComponent
(
msg
:
string
)
{
return
{
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
handleSubmit
(
data
:
any
)
{
emit
(
'submit'
,
{
nodeId
:
currentNode
.
value
?.
id
,
nodeName
:
currentNode
.
value
?.
name
,
formData
:
data
||
currentFormData
.
value
});
}
// 初始化只读节点的表单数据(从外部传入或模拟)
function
initReadonlyFormData
()
{
// 如果外部传入了表单数据,则按节点id映射
if
(
props
.
externalFormData
&&
Object
.
keys
(
props
.
externalFormData
).
length
>
0
)
{
// 假设 externalFormData 的结构为 { nodeId: formData, ... }
previousNodes
.
value
.
forEach
(
node
=>
{
if
(
props
.
externalFormData
[
node
.
id
])
{
formDataMap
.
value
[
node
.
id
]
=
props
.
externalFormData
[
node
.
id
];
}
else
{
// 如果没有传入,设置空对象
formDataMap
.
value
[
node
.
id
]
=
{};
}
});
}
else
{
// 初始化空数据
previousNodes
.
value
.
forEach
(
node
=>
{
formDataMap
.
value
[
node
.
id
]
=
{};
});
}
}
// 监听外部表单数据变化
watch
(()
=>
props
.
externalFormData
,
(
newData
)
=>
{
if
(
newData
&&
Object
.
keys
(
newData
).
length
>
0
)
{
previousNodes
.
value
.
forEach
(
node
=>
{
if
(
newData
[
node
.
id
])
{
formDataMap
.
value
[
node
.
id
]
=
newData
[
node
.
id
];
}
});
// 如果当前节点有数据,也更新
if
(
currentNode
.
value
&&
newData
[
currentNode
.
value
.
id
])
{
currentFormData
.
value
=
newData
[
currentNode
.
value
.
id
];
}
}
},
{
deep
:
true
,
immediate
:
true
});
// 组件挂载时初始化
onMounted
(()
=>
{
initReadonlyFormData
();
console
.
log
(
'MultiFormPreview 组件已挂载'
);
console
.
log
(
'当前节点索引:'
,
props
.
currentNodeIndex
);
console
.
log
(
'只读节点数量:'
,
previousNodes
.
value
.
length
);
console
.
log
(
'当前节点:'
,
currentNode
.
value
?.
name
);
});
</
script
>
<
style
scoped
lang=
"scss"
>
.multi-form-preview
{
width
:
100%
;
padding
:
16px
;
background-color
:
#f5f7fa
;
border-radius
:
8px
;
.form-readonly-item
,
.form-editable-item
{
margin-bottom
:
24px
;
background-color
:
#fff
;
border-radius
:
8px
;
overflow
:
hidden
;
box-shadow
:
0
1px
2px
rgba
(
0
,
0
,
0
,
0
.05
);
transition
:
box-shadow
0
.2s
;
&
:hover
{
box-shadow
:
0
2px
8px
rgba
(
0
,
0
,
0
,
0
.1
);
}
.form-header
{
display
:
flex
;
align-items
:
center
;
justify-content
:
space-between
;
padding
:
12px
16px
;
background-color
:
#fafbfc
;
border-bottom
:
1px
solid
#e8eef2
;
.form-name
{
font-size
:
15px
;
font-weight
:
500
;
color
:
#1f2f3d
;
}
.readonly-tag
,
.ant-tag
{
font-size
:
12px
;
}
}
.form-content
{
padding
:
20px
;
&
.readonly
{
background-color
:
#fefefe
;
// 只读模式下添加半透明遮罩效果,但仍保留交互(如果子组件支持disabled)
opacity
:
0
.95
;
}
&
.editable
{
background-color
:
#fff
;
}
}
}
.form-editable-item
{
border
:
1px
solid
#d9ecff
;
box-shadow
:
0
2px
8px
rgba
(
24
,
144
,
255
,
0
.08
);
.form-header
{
background-color
:
#e6f7ff
;
border-bottom-color
:
#bae7ff
;
.form-name
{
color
:
#096dd9
;
}
}
}
}
</
style
>
\ No newline at end of file
zrch-risk-client-39/src/views/common/WorkFlowFormDrawer.vue
0 → 100644
浏览文件 @
4996e66f
<
template
>
<a-drawer
:title=
"drawerTitle"
:visible=
"visible"
:width=
"drawerWidth"
:closable=
"true"
:mask-closable=
"maskClosable"
@
close=
"handleClose"
>
<!-- 选项卡模式 -->
<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"
>
<template
#
tab
>
<span>
{{
node
.
name
}}
<a-tag
color=
"blue"
size=
"small"
class=
"tab-tag"
>
只读
</a-tag>
</span>
</
template
>
<div
class=
"tab-content readonly-content"
>
<component
:is=
"getComponent(node.formUrl || node.formListUrl)"
:disabled=
"true"
:readonly=
"true"
:form-data=
"getFormData(node.id)"
:current-flow-node=
"node"
/>
</div>
</a-tab-pane>
<!-- 可编辑选项卡:索引等于 currentNodeIndex 的节点 -->
<a-tab-pane
v-if=
"editableNode"
:key=
"editableNode.id"
:tab=
"editableNode.name"
>
<
template
#
tab
>
<span>
{{
editableNode
.
name
}}
<a-tag
color=
"green"
size=
"small"
class=
"tab-tag"
>
可编辑
</a-tag>
</span>
</
template
>
<div
class=
"tab-content editable-content"
>
<component
:is=
"getComponent(editableNode.formUrl || editableNode.formListUrl)"
ref=
"editableFormRef"
:disabled=
"false"
:readonly=
"false"
:form-data=
"currentFormData"
:current-flow-node=
"editableNode"
@
update:form-data=
"handleFormDataUpdate"
/>
</div>
</a-tab-pane>
</a-tabs>
<!-- 空状态 -->
<div
v-if=
"!editableNode && readonlyNodes.length === 0"
class=
"empty-state"
>
<a-empty
description=
"未找到有效表单节点"
/>
</div>
<
template
#
footer
>
<div
class=
"drawer-footer"
>
<a-button
@
click=
"handleClose"
>
取消
</a-button>
<a-button
type=
"primary"
:loading=
"submitLoading"
@
click=
"handleSubmit"
>
提交
</a-button>
</div>
</
template
>
</a-drawer>
</template>
<
script
lang=
"ts"
setup
>
import
{
ref
,
computed
,
onMounted
,
defineAsyncComponent
,
h
,
watch
}
from
'vue'
import
{
message
}
from
'ant-design-vue'
interface
WorkflowNode
{
id
:
string
name
:
string
formUrl
?:
string
formListUrl
?:
string
procDefId
?:
string
[
key
:
string
]:
any
}
const
props
=
defineProps
({
visible
:
{
type
:
Boolean
,
default
:
false
},
title
:
{
type
:
String
,
default
:
'表单处理'
},
width
:
{
type
:
[
Number
,
String
],
default
:
720
},
maskClosable
:
{
type
:
Boolean
,
default
:
false
},
// 当前节点索引(从0开始),这个索引对应的节点是可编辑的
currentNodeIndex
:
{
type
:
Number
,
required
:
true
,
default
:
2
},
workflowNodes
:
{
type
:
Array
as
()
=>
WorkflowNode
[],
required
:
true
,
default
:
()
=>
[]
},
externalFormData
:
{
type
:
Object
as
()
=>
Record
<
string
,
any
>
,
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
editableFormRef
=
ref
()
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
[]
// 返回索引小于 idx 的节点
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
})
// 获取表单数据
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
()
}
if
(
componentCache
.
has
(
url
))
{
return
componentCache
.
get
(
url
)
}
let
componentPath
=
''
if
(
url
.
includes
(
'/views'
))
{
componentPath
=
`/src
${
url
}
`
}
else
{
componentPath
=
`/src/views
${
url
}
`
}
if
(
!
componentPath
.
match
(
/
\.(
vue|js|ts|jsx|tsx
)
$/
))
{
componentPath
+=
'.vue'
}
console
.
log
(
'加载组件路径:'
,
componentPath
)
const
loader
=
modules
[
componentPath
]
if
(
!
loader
)
{
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;'
},
'加载中...'
)
},
errorComponent
:
{
render
:
()
=>
h
(
'div'
,
{
style
:
'color: red; padding: 20px;'
},
'组件加载失败'
)
},
delay
:
200
,
timeout
:
3000
})
componentCache
.
set
(
url
,
AsyncComponent
)
return
AsyncComponent
}
function
createEmptyComponent
()
{
return
{
render
:
()
=>
h
(
'div'
,
{
style
:
'color: #999; padding: 20px; text-align: center;'
},
'该节点未配置表单'
)
}
}
function
createErrorComponent
(
msg
:
string
)
{
return
{
render
:
()
=>
h
(
'div'
,
{
style
:
'color: red; padding: 20px;'
},
msg
)
}
}
// 处理表单数据更新
function
handleFormDataUpdate
(
data
:
any
)
{
currentFormData
.
value
=
{
...
currentFormData
.
value
,
...
data
}
emit
(
'form-data-update'
,
currentFormData
.
value
)
}
// 提交处理
async
function
handleSubmit
()
{
if
(
!
editableNode
.
value
)
{
message
.
warning
(
'没有可编辑的表单'
)
return
}
if
(
editableFormRef
.
value
&&
editableFormRef
.
value
.
validate
)
{
try
{
await
editableFormRef
.
value
.
validate
()
}
catch
(
error
)
{
message
.
error
(
'请完善表单信息'
)
return
}
}
let
submitData
=
currentFormData
.
value
if
(
editableFormRef
.
value
&&
editableFormRef
.
value
.
getFormData
)
{
submitData
=
editableFormRef
.
value
.
getFormData
()
}
else
if
(
editableFormRef
.
value
&&
editableFormRef
.
value
.
formData
)
{
submitData
=
editableFormRef
.
value
.
formData
}
console
.
log
(
'提交数据:'
,
{
nodeId
:
editableNode
.
value
.
id
,
nodeName
:
editableNode
.
value
.
name
,
formData
:
submitData
,
procDefId
:
props
.
procDefId
})
emit
(
'submit'
,
{
nodeId
:
editableNode
.
value
.
id
,
nodeName
:
editableNode
.
value
.
name
,
formData
:
submitData
,
procDefId
:
props
.
procDefId
})
}
// 关闭抽屉
function
handleClose
()
{
emit
(
'update:visible'
,
false
)
emit
(
'close'
)
}
// 重置数据
function
resetFormData
()
{
currentFormData
.
value
=
{}
const
newFormDataMap
:
Record
<
string
,
any
>
=
{}
readonlyNodes
.
value
.
forEach
(
node
=>
{
newFormDataMap
[
node
.
id
]
=
props
.
externalFormData
[
node
.
id
]
||
{}
})
formDataMap
.
value
=
newFormDataMap
if
(
editableNode
.
value
&&
props
.
externalFormData
[
editableNode
.
value
.
id
])
{
currentFormData
.
value
=
{
...
props
.
externalFormData
[
editableNode
.
value
.
id
]
}
}
// 设置默认激活的选项卡为可编辑的选项卡
if
(
editableNode
.
value
)
{
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
)
}
}
// 预加载组件
function
preloadComponents
()
{
props
.
workflowNodes
.
forEach
(
node
=>
{
const
url
=
node
.
formUrl
||
node
.
formListUrl
if
(
url
)
{
getComponent
(
url
)
}
})
}
// 监听抽屉打开
watch
(()
=>
props
.
visible
,
(
newVal
)
=>
{
if
(
newVal
)
{
console
.
log
(
'抽屉打开,currentNodeIndex:'
,
props
.
currentNodeIndex
)
console
.
log
(
'所有节点:'
,
props
.
workflowNodes
)
resetFormData
()
preloadComponents
()
}
},
{
immediate
:
true
})
// 监听外部数据变化
watch
(()
=>
props
.
externalFormData
,
(
newData
)
=>
{
if
(
newData
&&
Object
.
keys
(
newData
).
length
>
0
)
{
console
.
log
(
'外部数据变化:'
,
newData
)
const
newFormDataMap
=
{
...
formDataMap
.
value
}
readonlyNodes
.
value
.
forEach
(
node
=>
{
if
(
newData
[
node
.
id
])
{
newFormDataMap
[
node
.
id
]
=
newData
[
node
.
id
]
}
})
formDataMap
.
value
=
newFormDataMap
if
(
editableNode
.
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
()
})
defineExpose
({
resetFormData
,
getFormData
:
()
=>
currentFormData
.
value
,
validate
:
async
()
=>
{
if
(
editableFormRef
.
value
&&
editableFormRef
.
value
.
validate
)
{
return
await
editableFormRef
.
value
.
validate
()
}
return
true
}
})
</
script
>
<
style
scoped
lang=
"scss"
>
.workflow-form-drawer
{
width
:
100%
;
height
:
100%
;
overflow-y
:
auto
;
.form-card
{
border-radius
:
8px
;
box-shadow
:
0
1px
2px
rgba
(
0
,
0
,
0
,
0
.05
);
:deep
(
.ant-card-body
)
{
padding
:
0
;
}
}
.form-tabs
{
:deep
(
.ant-tabs-nav
)
{
margin-bottom
:
0
;
background-color
:
#fafbfc
;
padding
:
0
16px
;
border-bottom
:
1px
solid
#e8eef2
;
}
:deep
(
.ant-tabs-tab
)
{
padding
:
12px
20px
;
font-weight
:
500
;
transition
:
all
0
.3s
;
&
:hover
{
color
:
#1890ff
;
}
}
:deep
(
.ant-tabs-tab-active
)
{
.ant-tabs-tab-btn
{
color
:
#1890ff
;
}
}
:deep
(
.ant-tabs-ink-bar
)
{
background
:
#1890ff
;
}
}
.tab-content
{
padding
:
24px
;
min-height
:
400px
;
background-color
:
#fff
;
&
.readonly-content
{
background-color
:
#f5f5f5
;
// 让只读内容区域内的所有表单输入框都显示为只读样式
:deep
(
input
),
:deep
(
textarea
),
:deep
(
.ant-input
),
:deep
(
.ant-select-selector
),
:deep
(
.ant-picker
)
{
background-color
:
#f5f5f5
!
important
;
cursor
:
not
-
allowed
!
important
;
color
:
#666
!
important
;
}
:deep
(
.ant-input-affix-wrapper
)
{
background-color
:
#f5f5f5
!
important
;
}
}
&
.editable-content
{
background-color
:
#fff
;
}
}
.tab-tag
{
margin-left
:
8px
;
font-size
:
12px
;
transform
:
scale
(
0
.9
);
display
:
inline-block
;
}
.empty-state
{
padding
:
60px
0
;
text-align
:
center
;
}
&
:
:-
webkit-scrollbar
{
width
:
6px
;
}
&
:
:-
webkit-scrollbar-track
{
background
:
#f1f1f1
;
border-radius
:
3px
;
}
&
:
:-
webkit-scrollbar-thumb
{
background
:
#c1c1c1
;
border-radius
:
3px
;
&
:hover
{
background
:
#a8a8a8
;
}
}
}
.drawer-footer
{
text-align
:
right
;
:deep
(
.ant-btn
)
{
margin-left
:
8px
;
&
:first-child
{
margin-left
:
0
;
}
}
}
:deep
(
.ant-drawer-body
)
{
padding
:
16px
;
background-color
:
#f5f7fa
;
}
:deep
(
.ant-drawer-footer
)
{
padding
:
12px
16px
;
border-top
:
1px
solid
#e8eef2
;
}
</
style
>
\ No newline at end of file
zrch-risk-client-39/src/views/project/problemCheck/StProblemCheck.data.ts
浏览文件 @
4996e66f
...
...
@@ -183,12 +183,13 @@ export const formSchema: FormSchema[] = [
{
label
:
'问题描述'
,
field
:
'problemDes'
,
component
:
'
InputTextArea
'
,
component
:
'
JEditor
'
,
required
:
true
,
componentProps
:
{
rows
:
4
,
showCount
:
true
,
maxlength
:
3000
,
maxlength
:
30000
,
height
:
300
,
},
},
{
...
...
zrch-risk-client-39/src/views/project/problemCheck/StProblemCheckList.vue
浏览文件 @
4996e66f
...
...
@@ -2,10 +2,8 @@
<div>
<BasicTable
@
register=
"registerTable"
:rowSelection=
"rowSelection"
>
<template
#
tableTitle
>
<a-button
type=
"primary"
@
click=
"handleAdd"
preIcon=
"ant-design:plus-outlined"
>
新增
</a-button>
<a-button
type=
"primary"
@
click=
"handleAdd"
preIcon=
"ant-design:plus-outlined"
>
添加问题
</a-button>
<a-button
type=
"primary"
preIcon=
"ant-design:export-outlined"
@
click=
"onExportXls"
>
导出
</a-button>
<j-upload-button
type=
"primary"
preIcon=
"ant-design:import-outlined"
@
click=
"onImportXls"
>
导入
</j-upload-button>
<a-dropdown
v-if=
"selectedRowKeys.length > 0"
>
<template
#
overlay
>
<a-menu>
...
...
@@ -55,6 +53,8 @@
}
})
const
emit
=
defineEmits
([
'callback'
])
//注册model
const
[
registerModal
,
{
openModal
}]
=
useModal
();
const
[
registerPlanModal
,
{
openModal
:
openPlanModal
}]
=
useModal
();
...
...
@@ -95,7 +95,7 @@
/**
* 新增事件
*/
function
handleAdd
()
{
function
handleAdd
333333
()
{
openModal
(
true
,
{
isUpdate
:
false
,
showFooter
:
true
,
...
...
@@ -106,6 +106,10 @@
}
});
}
function
handleAdd
()
{
emit
(
"callback"
,
null
)
}
/**
* 编辑事件
*/
...
...
@@ -162,7 +166,7 @@
onClick
:
handleEdit
.
bind
(
null
,
record
),
},
{
label
:
'
启动流程
'
,
label
:
'
发送任务
'
,
onClick
:
handleFlow
.
bind
(
null
,
record
),
},
...
...
zrch-risk-client-39/src/views/project/problemCheck/StProblemIndex.vue
浏览文件 @
4996e66f
...
...
@@ -4,34 +4,60 @@
<a-tab-pane
v-for=
"(node, index) in workflowNodes"
:key=
"index + 1"
:tab=
"node.name"
>
<div
v-if=
"node.formListUrl"
class=
"tab-content"
>
<component
:is=
"loadComponent(node.formListUrl)"
:beforeFlowNode=
"workflowNodes[index-1]"
:currentFlowNode=
"node"
:nextFlowNode=
"workflowNodes[index+1]"
/>
@
startWorkFlow=
"handleDefinitionStart"
:beforeFlowNode=
"workflowNodes[index-1]"
:currentFlowNode=
"node"
:nextFlowNode=
"workflowNodes[index+1]"
@
open-multi-form=
"handleOpenMultiForm"
@
callback=
"handleCallback"
/>
</div>
<div
v-else
class=
"no-form"
>
该节点未配置表单
</div>
</a-tab-pane>
</a-tabs>
<!-- 多表单抽屉组件 -->
<WorkFlowFormDrawer
v-model:visible=
"drawerVisible"
:title=
"drawerTitle"
:current-node-index=
"currentMultiFormIndex"
:workflow-nodes=
"workflowNodes"
:external-form-data=
"externalFormData"
:proc-def-id=
"currentProcDefId"
@
submit=
"handleMultiFormSubmit"
@
close=
"handleDrawerClose"
@
form-data-update=
"handleMultiFormDataUpdate"
width=
"50%"
/>
</div>
</
template
>
<
script
lang=
"ts"
name=
"problem-stProblemCheck"
setup
>
import
{
ref
,
nextTick
,
onMounted
,
defineAsyncComponent
,
h
}
from
'vue'
;
import
{
getNodesByTableName
}
from
'/@/components/Process/api/definition'
;
import
{
definitionStart
,
flowXmlAndNode
}
from
"/@/components/Process/api/definition"
;
import
WorkFlowFormDrawer
from
'/@/views/common/WorkFlowFormDrawer.vue'
;
const
workflowNodes
=
ref
<
any
[]
>
([]);
const
activeTab
=
ref
(
1
);
// 组件缓存,避免重复加载
const
componentCache
=
new
Map
();
// 抽屉相关状态
const
drawerVisible
=
ref
(
false
);
const
drawerTitle
=
ref
(
'表单处理'
);
const
currentMultiFormIndex
=
ref
(
0
);
const
currentProcDefId
=
ref
(
''
);
const
externalFormData
=
ref
<
Record
<
string
,
any
>>
({});
// 使用 import.meta.glob 预加载所有可能的组件,使用 /@/ 格式
const
componentCache
=
new
Map
();
const
modules
=
import
.
meta
.
glob
(
'@/views/**/*.vue'
);
function
handleTabChange
(
key
)
{
activeTab
.
value
=
key
;
currentMultiFormIndex
.
value
=
key
-
1
;
}
// 将URL转换为正确的导入路径并动态加载组件
function
loadComponent
(
url
:
string
)
{
console
.
log
(
'开始加载组件,URL:'
,
url
);
...
...
@@ -39,36 +65,22 @@
console
.
log
(
'从缓存加载组件:'
,
url
);
return
componentCache
.
get
(
url
);
}
// 构建使用 /@/ 格式的组件路径
let
componentPath
=
''
;
// 检查url是否已包含/views
if
(
url
.
includes
(
'/views'
))
{
// 如果已包含/views,直接使用 /@/ 前缀
componentPath
=
`/src
${
url
}
`
;
}
else
{
// 否则添加 /@/views 前缀
componentPath
=
`/src/views
${
url
}
`
;
}
// 检查是否已有文件后缀
if
(
!
componentPath
.
match
(
/
\.(
vue|js|ts|jsx|tsx
)
$/
))
{
// 如果没有文件后缀,添加.vue
componentPath
+=
'.vue'
;
}
console
.
log
(
'生成的组件路径:'
,
componentPath
);
console
.
log
(
'所有可用的组件路径示例:'
,
Object
.
keys
(
modules
).
slice
(
0
,
10
));
// 从预加载的 modules 中获取加载器
let
loader
=
modules
[
componentPath
];
if
(
!
loader
)
{
console
.
error
(
'未找到组件:'
,
componentPath
);
console
.
log
(
'包含 problemCheck 的路径:'
,
Object
.
keys
(
modules
).
filter
(
key
=>
key
.
includes
(
'problemCheck'
)));
// 返回错误组件
const
ErrorComponent
=
{
render
:
()
=>
h
(
'div'
,
{
style
:
'color: red; padding: 20px;'
},
`组件未找到:
${
componentPath
}
`
)
};
...
...
@@ -76,7 +88,6 @@
return
ErrorComponent
;
}
// 创建异步组件
const
AsyncComponent
=
defineAsyncComponent
({
loader
:
()
=>
loader
()
as
Promise
<
{
default
:
any
}
>
,
loadingComponent
:
{
...
...
@@ -91,11 +102,89 @@
console
.
error
(
'异步组件加载错误:'
,
error
);
}
});
componentCache
.
set
(
url
,
AsyncComponent
);
return
AsyncComponent
;
}
const
handleDefinitionStart
=
(
procDefId
:
string
,
submitData
:
any
)
=>
{
return
definitionStart
({
procDefId
,
variables
:
submitData
})
}
const
handleOpenMultiForm
=
(
params
:
{
nodeIndex
?:
number
;
title
?:
string
;
procDefId
?:
string
;
formData
?:
Record
<
string
,
any
>
;
})
=>
{
console
.
log
(
'打开多表单抽屉:'
,
params
);
if
(
params
.
nodeIndex
!==
undefined
)
{
currentMultiFormIndex
.
value
=
params
.
nodeIndex
;
}
else
{
currentMultiFormIndex
.
value
=
activeTab
.
value
-
1
;
}
if
(
params
.
title
)
{
drawerTitle
.
value
=
params
.
title
;
}
else
{
const
currentNode
=
workflowNodes
.
value
[
currentMultiFormIndex
.
value
];
drawerTitle
.
value
=
currentNode
?
`
${
currentNode
.
name
}
- 历史表单查看`
:
'表单处理'
;
}
if
(
params
.
procDefId
)
{
currentProcDefId
.
value
=
params
.
procDefId
;
}
else
if
(
workflowNodes
.
value
[
currentMultiFormIndex
.
value
])
{
currentProcDefId
.
value
=
workflowNodes
.
value
[
currentMultiFormIndex
.
value
].
procDefId
||
''
;
}
if
(
params
.
formData
)
{
externalFormData
.
value
=
params
.
formData
;
}
else
{
externalFormData
.
value
=
{};
}
drawerVisible
.
value
=
true
;
};
const
handleMultiFormSubmit
=
async
(
submitData
:
{
nodeId
:
string
;
nodeName
:
string
;
formData
:
any
;
procDefId
:
string
;
})
=>
{
console
.
log
(
'多表单提交数据:'
,
submitData
);
try
{
await
definitionStart
({
procDefId
:
submitData
.
procDefId
,
variables
:
submitData
.
formData
});
drawerVisible
.
value
=
false
;
const
currentTabKey
=
activeTab
.
value
;
const
currentComponent
=
loadComponent
(
workflowNodes
.
value
[
currentTabKey
-
1
]?.
formListUrl
);
}
catch
(
error
)
{
console
.
error
(
'提交失败:'
,
error
);
throw
error
;
}
};
const
handleDrawerClose
=
()
=>
{
drawerVisible
.
value
=
false
;
console
.
log
(
'抽屉关闭'
);
};
const
handleMultiFormDataUpdate
=
(
data
:
any
)
=>
{
console
.
log
(
'多表单数据更新:'
,
data
);
// 可以在这里实时保存数据到本地
};
const
openHistoryForms
=
(
nodeIndex
:
number
,
formData
?:
Record
<
string
,
any
>
)
=>
{
handleOpenMultiForm
({
nodeIndex
,
title
:
`查看历史表单 -
${
workflowNodes
.
value
[
nodeIndex
]?.
name
||
''
}
`,
formData
});
};
defineExpose({
openHistoryForms,
openMultiForm: handleOpenMultiForm
});
onMounted(async () => {
await nextTick();
try {
...
...
@@ -104,12 +193,10 @@
workflowNodes.value = nodes;
console.log('获取到的工作流节点:', workflowNodes.value);
// 打印每个节点的 formListUrl
workflowNodes.value.forEach((node, index) => {
console.log(`
节点
$
{
index
+
1
}:
`, node.name, 'formListUrl:', node.formListUrl);
});
// 预加载所有节点的组件
if (workflowNodes.value && workflowNodes.value.length > 0) {
console.log('开始预加载组件...');
workflowNodes.value.forEach(node => {
...
...
@@ -123,6 +210,22 @@
console.error('获取工作流节点失败:', error);
}
});
function handleCallback(data: any) {
drawerVisible.value = true;
const currentNode = workflowNodes.value[currentMultiFormIndex.value];
currentProcDefId.value = currentNode.procDefId || '';
const userid = currentNode.assignee || '';
const nodeId = currentNode.id
const deployId = currentNode.deployId || '';
const procDefId = currentNode.procDefId || '';
const attributes = currentNode.attributes || {};
const userType = attributes.userType || [];
if (userType.length > 0) {
data['userType'] = userType[0].value || '';
}
}
</
script
>
<
style
scoped
>
...
...
zrch-risk-client-39/src/views/project/problemCheck/StProblemPlanList.vue
浏览文件 @
4996e66f
...
...
@@ -25,6 +25,7 @@
import
{
list
}
from
'./StProblemCheck.api'
;
import
StProblemCheckExecuteModal
from
'./components/StProblemCheckExecuteModal.vue'
;
const
emit
=
defineEmits
([
'callback'
])
const
props
=
defineProps
({
beforeFlowNode
:
{
...
...
@@ -41,9 +42,7 @@
}
})
const
[
registerExecuteModal
,
{
openModal
:
openExecuteModal
}]
=
useModal
();
const
{
prefixCls
,
tableContext
}
=
useListPage
({
tableProps
:
{
title
:
'问题整改计划'
,
...
...
@@ -71,12 +70,7 @@
const
[
registerTable
,
{
reload
},
{
rowSelection
,
selectedRowKeys
}]
=
tableContext
;
function
handlePlan
(
record
:
Recordable
)
{
openExecuteModal
(
true
,
{
record
,
isUpdate
:
true
,
showFooter
:
true
,
nextFlowNode
:
props
.
nextFlowNode
,
});
emit
(
"callback"
,
record
)
}
function
handleSuccess
()
{
...
...
zrch-risk-client-39/src/views/project/problemCheck/components/StProblemCheckForm.vue
浏览文件 @
4996e66f
...
...
@@ -41,7 +41,6 @@
let
formData
=
{};
const
queryByIdUrl
=
'/problem/stProblemCheck/queryById/'
;
alert
(
props
.
formData
.
dataId
)
async
function
initFormData
()
{
let
params
=
{
id
:
props
.
formData
.
dataId
};
const
data
=
await
defHttp
.
get
({
url
:
queryByIdUrl
,
params
});
...
...
@@ -53,6 +52,7 @@
}
async
function
submitForm
()
{
alert
(
888
)
let
data
=
getFieldsValue
();
let
params
=
Object
.
assign
({},
formData
,
data
);
console
.
log
(
'表单数据'
,
params
);
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论