Files
zhgh_whcp/target/classes/static/components/plugins/snaker/snakerFlowTaskFormAction.vue
T
2026-01-08 14:58:16 +08:00

316 lines
11 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="snaker-task-action" v-if="!loading || taskInfo">
<!-- 指定下一节点处理人 -->
<div class="next-handler-section" v-if="supportSpecifyNextHandler && candidates.length > 0">
<el-checkbox v-model="specifyNextHandler" @change="onSpecifyNextHandlerChange">指定下一节点处理人</el-checkbox>
<div class="handler-select-wrapper" v-if="specifyNextHandler">
<el-select v-model="selectedHandler" placeholder="请选择处理人" clearable filterable class="handler-select">
<el-option v-for="candidate in candidates" :key="candidate.userId" :label="candidate.userName" :value="candidate.userId">
<span style="float: left">{{ candidate.userName }}({{ candidate.ext?.loginName }})</span>
<span style="float: right; color: #8492a6; font-size: 13px">{{ candidate.ext?.unitName }}</span>
</el-option>
</el-select>
</div>
</div>
<!-- 第一个任务节点或新申请显示提交保存草稿取消 -->
<!-- <template v-if="isFirstTaskNodeOrNew">-->
<!-- <el-button type="primary" @click="handleSubmit" :loading="actionLoading" icon="el-icon-upload2">提交</el-button>-->
<!-- &lt;!&ndash; 保存草稿只在流程未发起时显示 &ndash;&gt;-->
<!-- <el-button @click="handleSaveDraft" v-if="!actionLoading && show_save_draft && !instanceId" icon="el-icon-document">保存草稿</el-button>-->
<!-- <el-button @click="handleCancel" :loading="actionLoading" v-if="show_cancel" icon="el-icon-close">取消</el-button>-->
<!-- </template>-->
<!-- &lt;!&ndash; 其他任务节点显示审批按钮 &ndash;&gt;-->
<!-- <template v-else>-->
<!-- &lt;!&ndash; 会签任务按钮 &ndash;&gt;-->
<!-- <template v-if="is_countersign_task">-->
<!-- <el-button type="primary" @click="handleAction('AGREE')" :loading="actionLoading" icon="el-icon-check">同意</el-button>-->
<!-- <el-button type="danger" plain @click="handleAction('COUNTERSIGN_DISAGREE')" :loading="actionLoading" icon="el-icon-close">-->
<!-- 不同意-->
<!-- </el-button>-->
<!-- </template>-->
<!-- &lt;!&ndash; 普通任务按钮 &ndash;&gt;-->
<!-- <template v-else>-->
<!-- <el-button type="primary" @click="handleAction('AGREE')" :loading="actionLoading" icon="el-icon-check">同意</el-button>-->
<!-- <el-button type="danger" plain @click="handleAction('REJECT')" :loading="actionLoading" icon="el-icon-close">拒绝</el-button>-->
<!-- <el-button @click="handleAction('ROLLBACK')" :loading="actionLoading" icon="el-icon-back">退回上一步</el-button>-->
<!-- <el-button @click="handleAction('ROLLBACK_TO_OPERATOR')" :loading="actionLoading" icon="el-icon-d-arrow-left">退回发起人</el-button>-->
<!-- <el-button @click="handleAction('JUMP')" :loading="actionLoading" icon="el-icon-position">跳转</el-button>-->
<!-- </template>-->
<!-- </template>-->
<!--没有流程实例的时候-->
<template v-if="!instanceId">
<el-button type="primary" @click="handleSubmit">提交</el-button>
<el-button @click="handleSaveDraft">保存</el-button>
</template>
<el-row type="flex" justify="end">
<el-button v-for="item in buttons" @click="handleAction(item.value)" :type="item.theme" :icon="item.icon" size="medium" :key="item.value">
{{ item.replacementText || item.originalText }}
</el-button>
</el-row>
</div>
<!-- 加载状态 -->
<div v-else class="snaker-task-action loading-state">
<el-button loading icon="el-icon-loading">加载中...</el-button>
</div>
</template>
<script>
module.exports = {
name: "SnakerFlowTaskFormAction",
props: {},
data() {
return {
// 加载状态
loading: false,
// 操作按钮加载状态
actionLoading: false,
// 任务信息
taskInfo: null,
// 任务操作枚举
actionEnum: {
APPLY: "0", // 发起申请
AGREE: "1", // 同意
REJECT: "2", // 拒绝
COUNTERSIGN_DISAGREE: "20", // 会签不同意 拒绝申请
ROLLBACK: "3", // 退回上一步
ROLLBACK_TO_OPERATOR: "6", // 退回发起人
JUMP: "4", // 跳转
RE_APPLY: "5", // 重新提交
SUBMIT: "0" // 发起申请
},
// 任务类型枚举
performTypeEnum: {
NORMAL: 0, // 普通任务
COUNTERSIGN: 1 // 会签任务
},
// 指定下一节点处理人相关
specifyNextHandler: false, // 是否指定下一节点处理人
selectedHandler: null, // 选中的处理人ID
candidates: [], // 候选人列表
supportCandidate: false,
taskId: GetQueryString("taskId"),
instanceId: GetQueryString("instanceId"),
defineKey: GetQueryString("defineKey"),
defineId: GetQueryString("defineId"),
businessId: GetQueryString("businessId")
}
},
computed: {
// 是否为会签任务
is_countersign_task() {
return this.taskInfo && this.taskInfo.performType === this.performTypeEnum.COUNTERSIGN
},
// 是否为第一个任务节点或新申请
isFirstTaskNodeOrNew() {
// 没有任务ID,说明是新申请
if (!this.taskId) {
return true
}
// 有任务ID但是任务信息中标识为第一个节点
return this.taskInfo && this.taskInfo.ext && this.taskInfo.ext.isFirstTaskNode
},
// 审批按钮配置
buttons() {
if (this.taskInfo) {
return this.taskInfo.taskModel.ext.buttonConfig.filter((v) => v.visible)
}
return []
},
// 是否支持选择下一步处理人
supportSpecifyNextHandler() {
return this.taskInfo && this.taskInfo.taskModel.ext.enableNextOperator
}
},
mounted() {
// 只有当有任务ID时才加载任务信息
if (this.taskId) {
this.loadTaskInfo()
this.loadCandidates()
}
},
methods: {
// 加载任务信息
loadTaskInfo() {
if (!this.taskId) return
this.loading = true
this.taskInfo = null
$.get("/flow/common/taskInfo", {
taskId: this.taskId
})
.then((res) => {
if (res.code === 0) {
this.taskInfo = res.data
}
})
.always(() => {
this.loading = false
})
},
// 处理提交操作
handleSubmit() {
// 根据是否有流程实例来确定操作类型
const submitAction = this.instanceId ? this.actionEnum.RE_APPLY : this.actionEnum.APPLY
// 触发父组件事件,传递提交操作
this.$emit("task-action", {
submitType: submitAction,
taskId: this.taskId,
instanceId: this.instanceId,
defineId: this.defineId,
defineKey: this.defineKey,
businessId: this.businessId
})
},
// 处理任务操作
handleAction(actionKey) {
if (this.actionLoading || !this.taskInfo) return
// 构建操作数据
const actionData = {
submitType: this.actionEnum[actionKey],
taskId: this.taskId,
processTaskId: this.taskId,
instanceId: this.instanceId,
defineId: this.defineId,
defineKey: this.defineKey,
businessId: this.businessId
}
// 如果指定了下一节点处理人,添加到操作数据中
if (this.specifyNextHandler && this.selectedHandler) {
actionData.tf_nextNodeOperator = this.selectedHandler
}
// 触发父组件事件,传递操作类型和任务信息
this.$emit("task-action", actionData)
},
// 保存草稿
handleSaveDraft() {
if (this.actionLoading) return
this.$emit("save-draft", {
submitType: this.actionEnum.APPLY,
defineKey: this.defineKey,
defineId: this.defineId
})
},
// 取消操作
handleCancel() {
const func = () => window.close()
this.$emit("cancel", func)
if (!this.$listeners.cancel) {
func()
}
},
// 刷新任务信息
refresh() {
if (this.taskId) {
this.loadTaskInfo()
}
},
// 处理指定下一节点处理人勾选框变化
onSpecifyNextHandlerChange(checked) {
if (!checked) {
this.selectedHandler = null
}
},
// 加载候选人列表
loadCandidates() {
$.get("/flow/common/candidate", {
taskId: this.taskId
}).then((res) => {
if (res.code === 0) {
this.candidates = res.data.candidates
this.supportCandidate = res.data.support
}
})
}
}
}
</script>
<style scoped>
.snaker-task-action {
text-align: center;
padding: 20px;
background: #fff;
border-top: 1px solid #eee;
margin-top: 20px;
}
.snaker-task-action .el-button {
margin: 0 8px;
min-width: 80px;
}
.loading-state {
display: flex;
justify-content: center;
align-items: center;
min-height: 60px;
}
/* 指定下一节点处理人样式 */
.next-handler-section {
margin-bottom: 20px;
padding: 15px;
background: #f8f9fa;
border: 1px solid #e9ecef;
border-radius: 4px;
text-align: left;
}
.handler-select-wrapper {
margin-top: 10px;
}
.handler-select {
width: 100%;
max-width: 300px;
}
/* 响应式 */
@media (max-width: 768px) {
.snaker-task-action {
display: flex;
flex-direction: column;
gap: 10px;
padding: 15px;
}
.snaker-task-action .el-button {
width: 100%;
margin: 0;
}
.next-handler-section {
margin-bottom: 15px;
padding: 10px;
}
.handler-select {
max-width: 100%;
}
}
</style>