Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
Z
zrch-risk-39
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
Administrator
zrch-risk-39
Commits
401f07d4
提交
401f07d4
authored
4月 29, 2026
作者:
whydesc
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
--待阅处理
上级
517441ba
隐藏空白字符变更
内嵌
并排
正在显示
5 个修改的文件
包含
1313 行增加
和
8 行删除
+1313
-8
TodoReadIndex.vue
...src/views/flowable/task/todo/components/TodoReadIndex.vue
+1301
-0
todoReadindex.vue
...-client-39/src/views/flowable/task/todo/todoReadindex.vue
+1
-1
MyTaskFlowCcList.vue
...isk-client-39/src/views/mytaskflowcc/MyTaskFlowCcList.vue
+2
-2
FlowInstanceServiceImpl.java
...odules/flowable/service/impl/FlowInstanceServiceImpl.java
+7
-5
MyTaskFlowCcController.java
...ecg/modules/stm/my/controller/MyTaskFlowCcController.java
+2
-0
没有找到文件。
zrch-risk-client-39/src/views/flowable/task/todo/components/TodoReadIndex.vue
0 → 100644
浏览文件 @
401f07d4
<
template
>
<div
class=
"app-container"
>
<a-card
class=
"box-card"
:body-style=
"
{ padding: '0' }">
<a-tabs
v-model:activeKey=
"activeName"
@
tab-click=
"handleTabClick"
:tab-bar-style=
"
{ margin: '0 24px', paddingTop: '8px' }"
class="process-tabs"
>
<!-- 当前表单标签页 -->
<a-tab-pane
key=
"1"
tab=
"当前表单"
:force-render=
"true"
>
<div
class=
"form-container"
>
<!-- 顶部操作栏 -->
<div
class=
"action-header"
>
<!--
<div
class=
"action-left"
>
<a-space>
<a-button
type=
"primary"
@
click=
"handleReject"
:loading=
"rejecting"
>
<template
#
icon
><CloseCircleOutlined
/></
template
>
驳回
</a-button>
<a-button
type=
"primary"
@
click=
"handleAssignTask"
:loading=
"assigning"
>
<
template
#
icon
><CloseCircleOutlined
/></
template
>
转办
</a-button>
<a-button
type=
"primary"
@
click=
"handleAssignReadTask"
:loading=
"assiReadgning"
>
<
template
#
icon
><CloseCircleOutlined
/></
template
>
转阅
</a-button>
</a-space>
</div>
<div
class=
"action-right"
>
<div
class=
"next-node-info"
>
<span
class=
"next-node-label"
>
下一节点:
</span>
<a-select
v-model:value=
"nextNodeNameSele"
placeholder=
"请选择下一个节点"
style=
"width: 100%"
@
change=
"handleChange"
v-if=
"shownextNodeNameSele"
>
<a-select-option
v-for=
"item in tableOptions"
:key=
"item.id"
:value=
"item.value"
>
{{ item.name }}
</a-select-option>
</a-select>
<a-tag
color=
"blue"
class=
"next-node-tag"
v-if=
"shownextNodeNametext"
>
{{ nextNodeName || '等待确定下一节点' }}
</a-tag>
</div>
</div>
-->
</div>
<div
class=
"content-wrapper"
>
<!-- 左侧主表单 -->
<div
class=
"main-form-section"
>
<!-- <a-card title="审批表单" :bordered="false" class="form-card">
<template #extra>
<a-button type="link" @click="refreshForm"> <ReloadOutlined /> 刷新 </a-button>
</template> -->
<div
class=
"form-card"
>
<div
v-show=
"formTp == 1"
class=
"form-wrapper"
>
<FlowInnerForm
ref=
"refCruInnerForm"
:key=
"formKey"
style=
"width: 100%; height: 100%"
/>
</div>
<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> -->
</div>
<!-- 右侧审批栏
<div class="sidebar-section" v-if="showApprovalUi">
<a-card :title="approvalTitle" :bordered="false" class="approval-card">
<BasicForm @register="registerForm" style="width: 100%" />
<div class="form-footer">
<a-space :size="12">
<a-button @click="handleSendTask" type="primary">提交</a-button>
</a-space>
</div>
</a-card>
</div>
-->
</div>
</div>
</a-tab-pane>
<!-- 流程流转记录标签页 -->
<a-tab-pane
key=
"2"
tab=
"流转记录"
>
<div
class=
"record-container"
>
<a-card
:bordered=
"false"
class=
"record-card"
>
<
template
#
title
>
<div
class=
"record-title"
>
<HistoryOutlined
/>
<span
style=
"margin-left: 8px"
>
流程流转记录
</span>
</div>
</
template
>
<div
v-if=
"loadingFlowRecord"
class=
"loading-state"
>
<a-spin
tip=
"加载流转记录中..."
/>
</div>
<div
v-else-if=
"flowRecordList.length === 0"
class=
"empty-state"
>
<a-empty
description=
"暂无流转记录"
/>
</div>
<a-timeline
v-else
class=
"flow-timeline"
>
<a-timeline-item
v-for=
"(item, index) in flowRecordList"
:key=
"index"
:color=
"getTimelineColor(item.finishTime)"
>
<div
class=
"timeline-item"
>
<div
class=
"timeline-header"
>
<div
class=
"task-name"
style=
"margin: 5px 0px"
>
<a-tag
:color=
"getTaskStatusColor(item.finishTime)"
class=
"status-tag"
>
{{ item.finishTime ? '已完成' : '进行中' }}
</a-tag>
<span
class=
"task-title"
>
{{ item.taskName }}
</span>
</div>
<div
class=
"task-time"
>
<ClockCircleOutlined
/>
<span>
{{ formatDuration(item.duration) }}
</span>
</div>
</div>
<div
class=
"timeline-content"
>
<a-descriptions
size=
"small"
:column=
"1"
bordered
>
<a-descriptions-item
label=
"办理人"
v-if=
"item.assigneeName"
>
<UserOutlined
class=
"desc-icon"
/>
{{ item.assigneeName }}
<a-tag
v-if=
"item.deptName"
color=
"default"
size=
"small"
>
{{ item.deptName }}
</a-tag>
</a-descriptions-item>
<a-descriptions-item
label=
"候选办理"
v-if=
"item.candidate"
>
<TeamOutlined
class=
"desc-icon"
/>
{{ item.candidate }}
</a-descriptions-item>
<a-descriptions-item
label=
"接收时间"
>
<CalendarOutlined
class=
"desc-icon"
/>
{{ formatTime(item.createTime) }}
</a-descriptions-item>
<a-descriptions-item
label=
"处理时间"
v-if=
"item.finishTime"
>
<CheckCircleOutlined
class=
"desc-icon"
/>
{{ formatTime(item.finishTime) }}
</a-descriptions-item>
<a-descriptions-item
label=
"处理意见"
v-if=
"item.comment?.comment"
>
<FormOutlined
class=
"desc-icon"
/>
<div
class=
"comment-box"
>
{{ item.comment?.comment }}
</div>
</a-descriptions-item>
</a-descriptions>
</div>
</div>
</a-timeline-item>
</a-timeline>
</a-card>
</div>
</a-tab-pane>
<!-- 流程图标签页 -->
<a-tab-pane
key=
"3"
tab=
"流程图"
>
<div
class=
"flowchart-container"
>
<a-card
:bordered=
"false"
class=
"flowchart-card"
:body-style=
"{ padding: '0', height: '100%', overflow: true }"
>
<
template
#
title
>
<div
class=
"flowchart-title"
>
<DeploymentUnitOutlined
/>
<span
style=
"margin-left: 8px"
>
流程图
</span>
</div>
</
template
>
<div
class=
"bpmn-wrapper"
>
<div
v-if=
"loadingFlowChart"
class=
"loading-state"
>
<a-spin
tip=
"加载流程图中..."
size=
"large"
/>
</div>
<div
class=
"bpmn-content"
>
<bpmn-viewer
:flowData=
"flowData"
:procInsId=
"taskForm.procInsId"
@
loaded=
"onFlowChartLoaded"
/>
</div>
</div>
</a-card>
</div>
</a-tab-pane>
</a-tabs>
</a-card>
<!-- 弹窗组件 -->
<Approve
@
register=
"registerApprove"
ref=
"refApprove"
/>
<Reject
@
register=
"registerReject"
ref=
"refReject"
/>
<Assign
@
register=
"registerAssign"
ref=
"refAssign"
/>
<AssignRead
@
register=
"registerAssignRead"
ref=
"refAssignRead"
/>
</div>
</template>
<
script
lang=
"ts"
setup
>
import
{
ref
,
reactive
,
nextTick
,
computed
,
watch
}
from
'vue'
;
import
{
message
}
from
'ant-design-vue'
;
import
{
UserOutlined
,
CalendarOutlined
,
ClockCircleOutlined
,
FormOutlined
,
SendOutlined
,
CloseCircleOutlined
,
ReloadOutlined
,
HistoryOutlined
,
TeamOutlined
,
CheckCircleOutlined
,
DeploymentUnitOutlined
,
}
from
'@ant-design/icons-vue'
;
// 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
{
flowTaskInfo
}
from
'/@/components/Process/api/process'
;
// 组件
import
BpmnViewer
from
'/@/components/Process/viewer/index.vue'
;
import
FlowInnerForm
from
'/@/views/flowable/task/components/FlowInnerForm.vue'
;
import
Approve
from
'./Approve.vue'
;
import
Reject
from
'./Reject.vue'
;
import
Assign
from
'./Assign.vue'
;
import
AssignRead
from
'./AssignRead.vue'
;
// 工具
import
{
useForm
,
BasicForm
}
from
'/@/components/Form'
;
import
{
useModal
}
from
'/@/components/Modal'
;
import
dayjs
from
'dayjs'
;
// 响应式数据
const
activeName
=
ref
(
'1'
);
const
sending
=
ref
(
false
);
const
rejecting
=
ref
(
false
);
const
formLoading
=
ref
(
false
);
const
formError
=
ref
(
false
);
const
loadingFlowRecord
=
ref
(
false
);
const
loadingFlowChart
=
ref
(
false
);
const
formKey
=
ref
(
0
);
const
showApprovalUi
=
ref
(
true
);
const
flowData
=
ref
<
any
>
({});
const
flowRecordList
=
ref
<
any
[]
>
([]);
const
nextNodeName
=
ref
(
''
);
const
nextNode
=
ref
<
any
>
(
null
);
const
nextNodenum
=
ref
(
0
);
const
tableOptions
=
ref
([]);
const
nextNodeNameSele
=
ref
(
''
);
const
nextNodeNameSelevue
=
ref
(
0
);
const
shownextNodeNameSele
=
ref
(
true
);
const
shownextNodeNametext
=
ref
(
false
);
const
res0
=
ref
();
const
res1
=
ref
();
const
taskForm
=
reactive
({
returnTaskShow
:
false
,
delegateTaskShow
:
false
,
defaultTaskShow
:
true
,
comment
:
''
,
procInsId
:
''
,
instanceId
:
''
,
deployId
:
''
,
taskId
:
''
,
procDefId
:
''
,
targetKey
:
''
,
values
:
{},
});
const
workFlowData
=
ref
<
any
>
({});
const
refCruInnerForm
=
ref
<
any
>
(
null
);
const
isApproval
=
ref
(
false
);
const
formUrl
=
ref
(
''
);
const
formTp
=
ref
<
any
>
();
const
approvalTitle
=
ref
(
'填写审批信息'
);
// 弹窗
const
refApprove
=
ref
(
null
);
const
refReject
=
ref
(
null
);
const
refAssign
=
ref
(
null
);
const
refAssignRead
=
ref
(
null
);
const
[
registerApprove
,
{
openModal
:
openApproveModal
}]
=
useModal
();
const
[
registerReject
,
{
openModal
:
openRejectModal
}]
=
useModal
();
const
[
registerAssign
,
{
openModal
:
openAssignModal
}]
=
useModal
();
const
[
registerAssignRead
,
{
openModal
:
openAssignReadModal
}]
=
useModal
();
// 转办表单配置
const
assignFormSchemas
=
[
{
label
:
computed
(()
=>
(
isApproval
.
value
?
'审批人'
:
'接收人'
)),
field
:
'checkSendUser'
,
component
:
'JSelectUser'
,
required
:
true
,
componentProps
:
{
allowClear
:
true
,
rowKey
:
'id'
,
labelKey
:
'realname'
,
showButton
:
false
,
modalTitle
:
computed
(()
=>
(
isApproval
.
value
?
'选择审批人'
:
'选择接收人'
)),
placeholder
:
computed
(()
=>
(
isApproval
.
value
?
'请选择审批人'
:
'请选择接收人'
)),
mode
:
'multiple'
,
},
},
];
// 转办表单注册
const
[
registerAssignForm
,
{
validate
:
validateAssign
}]
=
useForm
({
schemas
:
assignFormSchemas
,
showActionButtonGroup
:
false
,
});
// 计算属性
// const isFixed = computed(() => {
// return nextNode.value?.dataType === "fixed"
// })
const
isFixed
=
ref
(
true
);
const
assigning
=
ref
(
false
);
const
assiReadgning
=
ref
(
false
);
const
userType
=
computed
(()
=>
{
return
nextNode
.
value
?.
type
||
''
;
});
// 表单配置
const
formSchemas
=
[
{
label
:
'审批意见'
,
field
:
'comment'
,
component
:
'InputTextArea'
,
required
:
false
,
componentProps
:
{
allowClear
:
true
,
showCount
:
true
,
autoSize
:
{
minRows
:
6
,
maxRows
:
8
,
},
placeholder
:
'请输入审批意见,如:同意、需补充材料等'
,
maxlength
:
500
,
},
rules
:
[
{
required
:
true
,
message
:
'请填写审批意见'
},
{
min
:
2
,
message
:
'至少输入2个字符'
},
],
},
{
label
:
'接收人'
,
field
:
'checkSendUser'
,
component
:
'JSelectUser'
,
required
:
true
,
componentProps
:
{
allowClear
:
true
,
rowKey
:
'id'
,
labelKey
:
'realname'
,
showButton
:
false
,
modalTitle
:
'选择接收人'
,
placeholder
:
'请选择接收人'
,
mode
:
'multiple'
,
},
},
{
label
:
'抄送人'
,
field
:
'copyUser'
,
component
:
'JSelectUser'
,
required
:
false
,
componentProps
:
{
allowClear
:
true
,
rowKey
:
'id'
,
labelKey
:
'realname'
,
showButton
:
false
,
modalTitle
:
'选择抄送人'
,
placeholder
:
'请选择抄送人'
,
mode
:
'multiple'
,
},
},
{
label
:
'接收角色'
,
field
:
'checkSendRole'
,
component
:
'JSelectRole'
,
required
:
false
,
ifShow
:
computed
(()
=>
userType
.
value
!==
'user'
),
componentProps
:
{
labelKey
:
'roleName'
,
rowKey
:
'id'
,
allowClear
:
true
,
maxSelectCount
:
3
,
isRadioSelection
:
false
,
placeholder
:
'请选择接收角色'
,
mode
:
'multiple'
,
},
},
];
const
[
registerForm
,
{
validate
,
setFieldsValue
,
removeSchemaByFiled
,
resetFields
,
updateSchema
}]
=
useForm
({
schemas
:
formSchemas
as
any
,
showActionButtonGroup
:
false
,
baseColProps
:
{
span
:
24
},
labelWidth
:
100
,
layout
:
'vertical'
,
autoSubmitOnEnter
:
false
,
//不显示重置按钮
showResetButton
:
false
,
//自定义提交按钮文本和图标
submitButtonOptions
:
{
text
:
'提交'
,
preIcon
:
''
},
});
const
emit
=
defineEmits
([
'callback'
,
'success'
,
'error'
]);
// 方法
const
handleTabClick
=
async
(
key
:
string
)
=>
{
if
(
key
===
'1'
&&
!
formLoading
.
value
)
{
await
initializeCruInnerForm
();
}
if
(
key
===
'2'
&&
flowRecordList
.
value
.
length
===
0
)
{
await
loadFlowRecord
();
}
if
(
key
===
'3'
)
{
await
loadFlowChart
();
}
};
const
initializeCruInnerForm
=
async
()
=>
{
if
(
formLoading
.
value
)
return
;
try
{
formLoading
.
value
=
true
;
formError
.
value
=
false
;
await
nextTick
();
let
{
taskId
}
=
taskForm
;
if
(
!
taskId
)
{
// try to resolve taskId by business id from workFlowData
const
dataId
=
workFlowData
.
value
?.
dataId
||
workFlowData
.
value
?.
id
||
workFlowData
.
value
?.
businessId
;
if
(
dataId
)
{
try
{
const
info
=
await
flowTaskInfo
({
dataId
});
if
(
info
?.
taskId
)
{
taskForm
.
taskId
=
info
.
taskId
;
taskId
=
info
.
taskId
;
}
}
catch
(
e
)
{
// ignore and fall through to error below
console
.
warn
(
'flowTaskInfo 获取 taskId 失败'
,
e
);
}
}
}
if
(
!
taskId
)
{
throw
new
Error
(
'任务ID未设置'
);
}
const
resData
=
await
flowTaskForm
({
taskId
});
const
{
flowForm
=
{}
}
=
resData
;
// normalize form type to number for consistent comparisons
const
tp
=
Number
(
flowForm
.
formTp
);
formTp
.
value
=
tp
;
if
(
tp
===
1
)
{
// ensure the inner form component is recreated before initializing
formKey
.
value
++
;
await
nextTick
();
if
(
!
refCruInnerForm
.
value
)
{
// wait a tick more in case component hasn't mounted
await
nextTick
();
}
if
(
refCruInnerForm
.
value
&&
typeof
refCruInnerForm
.
value
.
iniData
===
'function'
)
{
await
refCruInnerForm
.
value
.
iniData
(
flowForm
);
}
else
{
throw
new
Error
(
'内嵌表单组件未就绪'
);
}
}
else
{
let
formValues
=
resData
.
formValues
||
{};
let
formUrlparval
=
formValues
.
dataId
;
let
formUrlpar
=
formValues
.
dataName
||
'id'
;
const
connector
=
flowForm
.
formUrl
&&
flowForm
.
formUrl
.
includes
(
'?'
)
?
'&'
:
'?'
;
formUrl
.
value
=
(
flowForm
.
formUrl
||
''
)
+
connector
+
formUrlpar
+
'='
+
formUrlparval
;
// force iframe reload when src is set/changed
formKey
.
value
++
;
await
nextTick
();
console
.
error
(
'表单url:'
,
formUrl
.
value
);
}
formError
.
value
=
false
;
}
catch
(
error
)
{
console
.
error
(
'初始化表单失败:'
,
error
);
formError
.
value
=
true
;
const
msg
=
error
instanceof
Error
?
error
.
message
:
String
(
error
);
message
.
error
(
`表单加载失败:
${
msg
}
`
);
}
finally
{
formLoading
.
value
=
false
;
}
};
const
retryLoadForm
=
()
=>
{
formError
.
value
=
false
;
initializeCruInnerForm
();
};
const
refreshForm
=
()
=>
{
formKey
.
value
++
;
initializeCruInnerForm
();
};
const
loadFlowRecord
=
async
()
=>
{
try
{
loadingFlowRecord
.
value
=
true
;
const
{
procInsId
,
deployId
}
=
taskForm
;
if
(
!
procInsId
||
!
deployId
)
return
;
const
res
=
await
flowRecord
({
procInsId
,
deployId
});
flowRecordList
.
value
=
res
.
flowList
||
[];
}
catch
(
error
)
{
console
.
error
(
'加载流转记录失败:'
,
error
);
message
.
error
(
'加载流转记录失败'
);
}
finally
{
loadingFlowRecord
.
value
=
false
;
}
};
const
loadFlowChart
=
async
()
=>
{
try
{
loadingFlowChart
.
value
=
true
;
const
{
procInsId
,
deployId
}
=
taskForm
;
if
(
!
procInsId
||
!
deployId
)
{
throw
new
Error
(
'缺少流程实例信息'
);
}
const
res
=
await
flowXmlAndNode
({
procInsId
,
deployId
});
flowData
.
value
=
res
;
}
catch
(
error
)
{
console
.
error
(
'加载流程图失败:'
,
error
);
message
.
error
(
'加载流程图失败'
);
}
finally
{
loadingFlowChart
.
value
=
false
;
}
};
const
formatTime
=
(
time
:
string
)
=>
{
if
(
!
time
)
return
''
;
return
dayjs
(
time
).
format
(
'YYYY-MM-DD HH:mm:ss'
);
};
const
formatDuration
=
(
duration
:
string
)
=>
{
if
(
!
duration
)
return
''
;
return
duration
.
replace
(
'PT'
,
''
).
toLowerCase
();
};
const
getTimelineColor
=
(
finishTime
:
string
|
null
)
=>
{
return
finishTime
?
'green'
:
'blue'
;
};
const
getTaskStatusColor
=
(
finishTime
:
string
|
null
)
=>
{
return
finishTime
?
'success'
:
'processing'
;
};
const
handleSendTask
=
async
()
=>
{
if
(
sending
.
value
)
return
;
try
{
sending
.
value
=
true
;
const
submitData
=
{
instanceId
:
taskForm
.
instanceId
,
deployId
:
taskForm
.
deployId
,
taskId
:
taskForm
.
taskId
,
comment
:
''
,
values
:
{},
};
//找到选择的下一步节点
if
(
nextNodenum
.
value
>
1
)
{
submitData
.
values
[
'userTaskid'
]
=
nextNodeNameSelevue
.
value
;
}
if
(
!
showApprovalUi
.
value
)
{
const
result
=
await
complete
(
submitData
);
message
.
success
(
'任务结束成功'
);
emit
(
'success'
,
result
);
emit
(
'callback'
);
return
false
;
}
const
formData
=
await
validate
();
Object
.
assign
(
submitData
,
formData
);
submitData
.
comment
=
submitData
.
comment
||
''
;
//alert("dd"+isFixed.value);
// if (!isFixed.value) {
if
(
userType
.
value
===
'user'
)
{
submitData
.
values
[
'approval'
]
=
formData
.
checkSendUser
;
submitData
.
values
[
'copyUser'
]
=
formData
.
copyUser
;
submitData
.
values
[
'approvalType'
]
=
'user'
;
if
(
formData
.
checkSendUser
)
{
submitData
.
values
[
'approval'
]
=
formData
.
checkSendUser
;
submitData
.
values
[
'copyUser'
]
=
formData
.
copyUser
;
submitData
.
values
[
'approvalType'
]
=
'user'
;
}
}
else
if
(
formData
.
checkSendRole
)
{
submitData
.
values
[
'approval'
]
=
formData
.
checkSendRole
;
submitData
.
values
[
'approvalType'
]
=
'role'
;
}
else
{
submitData
.
values
[
'approval'
]
=
formData
.
checkSendUser
;
submitData
.
values
[
'copyUser'
]
=
formData
.
copyUser
;
submitData
.
values
[
'approvalType'
]
=
'user'
;
}
console
.
log
(
"ssss why ----"
,
submitData
);
const
result
=
await
complete
(
submitData
);
message
.
success
(
'任务发送成功'
);
emit
(
'success'
,
result
);
emit
(
'callback'
);
}
catch
(
error
:
any
)
{
if
(
error
.
errorFields
)
{
message
.
error
(
'请完善表单信息'
);
}
else
{
message
.
error
(
error
.
message
||
'发送任务失败'
);
}
}
finally
{
sending
.
value
=
false
;
}
};
const
handleReject
=
()
=>
{
openRejectModal
(
true
,
{
isUpdate
:
false
,
data
:
workFlowData
.
value
,
onSuccess
:
()
=>
{
message
.
error
(
'任务已驳回'
);
emit
(
'callback'
);
},
});
};
const
onFlowChartLoaded
=
()
=>
{
console
.
log
(
'流程图加载完成'
);
};
const
handleChange
=
(
value
:
string
)
=>
{
console
.
log
(
`selected
${
value
}
`
);
nextNodeNameSelevue
.
value
=
value
;
console
.
log
(
' nextNodeNameSelevue.value '
,
nextNodeNameSelevue
.
value
);
if
(
value
==
0
)
{
ChangeSelectNodeAfter
(
res0
);
}
if
(
value
==
1
)
{
ChangeSelectNodeAfter
(
res1
);
}
if
(
value
==
2
)
{
ChangeSelectNodeAfter
(
res2
);
}
};
function
ChangeSelectNodeAfter
(
res
)
{
isFixed
.
value
=
res
.
dataType
==
'fixed'
?
true
:
false
;
if
(
isFixed
.
value
&&
!
isApproval
.
value
)
{
showApprovalUi
.
value
;
}
nextNode
.
value
=
res
;
nextNodeName
.
value
=
res
.
userTask
?.
name
||
''
;
if
(
res
.
type
===
'role'
)
{
removeSchemaByFiled
(
'checkSendUser'
);
if
(
res
.
dataType
===
'fixed'
&&
res
.
userTask
?.
candidateGroups
)
{
setFieldsValue
({
checkSendRole
:
res
.
userTask
.
candidateGroups
,
});
}
}
else
{
removeSchemaByFiled
(
'checkSendRole'
);
if
(
res
.
dataType
===
'fixed'
&&
res
.
userTask
?.
assignee
)
{
setFieldsValue
({
checkSendUser
:
res
.
userTask
.
assignee
,
});
}
}
updateSchema
([
{
field
:
'checkSendUser'
,
label
:
isApproval
.
value
?
'接收人'
:
'审批人'
,
componentProps
:
{
modalTitle
:
isApproval
.
value
?
'选择接收人'
:
'选择审批人'
,
placeholder
:
isApproval
.
value
?
'请选择接收人'
:
'请选择审批人'
,
},
},
]);
}
const
iniData
=
async
(
data
:
any
)
=>
{
try
{
// 设置工作流数据
workFlowData
.
value
=
data
;
console
.
log
(
'why iniData'
,
data
);
// 更新任务表单
Object
.
assign
(
taskForm
,
{
deployId
:
data
.
deployId
||
''
,
taskId
:
data
.
taskId
||
''
,
procInsId
:
data
.
procInsId
||
''
,
executionId
:
data
.
executionId
||
''
,
instanceId
:
data
.
procInsId
||
''
,
});
isApproval
.
value
=
data
.
nodeisApprove
;
nextTick
(()
=>
{
updateSchema
([
{
field
:
'checkSendUser'
,
label
:
isApproval
.
value
?
'接收人'
:
'审批人'
,
componentProps
:
{
modalTitle
:
isApproval
.
value
?
'选择接收人'
:
'选择审批人'
,
placeholder
:
isApproval
.
value
?
'请选择接收人'
:
'请选择审批人'
,
},
},
]);
});
if
(
!
isApproval
.
value
)
{
approvalTitle
.
value
=
'选择人员'
;
removeSchemaByFiled
(
'comment'
);
}
else
{
approvalTitle
.
value
=
'填写意见'
;
}
if
(
taskForm
.
taskId
)
{
const
reslist
=
await
getNextFlowNode
({
taskId
:
taskForm
.
taskId
});
console
.
log
(
'getNextFlowNode reslist '
,
reslist
);
if
(
reslist
==
null
)
{
// 到达流程结束节点:设置展示状态但不要提前返回,仍需加载表单和流转记录
nextNodeName
.
value
=
'结束'
;
removeSchemaByFiled
(
'checkSendRole'
);
removeSchemaByFiled
(
'checkSendUser'
);
showApprovalUi
.
value
=
isApproval
.
value
;
shownextNodeNameSele
.
value
=
false
;
shownextNodeNametext
.
value
=
true
;
// 不再 return,这样后续仍会继续加载流转记录和表单
}
else
{
shownextNodeNameSele
.
value
=
true
;
shownextNodeNametext
.
value
=
false
;
nextNodenum
.
value
=
reslist
.
length
;
//why工作流修改
// 使用 for 循环赋值
for
(
let
i
=
0
;
i
<
reslist
.
length
;
i
++
)
{
let
resb
=
reslist
[
i
];
tableOptions
.
value
.
push
({
id
:
`
${
i
}
`
,
name
:
`
${
resb
.
userTask
.
name
}
`
,
value
:
`
${
i
}
`
,
});
}
nextNodeNameSele
.
value
=
tableOptions
.
value
[
0
].
name
;
const
res
=
reslist
[
0
];
// 获取第一行数据
console
.
log
(
'res '
,
res
);
ChangeSelectNodeAfter
(
res
);
if
(
reslist
.
length
==
1
)
{
res0
.
value
=
reslist
[
0
];
}
if
(
reslist
.
length
==
2
)
{
res0
.
value
=
reslist
[
0
];
res1
.
value
=
reslist
[
1
];
}
if
(
reslist
.
length
==
3
)
{
res0
.
value
=
reslist
[
0
];
res1
.
value
=
reslist
[
1
];
res2
.
value
=
reslist
[
2
];
}
}
}
// 加载流转记录
await
loadFlowRecord
();
// 加载当前表单
if
(
activeName
.
value
===
'1'
)
{
await
initializeCruInnerForm
();
}
}
catch
(
error
)
{
console
.
error
(
'初始化数据失败:'
,
error
);
message
.
error
(
'初始化失败,请刷新页面重试'
);
}
};
//转办处理
const
handleAssignTask
=
()
=>
{
openAssignModal
(
true
,
{
isUpdate
:
false
,
data
:
workFlowData
.
value
,
onSuccess
:
()
=>
{
message
.
success
(
'任务转办成功'
);
emit
(
'success'
);
emit
(
'callback'
);
},
});
};
//转阅处理
const
handleAssignReadTask
=
()
=>
{
openAssignReadModal
(
true
,
{
isUpdate
:
false
,
data
:
workFlowData
.
value
,
onSuccess
:
()
=>
{
message
.
success
(
'任务转阅成功'
);
emit
(
'success'
);
emit
(
'callback'
);
},
});
};
defineExpose
({
iniData
,
});
</
script
>
<
style
lang=
"scss"
scoped
>
/* ==================== 柔和中性风格 - CSS 变量 ==================== */
.execute-form-container
{
background
:
var
(
--
color-bg-white
);
min-height
:
100vh
;
font-family
:
-
apple-system
,
BlinkMacSystemFont
,
'PingFang SC'
,
'Helvetica Neue'
,
sans-serif
;
}
.app-container
{
--color-primary
:
#3b5bdb
;
--color-primary-hover
:
#364fc7
;
--color-primary-light
:
#e8ecfd
;
--color-success
:
#2f9e44
;
--color-warning
:
#e67700
;
--color-error
:
#c92a2a
;
--color-text-primary
:
#1c1c1e
;
--color-text-secondary
:
#555770
;
--color-text-muted
:
#a0a3b1
;
--color-border
:
#e4e4e9
;
--color-border-strong
:
#c8c8d0
;
--color-bg-page
:
#f5f5f7
;
--color-bg-white
:
#ffffff
;
--color-bg-section
:
#f0f0f4
;
--radius
:
6px
;
height
:
100vh
;
margin
:
0
;
padding
:
0
;
// background: linear-gradient(135deg, #b0b3c2 0%, #764ba2 100%);
overflow
:
hidden
;
}
.box-card
{
height
:
100%
;
border
:
none
;
box-shadow
:
none
;
border-radius
:
0
;
overflow
:
hidden
;
margin
:
0px
;
:deep
(
.ant-card-body
)
{
height
:
100%
;
padding
:
0
;
}
}
.process-tabs
{
height
:
100%
;
:deep
(
.ant-tabs-nav
)
{
background
:
white
;
margin
:
0
;
padding
:
0
24px
;
box-shadow
:
0
2px
8px
rgba
(
0
,
0
,
0
,
0
.06
);
}
:deep
(
.ant-tabs-content
)
{
height
:
calc
(
100%
-
55px
);
overflow
:
hidden
;
}
:deep
(
.ant-tabs-tabpane
)
{
height
:
100%
;
padding
:
0
;
}
}
// 当前表单页面样式
.form-container
{
height
:
100%
;
display
:
flex
;
flex-direction
:
column
;
background
:
#f5f7fa
;
}
.action-header
{
background
:
white
;
padding
:
16px
24px
;
display
:
flex
;
justify-content
:
space-between
;
align-items
:
center
;
box-shadow
:
0
2px
8px
rgba
(
0
,
0
,
0
,
0
.06
);
border-bottom
:
1px
solid
#f0f0f0
;
.action-left
{
flex
:
1
;
}
.action-right
{
.next-node-info
{
display
:
flex
;
align-items
:
center
;
gap
:
12px
;
}
.next-node-label
{
width
:
120px
;
color
:
#666
;
font-size
:
14px
;
}
.next-node-tag
{
font-size
:
14px
;
padding
:
4px
12px
;
border-radius
:
16px
;
font-weight
:
500
;
}
}
}
.content-wrapper
{
flex
:
1
;
display
:
flex
;
gap
:
24px
;
padding
:
24px
;
overflow
:
hidden
;
}
.main-form-section
{
flex
:
3
;
min-width
:
0
;
.form-card
{
height
:
100%
;
border-radius
:
8px
;
box-shadow
:
0
2px
12px
rgba
(
0
,
0
,
0
,
0
.08
);
overflow
:
hidden
;
:deep
(
.ant-card-head
)
{
background
:
linear-gradient
(
135deg
,
#667eea
0%
,
#764ba2
100%
);
color
:
white
;
border
:
none
;
padding
:
0
24px
;
.ant-card-head-title
{
font-size
:
18px
;
font-weight
:
600
;
padding
:
16px
0
;
}
.ant-card-extra
{
padding
:
16px
0
;
button
{
color
:
white
;
&
:hover
{
color
:
rgba
(
255
,
255
,
255
,
0
.8
);
}
}
}
}
:deep
(
.ant-card-body
)
{
padding
:
24px
;
height
:
calc
(
100%
-
64px
);
overflow-y
:
auto
;
}
}
.loading-state
,
.error-state
{
display
:
flex
;
justify-content
:
center
;
align-items
:
center
;
height
:
400px
;
}
.form-wrapper
{
height
:
100%
;
}
}
.sidebar-section
{
flex
:
1
;
min-width
:
400px
;
.approval-card
{
height
:
100%
;
border-radius
:
8px
;
box-shadow
:
0
2px
12px
rgba
(
0
,
0
,
0
,
0
.08
);
overflow
:
hidden
;
:deep
(
.ant-card-head
)
{
background
:
linear-gradient
(
135deg
,
#36d1dc
0%
,
#5b86e5
100%
);
color
:
white
;
border
:
none
;
padding
:
0
24px
;
.ant-card-head-title
{
font-size
:
18px
;
font-weight
:
600
;
padding
:
16px
0
;
}
}
:deep
(
.ant-card-body
)
{
padding
:
24px
;
height
:
calc
(
100%
-
64px
);
display
:
flex
;
flex-direction
:
column
;
}
}
.form-tips
{
margin-top
:
auto
;
padding-top
:
20px
;
.tips-alert
{
border-radius
:
6px
;
:deep
(
.ant-alert-message
)
{
font-weight
:
500
;
}
}
}
}
// 流转记录页面样式
.record-container
{
height
:
100%
;
padding
:
24px
;
background
:
#f5f7fa
;
.record-card
{
height
:
100%
;
border-radius
:
8px
;
box-shadow
:
0
2px
12px
rgba
(
0
,
0
,
0
,
0
.08
);
overflow
:
hidden
;
:deep
(
.ant-card-head
)
{
background
:
linear-gradient
(
135deg
,
#f093fb
0%
,
#f5576c
100%
);
color
:
white
;
border
:
none
;
padding
:
0
24px
;
.ant-card-head-title
{
font-size
:
18px
;
font-weight
:
600
;
padding
:
16px
0
;
}
}
:deep
(
.ant-card-body
)
{
padding
:
24px
;
height
:
calc
(
100%
-
64px
);
overflow-y
:
auto
;
}
}
.record-title
{
display
:
flex
;
align-items
:
center
;
font-size
:
16px
;
.anticon
{
font-size
:
20px
;
}
}
}
.flow-timeline
{
:deep
(
.ant-timeline-item
)
{
padding-bottom
:
24px
;
&
:last-child
{
padding-bottom
:
0
;
}
}
}
.timeline-item
{
.timeline-header
{
display
:
flex
;
justify-content
:
space-between
;
align-items
:
center
;
margin-bottom
:
12px
;
.task-name
{
display
:
flex
;
align-items
:
center
;
gap
:
12px
;
.status-tag
{
border-radius
:
12px
;
font-size
:
12px
;
padding
:
2px
10px
;
}
.task-title
{
font-weight
:
500
;
color
:
#333
;
}
}
.task-time
{
color
:
#666
;
font-size
:
13px
;
.anticon
{
margin-right
:
4px
;
}
}
}
.timeline-content
{
:deep
(
.ant-descriptions
)
{
border-radius
:
6px
;
overflow
:
hidden
;
.ant-descriptions-item-label
{
background
:
#fafafa
;
font-weight
:
500
;
min-width
:
80px
;
}
.desc-icon
{
margin-right
:
8px
;
color
:
#666
;
}
}
}
.comment-box
{
white-space
:
pre-wrap
;
word-break
:
break-word
;
line-height
:
1
.6
;
color
:
#333
;
}
}
.loading-state
,
.empty-state
{
display
:
flex
;
justify-content
:
center
;
align-items
:
center
;
height
:
300px
;
}
// 流程图页面样式
.flowchart-container
{
height
:
100%
;
padding
:
24px
;
background
:
#f5f7fa
;
.flowchart-card
{
height
:
100%
;
border-radius
:
8px
;
box-shadow
:
0
2px
12px
rgba
(
0
,
0
,
0
,
0
.08
);
overflow
:
hidden
;
:deep
(
.ant-card-head
)
{
background
:
linear-gradient
(
135deg
,
#4facfe
0%
,
#00f2fe
100%
);
color
:
white
;
border
:
none
;
padding
:
0
24px
;
.ant-card-head-title
{
font-size
:
18px
;
font-weight
:
600
;
padding
:
16px
0
;
}
}
:deep
(
.ant-card-body
)
{
height
:
calc
(
100%
-
64px
);
padding
:
0
;
}
}
.flowchart-title
{
display
:
flex
;
align-items
:
center
;
font-size
:
16px
;
.anticon
{
font-size
:
20px
;
}
}
}
.bpmn-wrapper
{
height
:
100%
;
padding
:
24px
;
.loading-state
{
display
:
flex
;
justify-content
:
center
;
align-items
:
center
;
height
:
500px
;
}
.bpmn-content
{
height
:
100%
;
min-height
:
500px
;
border
:
1px
solid
#e8e8e8
;
border-radius
:
6px
;
overflow
:
hidden
;
background
:
white
;
}
}
// 响应式设计
@media
(
max-width
:
1200px
)
{
.content-wrapper
{
flex-direction
:
column
;
gap
:
20px
;
}
.main-form-section
,
.sidebar-section
{
flex
:
none
;
min-width
:
auto
;
}
.sidebar-section
{
min-height
:
400px
;
}
}
@media
(
max-width
:
768px
)
{
.action-header
{
flex-direction
:
column
;
gap
:
16px
;
align-items
:
stretch
;
.action-right
{
.next-node-info
{
justify-content
:
center
;
}
}
}
.content-wrapper
{
padding
:
16px
;
}
.process-tabs
{
:deep
(
.ant-tabs-nav
)
{
padding
:
0
16px
;
}
}
}
// 滚动条美化
::-webkit-scrollbar
{
width
:
8px
;
height
:
8px
;
}
::-webkit-scrollbar-track
{
background
:
#f1f1f1
;
border-radius
:
4px
;
}
::-webkit-scrollbar-thumb
{
background
:
#c1c1c1
;
border-radius
:
4px
;
&
:hover
{
background
:
#a8a8a8
;
}
}
// 动画效果
.fade-enter-active
,
.fade-leave-active
{
transition
:
opacity
0
.3s
ease
;
}
.fade-enter-from
,
.fade-leave-to
{
opacity
:
0
;
}
</
style
>
zrch-risk-client-39/src/views/flowable/task/todo/todoReadindex.vue
浏览文件 @
401f07d4
...
...
@@ -40,7 +40,7 @@
class=
"custom-class"
root-class-name=
"root-class-name"
:root-style=
"{ color: 'blue' }"
title=
"待
办
任务"
title=
"待
阅
任务"
placement=
"right"
width=
"90%"
style=
"margin: 0px; padding: 0px"
...
...
zrch-risk-client-39/src/views/mytaskflowcc/MyTaskFlowCcList.vue
浏览文件 @
401f07d4
...
...
@@ -44,7 +44,7 @@
<span
class=
"tag"
>
任务节点:
{{
taskName
}}
</span>
</div>
</
template
>
<TodoIndex
v-if=
"isShowDrawer"
ref=
"refTodoIndex"
@
callback=
"handleSuccess"
/>
<Todo
Read
Index
v-if=
"isShowDrawer"
ref=
"refTodoIndex"
@
callback=
"handleSuccess"
/>
</a-drawer>
</div>
...
...
@@ -75,7 +75,7 @@
import
{
getDateByPicker
}
from
'/@/utils'
;
import
{
todoList
,
getMyTaskFlow
}
from
'/@/components/Process/api/todo'
;
// 引入待办任务组件
import
Todo
Index
from
'../flowable/task/todo/components/Todo
Index.vue'
;
import
Todo
ReadIndex
from
'../flowable/task/todo/components/TodoRead
Index.vue'
;
// 引入详情组件
import
Detail
from
'../flowable/task/myProcess/components/Detail.vue'
;
const
taskCache
=
new
Map
<
string
,
any
>
();
...
...
zrch-risk-server-39/jeecg-module-system/jeecg-module-flowable/src/main/java/org/jeecg/modules/flowable/service/impl/FlowInstanceServiceImpl.java
浏览文件 @
401f07d4
...
...
@@ -157,12 +157,14 @@ public class FlowInstanceServiceImpl extends FlowServiceFactory implements IFlow
HistoricProcessInstance
historicProcessInstance
=
getHistoricProcessInstanceById
(
instanceId
);
if
(
historicProcessInstance
.
getEndTime
()
!=
null
)
{
historyService
.
deleteHistoricProcessInstance
(
historicProcessInstance
.
getId
());
return
;
// return;
}
else
{
// 删除流程实例
runtimeService
.
deleteProcessInstance
(
instanceId
,
deleteReason
);
// 删除历史流程实例
historyService
.
deleteHistoricProcessInstance
(
instanceId
);
}
// 删除流程实例
runtimeService
.
deleteProcessInstance
(
instanceId
,
deleteReason
);
// 删除历史流程实例
historyService
.
deleteHistoricProcessInstance
(
instanceId
);
//删除业务数据
sysDeployFormService
.
deleteMyTaskFlowAndCCAndHis
(
instanceId
);
...
...
zrch-risk-server-39/jeecg-module-system/jeecg-module-stm/src/main/java/org/jeecg/modules/stm/my/controller/MyTaskFlowCcController.java
浏览文件 @
401f07d4
...
...
@@ -19,6 +19,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
lombok.extern.slf4j.Slf4j
;
import
org.jeecg.modules.stm.utils.UserUtil
;
import
org.jeecgframework.poi.excel.ExcelImportUtil
;
import
org.jeecgframework.poi.excel.def.NormalExcelConstants
;
import
org.jeecgframework.poi.excel.entity.ExportParams
;
...
...
@@ -69,6 +70,7 @@ public class MyTaskFlowCcController extends JeecgController<MyTaskFlowCc, IMyTas
QueryWrapper
<
MyTaskFlowCc
>
queryWrapper
=
QueryGenerator
.
initQueryWrapper
(
myTaskFlowCc
,
req
.
getParameterMap
());
Page
<
MyTaskFlowCc
>
page
=
new
Page
<
MyTaskFlowCc
>(
pageNo
,
pageSize
);
queryWrapper
.
eq
(
"ccid"
,
UserUtil
.
getUserId
());
IPage
<
MyTaskFlowCc
>
pageList
=
myTaskFlowCcService
.
page
(
page
,
queryWrapper
);
return
Result
.
OK
(
pageList
);
}
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论