zhangwencui
2026-09-02 fa7fa3b7e38e6828dbb6964e72eac8e6b87c2b6e
批量提交和批量审批
已修改3个文件
219 ■■■■■ 文件已修改
src/views/officeProcessAutomation/ApproveManage/approve-list/index.vue 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/officeProcessAutomation/ApproveManage/approve-list/useApproveList.js 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/finalInspection/index.vue 75 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/officeProcessAutomation/ApproveManage/approve-list/index.vue
@@ -48,6 +48,13 @@
        <el-button :icon="RefreshRight" @click="resetSearch">重置</el-button>
      </div>
      <div class="search_actions">
        <el-button
          type="success"
          :icon="CircleCheck"
          @click="openBatchApproveDialog"
        >
          批量审批
        </el-button>
        <el-button type="primary" :icon="Plus" @click="openSubmitDialog">提交审批</el-button>
      </div>
    </div>
@@ -58,9 +65,10 @@
        :column="tableColumn"
        :tableData="tableData"
        :page="page"
        :isSelection="false"
        :isSelection="true"
        :tableLoading="tableLoading"
        :total="page.total"
        @selection-change="handleSelectionChange"
        @pagination="pagination"
      >
        <template #approveType="{ row }">
@@ -329,11 +337,53 @@
        </el-button>
      </template>
    </el-dialog>
    <!-- 批量审批操作 -->
    <el-dialog
      v-model="batchApproveDialog.visible"
      title="批量审批处理"
      width="560px"
      append-to-body
      destroy-on-close
      @closed="batchApproveOpinion = ''"
    >
      <el-form label-width="100px">
        <el-form-item label="审批意见">
          <el-input
            v-model="batchApproveOpinion"
            type="textarea"
            :rows="4"
            maxlength="500"
            show-word-limit
            placeholder="通过可留空;驳回请填写具体原因"
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button
          type="success"
          :loading="batchApproveSubmitting"
          @click="onBatchApprove('approved')"
        >
          通 过
        </el-button>
        <el-button
          type="danger"
          :loading="batchApproveSubmitting"
          @click="onBatchApprove('rejected')"
        >
          驳 回
        </el-button>
        <el-button :disabled="batchApproveSubmitting" @click="batchApproveDialog.visible = false">
          取 消
        </el-button>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import { Plus, RefreshRight } from "@element-plus/icons-vue";
import { CircleCheck, Plus, RefreshRight } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus";
import { computed, onMounted, ref } from "vue";
import { APPROVAL_MODULE_KEYS } from "../approve-shared/approvalModuleRegistry.js";
@@ -374,6 +424,9 @@
  approveDialog,
  approveOpinion,
  approveSubmitting,
  batchApproveDialog,
  batchApproveOpinion,
  batchApproveSubmitting,
  submitReimburseApprove,
  submitDialog,
  isSubmitEdit,
@@ -387,6 +440,8 @@
  handleQuery,
  resetSearch,
  pagination,
  handleSelectionChange,
  openBatchApproveDialog,
  resetSubmitDialogState,
  openSubmitDialog,
  openEditDialog,
