| | |
| | | <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> |
| | |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="false" |
| | | :isSelection="true" |
| | | :tableLoading="tableLoading" |
| | | :total="page.total" |
| | | @selection-change="handleSelectionChange" |
| | | @pagination="pagination" |
| | | > |
| | | <template #approveType="{ row }"> |
| | |
| | | </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"; |
| | |
| | | approveDialog, |
| | | approveOpinion, |
| | | approveSubmitting, |
| | | batchApproveDialog, |
| | | batchApproveOpinion, |
| | | batchApproveSubmitting, |
| | | submitReimburseApprove, |
| | | submitDialog, |
| | | isSubmitEdit, |
| | |
| | | handleQuery, |
| | | resetSearch, |
| | | pagination, |
| | | handleSelectionChange, |
| | | openBatchApproveDialog, |
| | | resetSubmitDialogState, |
| | | openSubmitDialog, |
| | | openEditDialog, |
| | |
| | | backToTemplatePick, |
| | | submitInstanceForm, |
| | | submitApprove, |
| | | submitBatchApprove, |
| | | openDetail, |
| | | openApprove, |
| | | } = al; |
| | |
| | | } |
| | | if (ret?.ok) { |
| | | ElMessage.success(result === "approved" ? "已通过" : "已驳回"); |
| | | } |
| | | } |
| | | |
| | | 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" ? "批量审批已通过" : "批量审批已驳回"); |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | border-left: 3px solid var(--el-color-primary); |
| | | line-height: 1.4; |
| | | } |
| | | </style> |
| | | </style> |
| | |
| | | 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({ |
| | |
| | | { |
| | | name: "审批", |
| | | type: "text", |
| | | disabled: (row) => row.approvalStatus !== "pending" || !row.isApprove, |
| | | disabled: (row) => !canApprove(row), |
| | | clickFun: (row) => openApprove(row), |
| | | }, |
| | | // { |
| | |
| | | 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) { |
| | |
| | | } |
| | | } |
| | | |
| | | 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 "驳回"; |
| | |
| | | approveDialog, |
| | | approveOpinion, |
| | | approveSubmitting, |
| | | selectedRows, |
| | | batchApproveDialog, |
| | | batchApproveOpinion, |
| | | batchApproveSubmitting, |
| | | submitReimburseApprove, |
| | | isReimburseApprovalInstance, |
| | | submitDialog, |
| | |
| | | handleQuery, |
| | | resetSearch, |
| | | pagination, |
| | | handleSelectionChange, |
| | | openBatchApproveDialog, |
| | | resetSubmitDialogState, |
| | | openSubmitDialog, |
| | | openEditDialog, |
| | |
| | | submitInstanceForm, |
| | | submitNewApproval, |
| | | submitApprove, |
| | | submitBatchApprove, |
| | | openDetail, |
| | | openApprove, |
| | | fetchApprovalList, |
| | | }; |
| | | } |
| | | } |
| | |
| | | <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> |
| | |
| | | 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: "分配检验员", |
| | |
| | | const tableData = ref([]); |
| | | const selectedRows = ref([]); |
| | | const tableLoading = ref(false); |
| | | const batchSubmitting = ref(false); |
| | | const currentRow = ref(null); |
| | | const page = reactive({ |
| | | current: 1, |
| | |
| | | // 表格选择数据 |
| | | 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; |
| | | }; |
| | | |
| | | // 打开弹框 |
| | |
| | | } |
| | | }; |
| | | |
| | | 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"); |