From 36444be2f90fbd304512feb9475b5b32b5c78453 Mon Sep 17 00:00:00 2001 From: weizong song Date: Tue, 20 Jan 2026 13:15:29 +0800 Subject: [PATCH] up --- rebuild.sh | 1 + src/api/flow/index.js | 20 ++ src/components/BudgetSourcePickerField.vue | 49 ++++- src/components/ContractSignField.vue | 162 +++++++++++++--- src/utils/formBuilder.js | 203 ++++++++++++--------- src/views/flow/DesktopForm.vue | 2 - src/views/flow/create.vue | 115 +++++++++++- src/views/flow/list.vue | 81 +++++++- 自定义字段渲染整理.md | 1 + 错误诊断和解决方案.md | 1 + 10 files changed, 505 insertions(+), 130 deletions(-) diff --git a/rebuild.sh b/rebuild.sh index 16b2131..d404ab9 100644 --- a/rebuild.sh +++ b/rebuild.sh @@ -123,3 +123,4 @@ echo "" + diff --git a/src/api/flow/index.js b/src/api/flow/index.js index d0d3273..526f4e7 100644 --- a/src/api/flow/index.js +++ b/src/api/flow/index.js @@ -339,3 +339,23 @@ export function getRelationList(flowId, isLoading = false) { isLoading }) } + +// 打捞流程至付款流程 +export function salvageFlow(flowId, isLoading = true) { + return request({ + method: 'post', + url: '/api/oa/flow/salvage', + data: { flow_id: flowId }, + isLoading + }) +} + +// 取消打捞 +export function cancelSalvage(flowId, isLoading = true) { + return request({ + method: 'post', + url: '/api/oa/flow/cancel-salvage', + data: { flow_id: flowId }, + isLoading + }) +} diff --git a/src/components/BudgetSourcePickerField.vue b/src/components/BudgetSourcePickerField.vue index 87e9fab..6f52f7a 100644 --- a/src/components/BudgetSourcePickerField.vue +++ b/src/components/BudgetSourcePickerField.vue @@ -219,8 +219,49 @@ +
+
抵消预付账款
+ + + {{ node.label }} + + + 预算: + {{ formatAmount(data.budget_amount) }} + + + 已用: + {{ formatAmount(data.used_amount || 0) }} + + + 执行率: + + {{ formatExecutionRate(data.execution_rate || 0) }} + + + + + +
+
暂无数据 @@ -462,12 +503,16 @@ export default { lastYearCarryoverTree() { return (this.treeData || []).filter((n) => n?.budget_type === "last_year_carryover"); }, + offsetPrepaidTree() { + return (this.treeData || []).filter((n) => n?.budget_type === "offset_prepaid"); + }, budgetTypeMap() { return { department: "部门预算", project: "自有账户", special_fund: "专项资金", last_year_carryover: "上一年结转资金", + offset_prepaid: "抵消预付账款", }; }, // 分配总额 @@ -624,6 +669,7 @@ export default { this.$refs.projectTreeRef, this.$refs.specialFundTreeRef, this.$refs.lastYearCarryoverTreeRef, + this.$refs.offsetPrepaidTreeRef, ].filter(Boolean); const nodes = []; refs.forEach((tree) => { @@ -646,6 +692,7 @@ export default { this.$refs.projectTreeRef, this.$refs.specialFundTreeRef, this.$refs.lastYearCarryoverTreeRef, + this.$refs.offsetPrepaidTreeRef, ].filter(Boolean); refs.forEach((tree) => { if (typeof tree.setCheckedKeys === "function") { diff --git a/src/components/ContractSignField.vue b/src/components/ContractSignField.vue index f719d9f..bb70f9d 100644 --- a/src/components/ContractSignField.vue +++ b/src/components/ContractSignField.vue @@ -96,7 +96,7 @@ - + - + - + - + @@ -328,7 +328,6 @@ import { getContractByFlowId, createContract, getBudgetYearOptions, - save, } from "@/api/flow"; import { userListNoAuth, departmentListNoAuth } from "@/api/common"; @@ -439,17 +438,17 @@ export default { // 监听多选下拉变化,触发校验 'form.owner_department_ids_array'() { if (this.$refs.formRef) { - this.$refs.formRef.validateField('owner_department_ids', () => {}); + this.$refs.formRef.validateField('owner_department_ids_array', () => {}); } }, 'form.handler_admin_ids_array'() { if (this.$refs.formRef) { - this.$refs.formRef.validateField('handler_admin_ids', () => {}); + this.$refs.formRef.validateField('handler_admin_ids_array', () => {}); } }, 'form.apply_handler_id_array'() { if (this.$refs.formRef) { - this.$refs.formRef.validateField('apply_handler_id', () => {}); + this.$refs.formRef.validateField('apply_handler_id_array', () => {}); } }, 'form.pay_plans'() { @@ -463,6 +462,16 @@ export default { this.$refs.formRef.validateField('amount_description', () => {}); } }, + // 监听合同类型变化,动态调整预算年度和项目经费来源的必填校验 + 'form.contract_type_id'() { + // 当合同类型改变时,重新验证相关字段 + if (this.$refs.formRef) { + this.$nextTick(() => { + this.$refs.formRef.validateField('fund_source_year_id'); + this.$refs.formRef.validateField('fund_source_budget_data_id'); + }); + } + }, }, async mounted() { // 组件初始化时,如果value为空但有flowId,尝试从流程数据恢复合同 @@ -514,7 +523,21 @@ export default { trigger: 'blur' } ], - budget_amount: [{ required: true, message: "请填写项目预算金额", trigger: "blur" }], + budget_amount: [ + { required: true, message: "请填写项目预算金额", trigger: "blur" }, + { + validator: (rule, value, callback) => { + if (value === null || value === undefined || value === '') { + callback(new Error('请填写项目预算金额')); + } else if (value === 0) { + callback(new Error('项目预算金额不能为0')); + } else { + callback(); + } + }, + trigger: 'blur' + } + ], contract_type_id: [{ required: true, message: "请选择合同类型", trigger: "change" }], sign_date: [{ required: true, message: "请选择签订日期", trigger: "change" }], apply_date: [{ required: true, message: "请选择申请日期", trigger: "change" }], @@ -531,18 +554,56 @@ export default { // 编辑时全量校验(与合同编辑页面对齐) this.rules = { ...baseRules, - fund_source_year_id: [{ required: true, message: "请选择预算年度", trigger: "change" }], - fund_source_budget_data_id: [{ required: true, message: "请选择项目经费来源", trigger: "change" }], + fund_source_year_id: [ + { + validator: (rule, value, callback) => { + // 默认必填,只有当合同类型明确是"收入类"时才撤销必填校验 + const contractTypeName = this.getContractTypeName(); + if (contractTypeName === '收入类') { + // 收入类不需要必填 + callback(); + } else { + // 其他情况(包括未选择合同类型)都需要必填 + if (!value) { + callback(new Error('请选择预算年度')); + } else { + callback(); + } + } + }, + trigger: 'change' + } + ], + fund_source_budget_data_id: [ + { + validator: (rule, value, callback) => { + // 默认必填,只有当合同类型明确是"收入类"时才撤销必填校验 + const contractTypeName = this.getContractTypeName(); + if (contractTypeName === '收入类') { + // 收入类不需要必填 + callback(); + } else { + // 其他情况(包括未选择合同类型)都需要必填 + if (!value) { + callback(new Error('请选择项目经费来源')); + } else { + callback(); + } + } + }, + trigger: 'change' + } + ], is_government_purchase: [{ required: true, message: "请选择是否为政府采购", trigger: "change" }], purchase_category_id: [{ required: true, message: "请选择采购类别", trigger: "change" }], purchase_method_id: [{ required: true, message: "请选择采购方式", trigger: "change" }], is_accepted: [{ required: true, message: "请选择是否验收", trigger: "change" }], - handler_admin_ids: [ + handler_admin_ids_array: [ { required: true, validator: (rule, value, callback) => { - const ids = this.form.handler_admin_ids_array; - if (!ids || !Array.isArray(ids) || ids.length === 0) { + const ids = Array.isArray(value) ? value : []; + if (ids.length === 0) { callback(new Error('请选择合同签订/变更经办人')); } else { callback(); @@ -551,12 +612,12 @@ export default { trigger: ['change', 'blur'] } ], - apply_handler_id: [ + apply_handler_id_array: [ { required: true, validator: (rule, value, callback) => { - const ids = this.form.apply_handler_id_array; - if (!ids || !Array.isArray(ids) || ids.length === 0) { + const ids = Array.isArray(value) ? value : []; + if (ids.length === 0) { callback(new Error('请选择申请科室经办人')); } else { callback(); @@ -565,12 +626,12 @@ export default { trigger: ['change', 'blur'] } ], - owner_department_ids: [ + owner_department_ids_array: [ { required: true, validator: (rule, value, callback) => { - const ids = this.form.owner_department_ids_array; - if (!ids || !Array.isArray(ids) || ids.length === 0) { + const ids = Array.isArray(value) ? value : []; + if (ids.length === 0) { callback(new Error('请选择科室')); } else { callback(); @@ -614,12 +675,30 @@ export default { ] }; }, + // 获取合同类型名称 + getContractTypeName() { + if (!this.form.contract_type_id) { + return null; + } + const contractType = this.contractTypeOptions.find(type => type.id === this.form.contract_type_id); + return contractType ? contractType.name : null; + }, handleFundSourceYearChange() { this.form.fund_source_budget_data_id = null; if (this.form.fund_source_year_id) { this.fetchFundSourceOptions(this.form.fund_source_year_id); } }, + // 处理合同类型变化 + handleContractTypeChange() { + // 当合同类型改变时,重新验证预算年度和项目经费来源 + if (this.$refs.formRef) { + this.$nextTick(() => { + this.$refs.formRef.validateField('fund_source_year_id'); + this.$refs.formRef.validateField('fund_source_budget_data_id'); + }); + } + }, async fetchBudgetYearOptions() { try { const response = await getBudgetYearOptions(false); @@ -829,7 +908,41 @@ export default { // 再次清除校验状态,确保填充数据后不会触发校验 this.$nextTick(() => { if (this.$refs.formRef) { - this.$refs.formRef.clearValidate(); + // 如果是编辑模式,在数据加载完成后,需要正确设置多选字段的校验状态 + if (this.isEditMode()) { + // 延迟一下,确保DOM已更新和数据已填充 + this.$nextTick(() => { + if (this.$refs.formRef) { + // 对于多选字段,如果数组有值,清除校验错误;如果为空,触发校验显示错误 + // 这样确保编辑模式下,已填充的字段不显示错误,未填充的字段显示错误 + const fieldsToCheck = [ + { prop: 'owner_department_ids_array', arrayField: 'owner_department_ids_array' }, + { prop: 'handler_admin_ids_array', arrayField: 'handler_admin_ids_array' }, + { prop: 'apply_handler_id_array', arrayField: 'apply_handler_id_array' }, + ]; + + fieldsToCheck.forEach(({ prop, arrayField }) => { + const ids = this.form[arrayField]; + if (ids && Array.isArray(ids) && ids.length > 0) { + // 有值,清除该字段的校验错误 + this.$refs.formRef.clearValidate(prop); + } else { + // 无值,先清除之前的错误状态,然后触发校验显示错误 + // 这样可以确保校验状态正确更新 + this.$refs.formRef.clearValidate(prop); + this.$nextTick(() => { + if (this.$refs.formRef) { + this.$refs.formRef.validateField(prop, () => {}); + } + }); + } + }); + } + }); + } else { + // 新建模式,清除所有校验状态 + this.$refs.formRef.clearValidate(); + } } }); }, @@ -1222,11 +1335,12 @@ export default { this.dialogVisible = false; Message.success(contractId ? "合同更新成功" : "合同创建成功"); - // 如果是新建合同(不是更新)且有flowId,自动保存到流程字段 + // 如果是新建合同(不是更新)且有flowId,自动保存到流程字段(轻量接口) if (!contractId && this.flowId && this.fieldName) { try { - await save(this.flowId, { - [this.fieldName]: String(data.id), + await request.post(`/api/oa/flow/save-field/${this.flowId}`, { + field_name: this.fieldName, + field_value: String(data.id), }); // 静默保存,不显示提示 } catch (e) { diff --git a/src/utils/formBuilder.js b/src/utils/formBuilder.js index 33c7b00..3f18981 100644 --- a/src/utils/formBuilder.js +++ b/src/utils/formBuilder.js @@ -1420,6 +1420,23 @@ export default function formBuilder( ); break; default: + // flow_title 在只读模式下,需要添加发起人和创建时间后缀 + let textDisplayValue = target[info.name] || ""; + if (info.name === "flow_title" && this.config && this.config.flow) { + // 优先从 logs[0].user.name 获取发起人,其次从 flow.creator.name + const firstLogCreator = this.logs && this.logs.length > 0 ? this.logs[0].user?.name : null; + const flowCreator = this.config.flow.creator?.name || null; + const creator = firstLogCreator || flowCreator || ""; + const createdAt = this.config.flow.created_at; + const formattedDate = createdAt + ? moment(createdAt).format("YYYY-MM-DD H:mm") + : ""; + // 格式化后缀:【发起人 | 创建时间】,格式:yyyy-mm-dd H:i + if (creator || formattedDate) { + const suffix = `【${creator || ""} | ${formattedDate}】`; + textDisplayValue = textDisplayValue + suffix; + } + } formItem = h( "span", { @@ -1427,7 +1444,7 @@ export default function formBuilder( color: "#333", }, }, - target[info.name] + textDisplayValue ); } } @@ -1563,8 +1580,9 @@ export default function formBuilder( }, isJointly ? [info._writeable ? formItem : "", jointlySignContent] - : [ - (() => { + : (() => { + // 获取字段值显示内容 + let fieldValueDisplay = (() => { if (info.name === "flow_title") { return formItem; } @@ -1582,95 +1600,106 @@ export default function formBuilder( if ((log && log.status) || log?.user?.id === this.$store.state.user.adminId || this.logs.length === 0) { return formItem; } + // 如果没有符合条件的 log,也返回 formItem 以确保显示 + return formItem; } - })(), - (() => { - // 检查 is_sign 是否为真值(支持 1, true, "1" 等) - if (info.is_sign && (info.is_sign === 1 || info.is_sign === true || info.is_sign === "1")) { - let log = null; - - // 方法1: 从 jointlySignLog 中查找(检查所有字段) - if (this.jointlySignLog && this.jointlySignLog.length > 0) { - log = this.jointlySignLog.find((log) => { - if (log.status > 0 && log.user && log.user.sign_file && log.user.sign_file.url) { - try { - const data = JSON.parse(log.data); - // 检查 data 中是否有匹配当前字段的条目 - return Object.values(data).some( - (value) => - value && - typeof value === 'object' && - value.custom_field_id === info.id - ); - } catch (e) { - return false; + })(); + + // 检查是否有签名需要显示 + let signLog = null; + if (info.is_sign && (info.is_sign === 1 || info.is_sign === true || info.is_sign === "1")) { + // 方法1: 从 jointlySignLog 中查找(检查所有字段) + if (this.jointlySignLog && this.jointlySignLog.length > 0) { + signLog = this.jointlySignLog.find((log) => { + if (log.status > 0 && log.user && log.user.sign_file && log.user.sign_file.url) { + try { + const data = JSON.parse(log.data); + // 检查 data 中是否有匹配当前字段的条目 + return Object.values(data).some( + (value) => + value && + typeof value === 'object' && + value.custom_field_id === info.id + ); + } catch (e) { + return false; + } + } + return false; + }); + } + + // 方法2: 如果没找到,从 this.logs 中查找(必须匹配字段ID和类型) + if (!signLog && this.logs && this.logs.length > 0) { + signLog = this.logs.find( + (log) => + log.status > 0 && + log.user && + log.user.sign_file && + log.user.sign_file.url && + log.node?.fields?.findIndex( + (field) => + field?.field_id === info.id && + field.type === "write" + ) !== -1 + ); + } + } + + // 如果找到签名日志,重新组织显示顺序 + if (signLog && signLog.status > 0 && signLog.user && signLog.user.sign_file && signLog.user.sign_file.url) { + const signDate = signLog.updated_at + ? this.$moment(signLog.updated_at).format("YYYY年MM月DD日") + : ""; + const signImageUrl = signLog.user.sign_file.url; + + return [ + // 1. input框的内容(独占一行) + fieldValueDisplay, + // 2. 签名图片(容器占一行) + h("div", { + style: { + "margin-top": "8px", + "margin-bottom": "8px", + } + }, [ + h("img", { + style: { + display: "block", + "max-height": "80px", + "max-width": "100px", + cursor: "pointer", + }, + attrs: { + src: signImageUrl, + alt: signLog.user?.name || "", + }, + on: { + click: () => { + this.$bus.$emit("online-file", signImageUrl); } } - return false; - }); - } - - // 方法2: 如果没找到,从 this.logs 中查找(必须匹配字段ID和类型) - if (!log && this.logs && this.logs.length > 0) { - log = this.logs.find( - (log) => - log.status > 0 && - log.user && - log.user.sign_file && - log.user.sign_file.url && - log.node?.fields?.findIndex( - (field) => - field?.field_id === info.id && - field.type === "write" - ) !== -1 - ); - } - - // 只有当找到匹配当前字段的log时才显示 - if (log && log.status > 0 && log.user && log.user.sign_file && log.user.sign_file.url) { - return h("div", { + }) + ]), + // 3. 日期(独占一行) + h("div", { + style: { + "margin-top": "4px", + } + }, [ + h("span", { style: { - "margin-top": "8px", - display: "flex", - "align-items": "center", - gap: "8px", + "font-size": "16px", + color: "#000", } - }, [ - h("el-image", { - style: { - "max-height": "80px", - "max-width": "100px", - display: "block", - }, - props: { - src: log.user.sign_file.url, - fit: "contain", - alt: log.user?.name || "", - "preview-src-list": [log.user.sign_file.url], - lazy: false, - }, - attrs: { - src: log.user.sign_file.url, - }, - }), - h( - "div", - { - style: { - "font-size": "16px", - color: "#000", - } - }, - log.updated_at - ? this.$moment(log.updated_at).format("YYYY年MM月DD日") - : "" - ), - ]); - } - } - return null; - })(), - ] + }, signDate) + ]) + ]; + } else { + // 没有签名时,只显示字段值 + return [fieldValueDisplay]; + } + })() ); } } diff --git a/src/views/flow/DesktopForm.vue b/src/views/flow/DesktopForm.vue index 472e215..f03f246 100644 --- a/src/views/flow/DesktopForm.vue +++ b/src/views/flow/DesktopForm.vue @@ -440,8 +440,6 @@ export default { padding: 8px 12px; margin: -1px 0 0 -1px; } -::v-deep .el-form-item__content { -} ::v-deep .el-radio, .el-radio__input { line-height: 1.5; } diff --git a/src/views/flow/create.vue b/src/views/flow/create.vue index 0e94cfe..09674a7 100644 --- a/src/views/flow/create.vue +++ b/src/views/flow/create.vue @@ -281,10 +281,26 @@ @@ -929,12 +945,38 @@ export default { return (field && (field.key || field.field_key)) ? (field.key || field.field_key) : ''; }, - // 相关事前流程字段是否渲染:目前仅对 oa_custom_model/out_custom_model 做“空值隐藏” + // 相关事前流程字段是否渲染: + // 1. 最顶层拦截:如果画布配置中 visible === false,则不显示 + // 2. 对 oa_custom_model/out_custom_model 做"空值隐藏" + // 3. 对 meeting_minutes 和 attachment/file 做"空值隐藏" shouldRenderPlannedField(expenditureId, field) { if (!field) return false; + + // 最顶层拦截:如果画布配置中关闭了元素的显示(visible === false),则不显示 + if (field.visible === false) { + return false; + } + + // oa_custom_model/out_custom_model 类型:仅当有绑定值时才显示 if (field.element_type === 'oa_custom_model' || field.element_type === 'out_custom_model') { return this.getOaCustomModelBindings(expenditureId, field).length > 0; } + + // meeting_minutes 类型:仅当有会议纪要ID时才显示 + if (field.element_type === 'meeting_minutes') { + const meetingMinuteId = this.extractMeetingMinuteId( + this.getIndirectFieldValue(expenditureId, this.getTplFieldKey(field)) + ); + return meetingMinuteId !== null && meetingMinuteId !== undefined; + } + + // attachment/file 类型:仅当有文件项时才显示 + if (field.element_type === 'attachment' || field.element_type === 'file') { + const fileItems = this.getPlannedFileItems(expenditureId, field); + return fileItems && fileItems.length > 0; + } + + // 其他类型:默认显示(已通过 visible 检查) return true; }, @@ -1692,6 +1734,47 @@ export default { }, // ---------- 事前流程附件/文件 ---------- + // 构建完整的文件URL(如果是相对路径,自动拼接当前域名) + buildFileUrl(path) { + if (!path) return null; + + const pathStr = String(path).trim(); + if (!pathStr) return null; + + // 如果已经是完整URL(http:// 或 https://),直接返回 + if (pathStr.startsWith('http://') || pathStr.startsWith('https://')) { + return pathStr; + } + + // 如果是相对路径(以 / 开头),拼接当前域名 + if (pathStr.startsWith('/')) { + const origin = window.location.origin; + return `${origin}${pathStr}`; + } + + // 其他情况,尝试拼接(可能是 storage/files/xxx 这种格式) + if (pathStr.includes('/')) { + const origin = window.location.origin; + return `${origin}/${pathStr.replace(/^\//, '')}`; + } + + // 无法处理的格式,返回原始值 + return pathStr; + }, + + // 处理附件点击 + handlePlannedFileClick(file) { + if (file.url) { + try { + window.open(file.url, '_blank'); + } catch (error) { + this.$message.error('打开文件失败:' + error.message); + } + } else { + this.$message.warning('文件链接不可用'); + } + }, + getPlannedFileItems(expenditureId, field) { const v = this.getIndirectFieldValue(expenditureId, field?.key); if (!v) return []; @@ -1701,19 +1784,33 @@ export default { const s = x.trim(); if (!s) return null; const name = s.split('/').pop(); - return { name: name || `附件${idx + 1}`, url: s }; + const url = this.buildFileUrl(s); + return { name: name || `附件${idx + 1}`, url }; } if (typeof x === 'object') { - const url = x.url || x.path || x.file_url || x.download_url || x.href || x.preview_url; + // 尝试从多个可能的字段中获取路径 + let rawPath = x.url || x.path || x.file_url || x.download_url || x.href || x.preview_url || x.value || x.file_path || x.folder; + + // 如果还是没有,检查对象的所有值,看是否有字符串类型的路径 + if (!rawPath) { + for (const [key, value] of Object.entries(x)) { + if (typeof value === 'string' && (value.includes('/') || value.includes('storage') || value.includes('files'))) { + rawPath = value; + break; + } + } + } + + const url = rawPath ? this.buildFileUrl(rawPath) : null; const name = x.original_name || x.file_name || x.name || x.filename || x.originalName || - (url ? String(url).split('/').pop() : null); - if (url || name) return { name: name || `附件${idx + 1}`, url }; - return null; + (url ? String(url).split('/').pop() : null) || + (rawPath ? String(rawPath).split('/').pop() : null); + return (url || name) ? { name: name || `附件${idx + 1}`, url } : null; } return null; }; @@ -2644,7 +2741,7 @@ export default { table-layout: fixed; } ::v-deep .el-descriptions-item__label { - width: 200px; + width: 250px; white-space: nowrap; } ::v-deep .el-descriptions-item__content { diff --git a/src/views/flow/list.vue b/src/views/flow/list.vue index 845fc32..9669e74 100644 --- a/src/views/flow/list.vue +++ b/src/views/flow/list.vue @@ -397,7 +397,17 @@ content: '点击工作名称查看简要。\n批量审批请先选择流程类型,并勾选同一节点的流程。', }" - > + > + + = cutoffDate) { + this.$message.warning("只有2026-01-01之前创建的流程可以打捞"); + return; + } + this.handleSalvage(row); + break; + case "cancel_salvage": + if (!row.is_salvaged) { + this.$message.warning("该流程未被打捞"); + return; + } + this.handleCancelSalvage(row); + break; default: } }, + async handleSalvage(row) { + try { + await this.$confirm("确认打捞该流程至付款流程?", "提示", { + type: "warning", + }); + const res = await salvageFlow(row.id); + // 响应拦截器已经处理,成功时返回的是data部分(字符串消息) + this.$message.success(res || "打捞成功"); + this.getList(); + } catch (err) { + if (err !== "cancel") { + this.$message.error(err.message || err.msg || "打捞失败"); + } + } + }, + async handleCancelSalvage(row) { + try { + await this.$confirm("确认取消打捞该流程?", "提示", { + type: "warning", + }); + const res = await cancelSalvage(row.id); + // 响应拦截器已经处理,成功时返回的是data部分(字符串消息) + this.$message.success(res || "取消打捞成功"); + this.getList(); + } catch (err) { + if (err !== "cancel") { + this.$message.error(err.message || err.msg || "取消打捞失败"); + } + } + }, contentFormatter(row) { const { data, fields } = row; let text = ""; @@ -1135,11 +1197,6 @@ export default { }, computed: { menuConfig() { - console.log( - "this.$store.state", - this.$store.state, - this.$store.state.user.roles.includes("全局流程监管") - ); if (this.$store.state.user.roles.includes("全局流程监管")) { return { className: "my-menus", @@ -1151,6 +1208,16 @@ export default { name: "编辑", prefixConfig: { icon: "vxe-icon-feedback" }, }, + { + code: "salvage", + name: "打捞至付款流程", + prefixConfig: { icon: "vxe-icon-check" }, + }, + { + code: "cancel_salvage", + name: "取消打捞", + prefixConfig: { icon: "vxe-icon-close" }, + }, ], ], }, diff --git a/自定义字段渲染整理.md b/自定义字段渲染整理.md index ec061bc..11fe5fa 100644 --- a/自定义字段渲染整理.md +++ b/自定义字段渲染整理.md @@ -1157,3 +1157,4 @@ form 对象存储字段值 + diff --git a/错误诊断和解决方案.md b/错误诊断和解决方案.md index 3a960c3..f490e82 100644 --- a/错误诊断和解决方案.md +++ b/错误诊断和解决方案.md @@ -194,3 +194,4 @@ A: 这是正常的,Vue CLI使用内容哈希来生成文件名。只要HTML文 +