@@ -394,6 +449,7 @@
  backToTemplatePick,
  submitInstanceForm,
  submitApprove,
  submitBatchApprove,
  openDetail,
  openApprove,
} = al;
@@ -438,6 +494,21 @@
  }
}
async function onBatchApprove(result) {
  const ret = await submitBatchApprove(result);
  if (ret?.needOpinion) {
    ElMessage.warning("驳回时请填写审批意见");
    return;
  }
  if (ret?.ok) {
    if (ret.failCount > 0) {
      ElMessage.warning(`成功审批${ret.successCount}条,失败${ret.failCount}条`);
    } else {
      ElMessage.success(result === "approved" ? "批量审批已通过" : "批量审批已驳回");
    }
  }
}
function formatRecordTime(time) {
  return formatDisplayTime(time) || "—";
}
src/views/officeProcessAutomation/ApproveManage/approve-list/useApproveList.js
@@ -85,6 +85,10 @@
  const approveDialog = reactive({ visible: false, row: null });
  const approveOpinion = ref("");
  const approveSubmitting = ref(false);
  const selectedRows = ref([]);
  const batchApproveDialog = reactive({ visible: false });
  const batchApproveOpinion = ref("");
  const batchApproveSubmitting = ref(false);
  /** 差旅/费用报销专用详情、审批弹窗 */
  const reimburseDialog = reactive({
@@ -189,7 +193,7 @@
        {
          name: "审批",
          type: "text",
          disabled: (row) => row.approvalStatus !== "pending" || !row.isApprove,
          disabled: (row) => !canApprove(row),
          clickFun: (row) => openApprove(row),
        },
        // {
@@ -263,6 +267,28 @@
    page.current = p;
    page.size = limit;
    fetchApprovalList();
  }
  function handleSelectionChange(selection) {
    selectedRows.value = selection || [];
  }
  function canApprove(row) {
    return row?.approvalStatus === "pending" && Boolean(row?.isApprove);
  }
  function openBatchApproveDialog() {
    if (!selectedRows.value.length) {
      ElMessage.warning("请选择数据");
      return;
    }
    const approveRows = selectedRows.value.filter(canApprove);
    if (!approveRows.length) {
      ElMessage.warning("所选数据不可审批");
      return;
    }
    batchApproveOpinion.value = "";
    batchApproveDialog.visible = true;
  }
  async function openReimburseDetail(row, mode) {
@@ -636,6 +662,40 @@
    }
  }
  async function submitBatchApprove(result) {
    const approveRows = selectedRows.value.filter(canApprove);
    if (!approveRows.length) {
      ElMessage.warning("所选数据不可审批");
      return { ok: false };
    }
    if (result === "rejected" && !(batchApproveOpinion.value || "").trim()) {
      return { needOpinion: true };
    }
    if (batchApproveSubmitting.value) return { ok: false };
    batchApproveSubmitting.value = true;
    try {
      const results = await Promise.allSettled(
        approveRows.map((row) =>
          approveApprovalInstance(
            buildApproveInstanceDto(row, result, batchApproveOpinion.value)
          )
        )
      );
      const successCount = results.filter((item) => item.status === "fulfilled").length;
      const failCount = approveRows.length - successCount;
      batchApproveDialog.visible = false;
      await fetchApprovalList();
      return { ok: successCount > 0, result, successCount, failCount };
    } catch {
      ElMessage.error("批量审批失败");
      return { ok: false };
    } finally {
      batchApproveSubmitting.value = false;
    }
  }
  function approvalActionLabel(result) {
    if (result === "approved") return "通过";
    if (result === "rejected") return "驳回";
@@ -664,6 +724,10 @@
    approveDialog,
    approveOpinion,
    approveSubmitting,
    selectedRows,
    batchApproveDialog,
    batchApproveOpinion,
    batchApproveSubmitting,
    submitReimburseApprove,
    isReimburseApprovalInstance,
    submitDialog,
@@ -685,6 +749,8 @@
    handleQuery,
    resetSearch,
    pagination,
    handleSelectionChange,
    openBatchApproveDialog,
    resetSubmitDialogState,
    openSubmitDialog,
    openEditDialog,
@@ -695,6 +761,7 @@
    submitInstanceForm,
    submitNewApproval,
    submitApprove,
    submitBatchApprove,
    openDetail,
    openApprove,
    fetchApprovalList,
src/views/qualityManagement/finalInspection/index.vue
@@ -59,6 +59,10 @@
        <el-button type="primary"
                   @click="openForm('add')">新增</el-button>
        <el-button @click="handleOut">导出</el-button>
        <el-button type="primary"
                   plain
                   :loading="batchSubmitting"
                   @click="handleBatchSubmit">批量提交</el-button>
        <el-button type="danger"
                   plain
                   @click="handleDelete">删除</el-button>
@@ -289,15 +293,7 @@
          clickFun: row => {
            submit(row.id);
          },
          disabled: row => {
            // 已提交则禁用
            if (row.inspectState == 1) return true;
            // 如果检验员有值,只有当前登录用户能提交
            if (row.checkName) {
              return row.checkName !== userStore.nickName;
            }
            return false;
          },
          disabled: row => !canSubmit(row),
        },
        {
          name: "分配检验员",
@@ -326,6 +322,7 @@
  const tableData = ref([]);
  const selectedRows = ref([]);
  const tableLoading = ref(false);
  const batchSubmitting = ref(false);
  const currentRow = ref(null);
  const page = reactive({
    current: 1,
@@ -391,6 +388,16 @@
  // 表格选择数据
  const handleSelectionChange = selection => {
    selectedRows.value = selection;
  };
  const canSubmit = row => {
    // 已提交则禁用
    if (row.inspectState == 1) return false;
    // 如果检验员有值,只有当前登录用户能提交
    if (row.checkName) {
      return row.checkName === userStore.nickName;
    }
    return true;
  };
  // 打开弹框
@@ -464,6 +471,56 @@
    }
  };
  const handleBatchSubmit = () => {
    if (selectedRows.value.length === 0) {
      proxy.$modal.msgWarning("请选择数据");
      return;
    }
    const submitRows = selectedRows.value.filter(item => canSubmit(item));
    if (submitRows.length === 0) {
      proxy.$modal.msgWarning("所选数据不可提交");
      return;
    }
    ElMessageBox.confirm(
      `选中的${submitRows.length}条内容将被提交,是否确认提交?`,
      "批量提交",
      {
        confirmButtonText: "确认",
        cancelButtonText: "取消",
        type: "warning",
      }
    )
      .then(async () => {
        batchSubmitting.value = true;
        const results = await Promise.allSettled(
          submitRows.map(item => submitQualityInspect({ id: item.id }))
        );
        const successCount = results.filter(
          item => item.status === "fulfilled" && item.value?.code === 200
        ).length;
        const failCount = submitRows.length - successCount;
        if (successCount > 0 && failCount === 0) {
          proxy.$modal.msgSuccess("批量提交成功");
        } else if (successCount > 0) {
          proxy.$modal.msgWarning(
            `成功提交${successCount}条,失败${failCount}条`
          );
        } else {
          proxy.$modal.msgError("批量提交失败");
        }
        getList();
      })
      .catch(() => {
        proxy.$modal.msg("已取消");
      })
      .finally(() => {
        batchSubmitting.value = false;
      });
  };
  // 关闭弹框
  const closeDia = () => {
    proxy.resetForm("formRef");