fix:重新发起

This commit is contained in:
大黑 2026-01-21 15:32:52 +08:00
parent 3d7ee782b1
commit d53901e00a
14 changed files with 5207 additions and 1598 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -220,7 +220,10 @@ export default {
url: '/custom/responsible/getImportTemplate',
method: 'get'
},
GET_MODEL_BY_ID: {
url: '/custom/template/getTemplateById',
method: 'get'
},
// 修改流程主题
EDIT_DATA_PROCESS_TITLE: {
url: '/custom/activiti/updateFlowTitle',

View File

@ -105,10 +105,7 @@ export default {
url: '/custom/approval/directSendingApproval',
method: 'get'
},
GET_MODEL_BY_ID: {
url: '/custom/template/getTemplateById',
method: 'get'
},
GET_CAN_RETURN_NODE: {
url: '/custom/approval/getReturnNodes',
method: 'get'
@ -124,5 +121,13 @@ export default {
EDIT_APPROVAL_PROCESS_TITLE: {
url: '/custom/approval/updateFlowTitle',
method: 'get'
},
EDIT_APPROVAL_PROCESS: {
url: '/custom/approval/updateNode',
method: 'post'
},
CONTINUE_APPROVAL_PROCESS: {
url: '/custom/approval/continueApproval',
method: 'get'
}
}

View File

@ -62,5 +62,9 @@ export default {
GET_REPORT_APPROVAL_USERS: {
url: '/custom/benchmark/getApprovalUsers',
method: 'get'
},
CONTINUE_REPORT_APPROVAL: {
url: '/custom/benchmark/continueApproval',
method: 'get'
}
}

View File

@ -1557,22 +1557,21 @@ export default {
}
}
}
}
.return-opinion-section {
margin-top: 16px;
padding-top: 16px;
margin-top: 16px !important;
border-top: 1px solid #ebeef5;
.opinion-label {
margin-bottom: 8px;
margin-top: 8px;
margin-bottom: 5px !important;
margin-top: 5px !important;
font-size: 14px;
color: #606266;
font-weight: 500;
}
}
}
}
.approval-progress-fade-enter-active,
.approval-progress-fade-leave-active {
transition: opacity 0.2s ease;

File diff suppressed because it is too large Load Diff

View File

@ -2841,11 +2841,10 @@ export default {
// fromTodo flowId canResend true GET_DATA_APPROVAL_USERS
if (this.shouldShowResendButton) {
this.isResendMode = true
const flowId = this.engineModelID
const request = {
...api.GET_DATA_APPROVAL_USERS,
params: {
templateId: flowId
templateId: this.flowId
},
disableSuccessMsg: true
}

View File

@ -77,7 +77,7 @@
type="primary"
@click="handleResendApproval"
>
重新发起
发起
</el-button>
</template>
<template v-else-if="isMaintainMode">
@ -323,12 +323,41 @@
<div class="approval-process-title">
<div class="description-label">
流程主题 <span class="required-mark">*</span>
<div v-if="isResendModeFilled && !isProcessTitleEditing" class="step-actions">
<el-button
type="text"
size="small"
class="edit-step-btn"
@click="handleEditProcessTitle"
>
修改
</el-button>
</div>
<div v-else-if="isResendModeFilled && isProcessTitleEditing" class="step-actions">
<el-button
type="text"
size="small"
class="save-step-btn"
@click="handleSaveProcessTitle"
>
保存
</el-button>
<el-button
type="text"
size="small"
class="cancel-step-btn"
@click="handleCancelEditProcessTitle"
>
返回
</el-button>
</div>
</div>
<el-input
v-model="approvalFormData.processTitle"
maxlength="100"
show-word-limit
placeholder="请输入流程主题"
:disabled="isResendModeFilled && !isProcessTitleEditing"
/>
</div>
</div>
@ -365,6 +394,7 @@
placeholder="请选择"
:remote-method="(query) => handleRemoteSearch(query, index)"
:loading="step.loading"
:disabled="isResendModeFilled && !isProcessTitleEditing"
class="handler-select"
@change="(value) => handleHandlerChange(index, value)"
>
@ -680,35 +710,47 @@ export default {
approvalSubmitting: false, // loading
resending: false, // loading
isResendMode: false, //
isResendModeFilled: false, //
resendApprovalData: null, //
resendFlowId: null, // ID resendApprovalData
isProcessTitleEditing: false, //
originalProcessTitle: '', //
approvalWorkflowSteps: [
{
name: '校对',
required: true,
handlers: [],
options: [],
loading: false
loading: false,
isEditing: false, //
originalData: null //
},
{
name: '审核',
required: true,
handlers: [],
options: [],
loading: false
loading: false,
isEditing: false,
originalData: null
},
{
name: '会签',
required: false,
handlers: [],
options: [],
loading: false
loading: false,
isEditing: false,
originalData: null
},
{
name: '批准',
required: true,
handlers: [],
options: [],
loading: false
loading: false,
isEditing: false,
originalData: null
}
],
nextLocalId: 1,
@ -1416,7 +1458,6 @@ export default {
console.log('获取审批流程信息:', resp)
// fillResendApprovalData
this.resendApprovalData = resp
// getApprovalChange
this.getApprovalChange()
})
@ -2076,28 +2117,36 @@ export default {
required: true,
handlers: [],
options: [],
loading: false
loading: false,
isEditing: false,
originalData: null
},
{
name: '审核',
required: true,
handlers: [],
options: [],
loading: false
loading: false,
isEditing: false,
originalData: null
},
{
name: '会签',
required: false,
handlers: [],
options: [],
loading: false
loading: false,
isEditing: false,
originalData: null
},
{
name: '批准',
required: true,
handlers: [],
options: [],
loading: false
loading: false,
isEditing: false,
originalData: null
}
]
@ -2282,6 +2331,25 @@ export default {
} else {
console.log('节点列表为空,无法填充人员信息')
}
// flowId dataObj
if (dataObj && !Array.isArray(dataObj)) {
this.resendFlowId = dataObj.flowId || dataObj.id || null
console.log('提取的 flowId:', this.resendFlowId)
}
//
this.isResendModeFilled = true
//
this.originalProcessTitle = this.approvalFormData.processTitle || ''
//
this.approvalWorkflowSteps.forEach((step) => {
step.originalData = {
handlers: JSON.parse(JSON.stringify(step.handlers || [])),
options: JSON.parse(JSON.stringify(step.options || []))
}
step.isEditing = false
})
},
handleApprovalCancel() {
// 退
@ -2312,32 +2380,280 @@ export default {
required: true,
handlers: [],
options: [],
loading: false
loading: false,
isEditing: false,
originalData: null
},
{
name: '审核',
required: true,
handlers: [],
options: [],
loading: false
loading: false,
isEditing: false,
originalData: null
},
{
name: '会签',
required: false,
handlers: [],
options: [],
loading: false
loading: false,
isEditing: false,
originalData: null
},
{
name: '批准',
required: true,
handlers: [],
options: [],
loading: false
loading: false,
isEditing: false,
originalData: null
}
]
//
this.isResendModeFilled = false
this.resendFlowId = null
this.isProcessTitleEditing = false
this.originalProcessTitle = ''
},
//
handleEditStep(stepIndex) {
const step = this.approvalWorkflowSteps[stepIndex]
if (!step) {
return
}
//
step.originalData = {
handlers: JSON.parse(JSON.stringify(step.handlers || [])),
options: JSON.parse(JSON.stringify(step.options || []))
}
//
step.isEditing = true
},
//
handleSaveStep(stepIndex) {
const step = this.approvalWorkflowSteps[stepIndex]
if (!step) {
return
}
const userIds = (step.handlers || []).filter(Boolean)
if (userIds.length === 0) {
this.$message.warning('请至少选择一位处理人')
return
}
// flowId detail resendFlowId
let flowId = null
if (this.detail && this.detail.flowId) {
flowId = this.detail.flowId
} else if (this.resendFlowId) {
flowId = this.resendFlowId
}
if (!flowId) {
this.$message.error('缺少流程ID无法保存')
return
}
const request = {
...api.EDIT_APPROVAL_PROCESS,
params: {
flowId: flowId,
nodeName: step.name,
userIds
},
disableSuccessMsg: true
}
step.loading = true
this.$request(request)
.asyncThen(() => {
//
step.originalData = {
handlers: JSON.parse(JSON.stringify(step.handlers || [])),
options: JSON.parse(JSON.stringify(step.options || []))
}
// 退
step.isEditing = false
this.$message({
type: 'success',
message: '保存成功'
})
})
.asyncErrorCatch((err) => {
console.error('保存环节编辑失败:', err)
this.$message({
type: 'error',
message: err?.message || '保存失败,请重试'
})
})
.finally(() => {
step.loading = false
})
},
//
handleCancelEditStep(stepIndex) {
const step = this.approvalWorkflowSteps[stepIndex]
if (!step || !step.originalData) {
return
}
//
step.handlers = JSON.parse(JSON.stringify(step.originalData.handlers || []))
step.options = JSON.parse(JSON.stringify(step.originalData.options || []))
// 退
step.isEditing = false
},
//
handleEditProcessTitle() {
//
this.originalProcessTitle = this.approvalFormData.processTitle || ''
//
this.approvalWorkflowSteps.forEach((step) => {
step.originalData = {
handlers: JSON.parse(JSON.stringify(step.handlers || [])),
options: JSON.parse(JSON.stringify(step.options || []))
}
})
//
this.isProcessTitleEditing = true
},
//
handleSaveProcessTitle() {
const newTitle = (this.approvalFormData.processTitle || '').trim()
if (!newTitle) {
this.$message.warning('流程主题不能为空')
return
}
// flowId detail resendFlowId
let flowId = null
if (this.detail && this.detail.flowId) {
flowId = this.detail.flowId
} else if (this.resendFlowId) {
flowId = this.resendFlowId
}
if (!flowId) {
this.$message.error('缺少流程ID无法保存')
return
}
// nodeList
const nodeList = this.approvalWorkflowSteps.map((step, index) => ({
nodeName: step.name,
assignees: step.handlers,
nodeOrder: index + 1
}))
// nodeList, flowId, title, userId
const request = {
...api.EDIT_APPROVAL_PROCESS,
params: {
nodeList: nodeList,
flowId: flowId,
title: newTitle,
userId: getUserId()
},
disableSuccessMsg: true
}
this.$request(request)
.asyncThen(() => {
//
this.originalProcessTitle = newTitle
//
this.approvalWorkflowSteps.forEach((step) => {
step.originalData = {
handlers: JSON.parse(JSON.stringify(step.handlers || [])),
options: JSON.parse(JSON.stringify(step.options || []))
}
})
// 退
this.isProcessTitleEditing = false
this.$message({
type: 'success',
message: '保存成功'
})
//
if (flowId) {
// detail flowId
if (!this.detail) {
this.detail = {}
}
if (!this.detail.flowId) {
this.detail.flowId = flowId
}
this.getApprovalSpet()
}
})
.asyncErrorCatch((err) => {
console.error('保存失败:', err)
this.$message({
type: 'error',
message: err?.message || '保存失败,请重试'
})
})
},
//
handleCancelEditProcessTitle() {
//
this.approvalFormData.processTitle = this.originalProcessTitle || ''
//
this.approvalWorkflowSteps.forEach((step) => {
if (step.originalData) {
step.handlers = JSON.parse(JSON.stringify(step.originalData.handlers || []))
step.options = JSON.parse(JSON.stringify(step.originalData.options || []))
}
})
// 退
this.isProcessTitleEditing = false
},
handleApprovalFormSubmit() {
//
if (this.isResendModeFilled) {
// CONTINUE_APPROVAL_PROCESS
// resendFlowId flowId
const flowId = this.resendFlowId
if (!flowId) {
this.$message.error('缺少流程ID无法继续审批')
return
}
const request = {
...api.CONTINUE_APPROVAL_PROCESS,
params: {
flowId: flowId,
userId: getUserId()
},
disableSuccessMsg: true
}
this.approvalSubmitting = true
this.$request(request)
.asyncThen((resp) => {
console.log('审批提交成功')
this.$message({
type: 'success',
message: '审批提交成功'
})
this.isApprovalMode = false
this.isResendModeFilled = false
this.resendFlowId = null
this.approvalSubmitting = false
//
this.originalTableDataForApproval = []
this.originalPaginationForApproval = null
this.handleBack()
})
.asyncErrorCatch((err) => {
console.error('审批提交失败:', err)
this.$message({
type: 'error',
message: err?.message || '审批提交失败,请重试'
})
})
.finally(() => {
this.approvalSubmitting = false
})
} else {
// START_APPROVAL
// ID
const templateRowId = this.getDetailTemplateId()
if (!templateRowId) {
@ -2395,6 +2711,7 @@ export default {
.finally(() => {
this.approvalSubmitting = false
})
}
},
handleRemoteSearch(query, stepIndex) {
const step = this.approvalWorkflowSteps[stepIndex]
@ -3793,11 +4110,57 @@ export default {
font-size: 16px;
line-height: 24px;
font-weight: bolder;
margin-bottom: 8px;
margin-bottom: 8px !important;
color: #303133;
}
}
.approval-process-title {
display: flex;
flex-direction: column;
gap: 8px;
margin-bottom: 16px;
.description-label {
font-size: 16px;
line-height: 24px;
font-weight: bolder;
margin-bottom: 8px !important;
color: #303133;
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
.step-actions {
display: flex;
align-items: center;
gap: 8px;
flex-shrink: 0;
.edit-step-btn,
.save-step-btn,
.cancel-step-btn {
padding: 0;
font-size: 12px;
color: #409eff;
&:hover {
color: #66b1ff;
}
}
.cancel-step-btn {
color: #909399;
&:hover {
color: #a6a9ad;
}
}
}
}
}
.approval-workflow {
display: flex;
flex-direction: column;
@ -3807,7 +4170,6 @@ export default {
font-size: 14px;
font-weight: 600;
color: #303133;
margin-bottom: 8px;
}
.workflow-table {

View File

@ -110,7 +110,9 @@
v-for="(colConfig, index) in tableConfig.colConfigs"
v-slot:[colConfig.customHeadSlot]="{ column }"
>
<div v-if="colConfig.customHeadSlot" :key="index"> {{ column }} {{ colConfig }} </div>
<div v-if="colConfig.customHeadSlot" :key="index">
{{ column }} {{ colConfig }}
</div>
</template>
<template
@ -166,16 +168,7 @@
>
修改
</a>
<span style="width: 6px; display: inline-block"></span>
<a
v-if="row.status === 'DRAFT' && hasReportEditPermission() && row.returnNum > 0"
href="javascript:void(0)"
class="el-link el-link--primary"
@click.stop="handleEdit(row)"
>
重新发起
</a>
<span style="width: 6px; display: inline-block"></span>
<span v-if="row.status === 'DRAFT' && hasReportEditPermission() && row.returnNum === 0" style="width: 6px; display: inline-block"></span>
<!-- <a
v-if="row.status === 'APPROVING'"
href="javascript:void(0)"
@ -464,7 +457,9 @@
>
<div class="dialog-body-wrapper">
<div class="approval-process-title">
<div class="description-label"> 流程主题 <span class="required-mark">*</span> </div>
<div class="description-label">
流程主题 <span class="required-mark">*</span>
</div>
<el-input
v-model="launchProcessTitle"
maxlength="100"
@ -1858,10 +1853,13 @@ export default {
this.showReportDetail = false
this.currentReportDetail = null
},
handleReportDetailRefresh() {
handleReportDetailRefresh(payload) {
//
this.loadData()
//
//
if (payload && payload.keepOpen) {
return
}
this.closeReportDetail()
},
currentChange(currentPage) {

View File

@ -26,7 +26,7 @@
>
直送
</el-button>
<el-button v-else @click="handleLaunch">
<el-button @click="handleLaunch">
发起
</el-button>
<el-button type="primary" @click="handleEdit">
@ -42,7 +42,7 @@
直送
</el-button>
<el-button @click="handleResendApproval">
重新发起
发起
</el-button>
<el-button type="primary" @click="handleEdit">
修改
@ -53,10 +53,7 @@
<el-button @click="handleCancelEdit">
返回
</el-button>
<el-button v-if="canResend" type="primary" @click="handleResendApproval">
重新发起
</el-button>
<el-button v-else type="primary" :loading="saving" @click="handleSave">
<el-button type="primary" :loading="saving" @click="handleSave">
保存
</el-button>
</template>
@ -331,7 +328,7 @@
</section>
<!-- 审批流程 -->
<section v-if="reportDetail.status && reportDetail.status !== 'DRAFT' && detail.flowId" class="block-section">
<section v-if="reportDetail.status && reportDetail.status !== 'DRAFT' && detail.flowId && !isEditMode" class="block-section">
<div class="section-title">
审批流程
</div>
@ -372,7 +369,7 @@
</section>
<!-- 审批环节草稿状态下显示 -->
<section v-if="reportDetail.status === 'DRAFT'" class="block-section">
<section v-if="reportDetail.status === 'DRAFT' || reportDetail.status === 'REJECTED'" class="block-section">
<div class="section-title">
审批环节
</div>
@ -395,6 +392,7 @@
maxlength="100"
show-word-limit
placeholder="请输入流程主题"
@change="handleProcessTitleChange"
/>
</div>
<div class="workflow-table">
@ -629,6 +627,10 @@ export default {
saving: false, //
isEditingProcessTitle: false, //
editingProcessTitle: '', //
approvalFlowIdFromUsers: '', // ID
approvalCanSend: false, //
// watch/change
originalEditSnapshot: null, //
approvalWorkflowSteps: [
{
name: '校对',
@ -684,7 +686,7 @@ export default {
let processedNodes = this.flowNodes
if (rejectIndex !== -1) {
// REJECT
processedNodes = this.flowNodes.slice(0, rejectIndex + 1)
// processedNodes = this.flowNodes.slice(0, rejectIndex + 1)
} else {
// REJECT result "" APPROVING
const stayIndex = processedNodes.findIndex((node) => node.result === '待审批')
@ -745,22 +747,6 @@ export default {
opinion: opinion
})
})
} else if (this.progress && this.progress.length > 0) {
// flowNodes使 progress
this.progress.forEach((stage) => {
if (stage.steps && stage.steps.length > 0) {
stage.steps.forEach((step) => {
nodes.push({
title: stage.title || '审批节点',
userName: step.userName,
operateTime: step.approvalTime || step.handleTime || step.createTime,
result: step.result || step.status,
status: step.result || step.status,
opinion: step.opinion || step.remark || step.comment || null
})
})
}
})
}
return nodes
@ -981,11 +967,16 @@ export default {
templateVersion: data.templateVersion || '',
contentName: data.contentName || ''
}
this.reportDetail.processTitle = data.progressTitle
// flowStatus REJECTED"稿"
const flowStatus = data.flowStatus || ''
const createBy = data.createBy || ''
if (flowStatus) {
//
this.$set(this.reportDetail, 'status', flowStatus)
}
this.showTopDetail = {
processTitle: data.progressTitle || '',
processTitle: data.progressTitle,
createBy: createBy,
createTime: data.createTime || '',
currentNode: flowStatus === 'REJECTED' ? '编制' : (data.currentNode || ''),
@ -1374,7 +1365,8 @@ export default {
// report.vue
handleLaunch() {
const reportId = this.reportDetail.reportId || this.reportDetail.id || this.detail.reportId || this.detail.id
const flowId = this.detail.flowId || this.reportDetail.flowId
const flowId = this.approvalFlowIdFromUsers || this.detail.flowId || this.reportDetail.flowId
const canSend = this.canResend
if (!reportId) {
this.$message.error('缺少报告ID无法发起审批')
@ -1392,16 +1384,34 @@ export default {
type: 'warning'
})
.then(() => {
let request = null
if (canSend) {
// 使 flowId
const continueFlowId = this.approvalFlowIdFromUsers || flowId
if (!continueFlowId) {
this.$message.error('缺少流程ID无法继续发起审批')
return
}
request = {
...api.CONTINUE_REPORT_APPROVAL,
params: {
flowId: continueFlowId,
userId: getUserId()
},
disableSuccessMsg: true
}
} else {
const submitData = {
reportId: reportId,
flowId: flowId,
userId: getUserId()
}
const request = {
request = {
...api.ADD_REPORT,
params: submitData,
disableSuccessMsg: true
}
}
this.launching = true
this.$request(request)
@ -1499,7 +1509,7 @@ export default {
// 稿
loadApprovalUsers(flowId) {
if (!flowId) {
return
return Promise.resolve()
}
const request = {
...api.GET_REPORT_APPROVAL_USERS,
@ -1508,15 +1518,47 @@ export default {
},
disableSuccessMsg: true
}
this.$request(request)
return this.$request(request)
.asyncThen((resp) => {
console.log('获取审批流程信息:', resp)
// ID
const meta = this.parseApprovalUsersMeta(resp)
this.approvalCanSend = !!meta.canSend
this.approvalFlowIdFromUsers = meta.flowId || flowId || ''
//
if (meta.title) {
this.reportDetail.processTitle = meta.title
this.showTopDetail.processTitle = meta.title
//
if (this.isEditMode) {
this.editFormData.processTitle = meta.title
}
}
this.fillApprovalUsersData(resp, this.approvalWorkflowSteps)
})
.asyncErrorCatch((err) => {
console.error('获取审批流程信息失败:', err)
throw err
})
},
// ID/
parseApprovalUsersMeta(resp) {
const meta = { flowId: '', canSend: false, title: '' }
const candidate = resp?.data ?? resp
const pickFrom = (obj) => {
if (!obj || Array.isArray(obj)) return
meta.flowId = meta.flowId || obj.flowId || obj.id || obj.flowid || ''
meta.canSend = meta.canSend || obj.canSend || obj.canResend || false
meta.title = meta.title || obj.progressTitle || obj.processTitle || obj.title || ''
}
if (candidate && !Array.isArray(candidate)) {
pickFrom(candidate)
if (candidate.data && !Array.isArray(candidate.data)) {
pickFrom(candidate.data)
}
}
return meta
},
// report.vue
fillApprovalUsersData(resp, workflowSteps) {
//
@ -1669,13 +1711,16 @@ export default {
},
//
handleHandlerChange(stepIndex, selectedIds) {
//
//
},
//
handleResendApproval() {
//
this.handleResatrtLaunch()
},
handleProcessTitleChange() {
//
},
// 稿
loadLaunchApprovalUsers(flowId) {
if (!flowId) {
@ -1700,7 +1745,7 @@ export default {
})
},
//
handleEdit() {
async handleEdit() {
//
this.originalReportDetail = JSON.parse(JSON.stringify(this.reportDetail))
//
@ -1735,14 +1780,19 @@ export default {
this.fileList = []
}
this.selectedFile = null
// 稿
this.isEditMode = true
// 稿/
if (this.reportDetail.status === 'DRAFT') {
const flowId = this.detail.flowId || this.reportDetail.flowId
if (flowId && (!this.approvalWorkflowSteps[0].handlers || this.approvalWorkflowSteps[0].handlers.length === 0)) {
this.loadApprovalUsers(flowId)
if (flowId) {
try {
await this.loadApprovalUsers(flowId)
} catch (e) {
// ignore
}
}
this.isEditMode = true
}
this.originalEditSnapshot = this.buildEditSnapshot()
},
//
handleCancelEdit() {
@ -1770,6 +1820,7 @@ export default {
}
this.fileList = []
this.selectedFile = null
this.originalEditSnapshot = null
this.isEditMode = false
//
if (this.$refs.editForm) {
@ -1862,20 +1913,73 @@ export default {
this.submitEdit()
}
},
buildEditSnapshot() {
const normalize = (v) => (v == null ? '' : v)
const normalizeSteps = (steps) =>
(steps || []).map((s) => ({
name: s.name,
handlers: (s.handlers || []).filter(Boolean).slice().sort()
}))
//
return {
form: {
title: normalize(this.editFormData?.title),
manufacturerName: normalize(this.editFormData?.manufacturerName),
modelName: normalize(this.editFormData?.modelName),
manufacturerAbbreviation: normalize(this.editFormData?.manufacturerAbbreviation),
modelAbbreviation: normalize(this.editFormData?.modelAbbreviation),
productNumber: normalize(this.editFormData?.productNumber),
module: normalize(this.editFormData?.module),
plate: normalize(this.editFormData?.plate),
platform: normalize(this.editFormData?.platform),
series: normalize(this.editFormData?.series),
marketSegment: normalize(this.editFormData?.marketSegment),
projectName: normalize(this.editFormData?.projectName),
projectNumber: normalize(this.editFormData?.projectNumber),
explanation: normalize(this.editFormData?.explanation),
fileUrl: normalize(this.editFormData?.fileUrl),
fileName: normalize(this.editFormData?.fileName)
},
processTitle: (this.editFormData?.processTitle || '').trim(),
steps: normalizeSteps(this.approvalWorkflowSteps)
}
},
diffEditSnapshot(original, current) {
const isSame = (a, b) => JSON.stringify(a) === JSON.stringify(b)
const baseChanged =
!original ||
!isSame(original.form, current.form) ||
!!this.selectedFile //
const approvalChanged =
!original ||
original.processTitle !== current.processTitle ||
!isSame(original.steps, current.steps)
return { baseChanged, approvalChanged }
},
hasAnyEditChange() {
const current = this.buildEditSnapshot()
const { baseChanged, approvalChanged } = this.diffEditSnapshot(this.originalEditSnapshot, current)
return baseChanged || approvalChanged
},
//
submitEdit() {
const submitData = async () => {
try {
//
if (!this.hasAnyEditChange()) {
this.isEditMode = false
this.$message({
type: 'info',
message: '未修改,无需保存'
})
return
}
//
if (this.selectedFile) {
try {
const fileUrl = await this.handleFileUpload()
this.editFormData.fileUrl = fileUrl || ''
this.editFormData.fileName = this.selectedFile.name
} catch (err) {
console.error('文件上传失败:', err)
this.$message.error('文件上传失败,请重试')
return
}
}
const reportId = this.reportDetail.reportId || this.reportDetail.id
@ -1884,54 +1988,119 @@ export default {
return
}
// 稿
const includeApprovalInSave = !this.canResend
const shouldUpdateApprovalProcess = this.canResend
const { processTitle, ...restForm } = this.editFormData
const params = {
reportId: reportId,
flowId: this.detail.flowId,
...this.editFormData,
...restForm,
createBy: getUserId(),
userId: getUserId()
}
// 稿
if (this.reportDetail.status === 'DRAFT') {
const nodeList = this.approvalWorkflowSteps.map((step, index) => ({
if (includeApprovalInSave) {
params.processTitle = processTitle || ''
params.nodeList = this.approvalWorkflowSteps.map((step, index) => ({
nodeName: step.name,
assignees: step.handlers,
nodeOrder: index + 1
}))
params.nodeList = nodeList
}
this.saving = true
// watch/change
const currentSnap = this.buildEditSnapshot()
const { baseChanged, approvalChanged } = this.diffEditSnapshot(this.originalEditSnapshot, currentSnap)
// canResend true shouldUpdateApprovalProcess true updateApprovalProcess
// canResend false includeApprovalInSave true EDIT_REPORT
const needUpdateApprovalProcess =
shouldUpdateApprovalProcess && approvalChanged
// EDIT_REPORT
// 1. EDIT_REPORT
// 2. includeApprovalInSave true EDIT_REPORT
// 3. shouldUpdateApprovalProcess true EDIT_REPORT
const shouldOnlyUpdateApprovalProcess = shouldUpdateApprovalProcess && approvalChanged && !baseChanged
const needUpdateReportBase =
!shouldOnlyUpdateApprovalProcess && (
baseChanged ||
(includeApprovalInSave && approvalChanged)
)
if (needUpdateReportBase) {
console.log('needUpdateReportBase', needUpdateReportBase)
const request = {
...api.EDIT_REPORT,
params: params,
disableSuccessMsg: true
}
await this.$request(request).asyncThen(() => {})
}
if (needUpdateApprovalProcess) {
console.log('needUpdateApprovalProcess', needUpdateApprovalProcess)
await this.updateApprovalProcess()
}
this.saving = true
this.$request(request)
.asyncThen((resp) => {
this.saving = false
this.isEditMode = false
//
this.loadReportDetailFromApi(reportId, this.detail.flowId)
// + 稿/ handleResatrtLaunch
const currentFlowId = this.detail.flowId || this.reportDetail.flowId
this.loadReportDetailFromApi(reportId, currentFlowId)
if (this.reportDetail.status === 'DRAFT' && currentFlowId) {
//
this.loadApprovalUsers(currentFlowId)
}
//
this.originalEditSnapshot = this.buildEditSnapshot()
this.$message({
type: 'success',
message: '保存成功'
})
//
this.$emit('refresh')
})
.asyncErrorCatch((err) => {
//
this.$emit('refresh', { keepOpen: true })
} catch (err) {
console.error('保存失败:', err)
this.$message.error(err?.message || '保存失败,请重试')
} finally {
this.saving = false
this.$message.error('保存失败,请重试')
})
}
}
submitData()
},
//
updateApprovalProcess() {
const flowId = this.detail.flowId || this.reportDetail.flowId
if (!flowId) {
this.$message.error('缺少流程ID无法保存审批环节')
return Promise.reject(new Error('缺少流程ID'))
}
const nodeList = this.approvalWorkflowSteps.map((step, index) => ({
nodeName: step.name,
assignees: step.handlers,
nodeOrder: index + 1
}))
const request = {
...api.EDIT_APPROVAL_PROCESS,
params: {
nodeList: nodeList,
flowId: flowId,
title: this.editFormData.processTitle || '',
userId: getUserId()
},
disableSuccessMsg: true
}
return this.$request(request)
.asyncThen(() => {})
.asyncErrorCatch((err) => {
console.error('更新审批环节失败:', err)
this.$message.error(err?.message || '更新审批环节失败,请重试')
throw err
})
},
//
handleEditProcessTitle() {
this.isEditingProcessTitle = true

View File

@ -43,24 +43,6 @@
v-for="(colConfig, index) in tableConfig.colConfigs"
v-slot:[colConfig.customSlot]="{ row, rowIndex }"
>
<div v-if="colConfig.customSlot === 'options'" :key="'op' + index + '' + rowIndex">
<a
href="javascript:void(0)"
class="el-link el-link--primary"
@click.stop="handleRowView(row)"
>查看</a
>
<!-- <span
v-if="row.dataType === '数据维护'"
style="width: 6px; display: inline-block"
></span>
<a
href="javascript:void(0)"
class="el-link el-link--primary"
@click.stop="handleRowBack(row)"
>退回</a
> -->
</div>
<div v-if="colConfig.customSlot === 'processTitle'" :key="'pt' + index + '' + rowIndex">
<a
href="javascript:void(0)"
@ -157,7 +139,7 @@ import ApprovalProgressDetail from './approvalProgressDetail.vue'
import ReportDetail from './reportDetail.vue'
import ModelDetail from './modelDetail.vue'
import { getUserId } from '@/utils'
import api from '@/api/demo'
import api from '@/api'
export default {
name: 'TodoPage',
components: {
@ -229,14 +211,6 @@ export default {
minWidth: '150',
align: 'center',
formatter: this.formatDateTime
},
{
prop: 'options',
label: '操作',
customSlot: 'options',
align: 'center',
width: '100',
fixed: 'right'
}
],
seqType: '',