Procházet zdrojové kódy

feat: 申请作业票时支持直接提交审批

1. 申请/编辑弹窗底部新增提交按钮,与列表提交走同一个 ticketSubmit 接口

2. 新增态先保存拿到作业票 id 再发起审批流;编辑态先保存最新内容再提交

3. 保存响应未返回 id 时按作业票信息回查兜底,仍拿不到则提示到列表提交

4. 记录本次新增已保存的 id,提交失败重试复用,避免重复建票
xieyong před 6 dny
rodič
revize
252ee21890
1 změnil soubory, kde provedl 115 přidání a 38 odebrání
  1. 115 38
      src/views/DangerousWorkList/add.vue

+ 115 - 38
src/views/DangerousWorkList/add.vue

@@ -205,6 +205,7 @@
         type="primary"
         @click="save()"
         :loading="loading"
+        :disabled="submitLoading"
         >保存</el-button
       >
       <el-button
@@ -212,6 +213,7 @@
         type="success"
         @click="submit()"
         :loading="submitLoading"
+        :disabled="loading"
         >提交</el-button
       >
       <el-button @click="cancel">{{ isView ? '关闭' : '取消' }}</el-button>
@@ -244,7 +246,8 @@
     ticketSave,
     ticketUpdate,
     ticketGetById,
-    ticketSubmit
+    ticketSubmit,
+    ticketListByWorkId
   } from '@/api/dangerousWork';
   import { listOrganizations, getUserPage } from '@/api/system/organization';
 
@@ -298,6 +301,8 @@
         loading: false,
         // 提交审批中
         submitLoading: false,
+        // 新增申请保存后记录作业票 id,提交失败重试时复用
+        newTicketId: '',
         // 查询作业票详情中
         detailLoading: false,
         // 详情请求序号:用于丢弃过期响应(快速切换作业票时)
@@ -360,13 +365,17 @@
         );
         return option?.label || '';
       },
-      // 是否可提交:仅编辑态、已保存且为草稿(待提交)状态的作业票允许提交
+      // 是否可提交:
+      //  - 新增申请:作业票还没保存,提交时内部会先保存再发起审批流
+      //  - 编辑:仅草稿(待提交)状态允许提交
       canSubmit() {
-        return (
-          this.isEdit &&
-          !!this.form.id &&
-          Number(this.form.status) === DRAFT_STATUS
-        );
+        if (this.isView) {
+          return false;
+        }
+        if (this.isEdit) {
+          return !!this.form.id && Number(this.form.status) === DRAFT_STATUS;
+        }
+        return true;
       },
       // 作业类型下拉:优先取后端字典,字典没有时使用兜底数据
       workTypeList() {
@@ -527,6 +536,7 @@
         this.visible = true;
         this.dialogType = 'add';
         this.activeComp = 'main';
+        this.newTicketId = '';
         const detail = work || {};
         this.resetTicketForm();
         this.form = {
@@ -565,6 +575,7 @@
         this.visible = true;
         this.dialogType = mode || 'view';
         this.activeComp = 'main';
+        this.newTicketId = '';
         this.detailLoading = true;
         const seq = ++this.detailSeq;
         // 先清空上一次的数据,避免详情返回前展示旧内容
@@ -685,6 +696,7 @@
         this.rawExtension = null;
         this.detailLoading = false;
         this.submitLoading = false;
+        this.newTicketId = '';
         this.visible = false;
         this.$refs.form && this.$refs.form.clearValidate();
       },
@@ -789,32 +801,30 @@
         });
       },
       // 提交作业票并发起审批流:审批流编码按作业类型取
+      // 新增时先保存拿到作业票 id,编辑时直接用已有 id,最终与列表提交走同一个接口
       submit() {
-        if (!this.form.id) {
-          this.$message.warning('请先保存作业票后再提交');
-          return;
-        }
-        const processDefinitionKey = getProcessDefinitionKey(
-          this.form.workType,
-          this.currentWorkTypeName
-        );
-        if (!processDefinitionKey) {
-          this.$message.warning(
-            '该作业类型暂未接入审批流,请联系管理员配置审批流编码'
-          );
-          return;
-        }
         this.$refs.form.validate((valid) => {
           if (!valid) {
             return;
           }
-          // 提交前先保存,保证审批流中的作业票内容与页面一致
           const params = this.buildSaveParams();
           if (!params) {
             return;
           }
+          const processDefinitionKey = getProcessDefinitionKey(
+            this.form.workType,
+            this.currentWorkTypeName
+          );
+          if (!processDefinitionKey) {
+            this.$message.warning(
+              '该作业类型暂未接入审批流,请联系管理员配置审批流编码'
+            );
+            return;
+          }
           this.$confirm(
-            '提交前将自动保存作业票内容,提交后作业票不可再修改,确认提交吗?',
+            this.isEdit
+              ? '提交前将自动保存作业票内容,提交后作业票不可再修改,确认提交吗?'
+              : '提交后将保存作业票并发起审批流,提交后不可再修改,确认提交吗?',
             '提示',
             {
               confirmButtonText: '确定',
@@ -822,23 +832,90 @@
               type: 'warning'
             }
           )
-            .then(() => {
-              this.submitLoading = true;
-              return ticketUpdate(params)
-                .then(() =>
-                  ticketSubmit({ id: this.form.id, processDefinitionKey })
-                )
-                .then(() => {
-                  this.$message.success('提交成功,已发起审批');
-                  this.cancel();
-                  this.$emit('reload');
-                })
-                .finally(() => {
-                  this.submitLoading = false;
-                });
-            })
+            .then(() => this.submitTicket(params, processDefinitionKey))
             .catch(() => {});
         });
+      },
+      // 保存作业票并发起审批流
+      async submitTicket(params, processDefinitionKey) {
+        this.submitLoading = true;
+        try {
+          // form.id 为空时是新增;newTicketId 记录本次新增已保存的 id,
+          // 提交失败重试时复用,避免重复建票
+          let ticketId = this.form.id || this.newTicketId;
+          if (ticketId) {
+            // 已保存过:先保存最新内容,保证审批中的票与页面一致
+            // 修改接口不接收 workId(所属危险作业不可变更)
+            const { workId, ...updateParams } = params;
+            await ticketUpdate({ ...updateParams, id: ticketId });
+          } else {
+            // 新增:先保存拿到作业票 id
+            const saveRes = await ticketSave(params);
+            ticketId = await this.resolveSavedTicketId(saveRes, params);
+            if (!ticketId) {
+              this.$message.warning(
+                '作业票已保存,但未获取到作业票ID,请在作业票列表中点击「提交」发起审批'
+              );
+              this.cancel();
+              this.$emit('reload');
+              return;
+            }
+            this.newTicketId = ticketId;
+          }
+          await ticketSubmit({ id: ticketId, processDefinitionKey });
+          this.$message.success('提交成功,已发起审批');
+          this.cancel();
+          this.$emit('reload');
+        } catch (e) {
+          // 失败提示由响应拦截器统一处理
+        } finally {
+          this.submitLoading = false;
+        }
+      },
+      // 取新建作业票的 id:优先用保存响应,没有则按作业票信息回查
+      async resolveSavedTicketId(saveRes, params) {
+        const payload = saveRes?.data ?? saveRes;
+        const id =
+          this.extractId(payload) ||
+          this.extractId(payload?.data) ||
+          this.extractId(payload?.ticket);
+        if (id) {
+          return id;
+        }
+        // 兜底:按所属危险作业回查作业票列表,取与本次申请一致的最新一条
+        try {
+          const list = await ticketListByWorkId(params.workId);
+          const matched = (list || [])
+            .filter(
+              (item) =>
+                String(item.applicantId) === String(params.applicantId) &&
+                String(item.workType) === String(params.workType) &&
+                String(item.startTime || '') === String(params.startTime || '')
+            )
+            .sort((a, b) => (a.createTime < b.createTime ? 1 : -1));
+          return matched.length ? matched[0].id : '';
+        } catch (e) {
+          return '';
+        }
+      },
+      // 从响应数据中取作业票 id
+      extractId(source) {
+        if (source === undefined || source === null) {
+          return '';
+        }
+        if (typeof source === 'number') {
+          return source;
+        }
+        if (typeof source === 'string') {
+          return /^\d+$/.test(source) ? source : '';
+        }
+        if (typeof source === 'object') {
+          const value = source.id ?? source.ticketId;
+          if (value !== undefined && value !== null && value !== '') {
+            return value;
+          }
+        }
+        return '';
       }
     }
   };