| src/views/collaborativeApproval/approvalProcess/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/qualityManagement/rawMaterialInspection/components/formDia.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/salesManagement/salesLedger/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/views/collaborativeApproval/approvalProcess/index.vue
@@ -18,6 +18,8 @@ name="6"></el-tab-pane> <el-tab-pane label="发货审批" name="7"></el-tab-pane> <el-tab-pane label="入库审批" name="9"></el-tab-pane> </el-tabs> <div class="search_form"> <div> @@ -52,12 +54,12 @@ <el-button @click="handleOut">审批人维护</el-button> <el-button type="primary" @click="openForm('add')" v-if="currentApproveType !== 5 && currentApproveType !== 6 && currentApproveType !== 7">新增</el-button> v-if="currentApproveType !== 5 && currentApproveType !== 6 && currentApproveType !== 7 && currentApproveType !== 9">新增</el-button> <el-button @click="handleExport">导出</el-button> <el-button type="danger" plain @click="handleDelete" v-if="currentApproveType !== 5 && currentApproveType !== 6 && currentApproveType !== 7">删除</el-button> v-if="currentApproveType !== 5 && currentApproveType !== 6 && currentApproveType !== 7 && currentApproveType !== 9">删除</el-button> </div> </div> <div class="table_list"> @@ -187,6 +189,7 @@ const isReimburseType = currentApproveType.value === 4; // 报销管理 const isQuotationType = currentApproveType.value === 6; // 报价审批 const isPurchaseType = currentApproveType.value === 5; // 采购审批 const isInboundType = currentApproveType.value === 9; // 入库审批 // 基础列配置 const baseColumns = [ @@ -237,6 +240,8 @@ ? "报价单号" : isPurchaseType ? "采购合同号" : isInboundType ? "入库单号" : "审批事由", prop: "approveReason", }, @@ -289,6 +294,7 @@ currentApproveType.value === 5 || currentApproveType.value === 6 || currentApproveType.value === 7 || currentApproveType.value === 9 || row.approveStatus == 2 || row.approveStatus == 1 || row.approveStatus == 4, @@ -402,6 +408,7 @@ 5: "/approveProcess/exportFive", 6: "/approveProcess/exportSix", 7: "/approveProcess/exportSeven", 9: "/approveProcess/exportNine", }; const url = urlMap[type] || urlMap[0]; const nameMap = { @@ -413,6 +420,7 @@ 5: "采购申请审批表", 6: "报价审批表", 7: "发货审批表", 9: "入库审批表", }; const fileName = nameMap[type] || nameMap[0]; proxy.download(url, {}, `${fileName}.xlsx`); src/views/qualityManagement/rawMaterialInspection/components/formDia.vue
@@ -88,13 +88,13 @@ clearable :precision="2" :disabled="supplierQuantityDisabled"/> </el-form-item> </el-col> </el-row> <el-row :gutter="30"> <el-col :span="12"> <el-form-item label="检测单位:" prop="checkCompany"> <el-input v-model="form.checkCompany" placeholder="请输入" clearable/> </el-form-item> </el-col> </el-row> <el-row :gutter="30"> <el-col :span="12"> <el-form-item label="检测结果:" prop="checkResult"> <el-select v-model="form.checkResult"> @@ -103,8 +103,6 @@ </el-select> </el-form-item> </el-col> </el-row> <el-row :gutter="30"> <el-col :span="12"> <el-form-item label="检验员:" prop="checkName"> <el-select v-model="form.checkName" placeholder="请选择" clearable style="width: 100%"> @@ -112,6 +110,8 @@ </el-select> </el-form-item> </el-col> </el-row> <el-row :gutter="30"> <el-col :span="12"> <el-form-item label="检测日期:" prop="checkTime"> <el-date-picker @@ -123,6 +123,47 @@ clearable style="width: 100%" /> </el-form-item> </el-col> </el-row> <el-row :gutter="30"> <el-col :span="24"> <el-form-item> <template #label> <div style="display: flex; align-items: center; justify-content: space-between; width: 100%;"> <span>审批人选择:</span> <el-button type="primary" size="small" @click="addApproverNode" icon="Plus">新增节点</el-button> </div> </template> <div class="approver-nodes-container"> <div v-for="(node, index) in approverNodes" :key="node.id" class="approver-node-item"> <div class="approver-node-header"> <span class="approver-node-label">审批节点 {{ index + 1 }}</span> <el-button v-if="approverNodes.length > 1" type="danger" size="small" text @click="removeApproverNode(index)" icon="Delete">删除</el-button> </div> <el-select v-model="node.userId" placeholder="请选择审批人" filterable style="width: 100%"> <el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId" /> </el-select> </div> </div> </el-form-item> </el-col> </el-row> @@ -180,6 +221,7 @@ quantity: "", checkCompany: "", checkResult: "", reviewName: "", }, rules: { checkTime: [{required: true, message: "请输入", trigger: "blur"},], @@ -229,6 +271,14 @@ const testStandardOptions = ref([]); // 指标选择下拉框数据 const modelOptions = ref([]); const userList = ref([]); // 检验员下拉列表 const approverNodes = ref([{ id: 1, userId: null }]); let nextApproverId = 2; const addApproverNode = () => { approverNodes.value.push({ id: nextApproverId++, userId: null }); }; const removeApproverNode = index => { approverNodes.value.splice(index, 1); }; // 编辑时:productMainId 或 purchaseLedgerId 任一有值则供应商、数量置灰 const supplierQuantityDisabled = computed(() => { @@ -265,7 +315,10 @@ quantity: "", checkCompany: "", checkResult: "", reviewName: "", } approverNodes.value = [{ id: 1, userId: null }]; nextApproverId = 2; testStandardOptions.value = []; tableData.value = []; // 先确保产品树已加载,否则编辑时产品/规格型号无法反显 @@ -274,6 +327,25 @@ // 先保存 testStandardId,避免被清空 const savedTestStandardId = row.testStandardId; form.value = {...row} if (form.value.approveUserIds) { const ids = String(form.value.approveUserIds) .split(",") .map(id => id.trim()) .filter(Boolean); if (ids.length > 0) { approverNodes.value = ids.map((id, index) => ({ id: index + 1, userId: Number(id), })); nextApproverId = ids.length + 1; } } else if (form.value.reviewName) { const matchedReviewer = userList.value.find(item => item.nickName === form.value.reviewName); if (matchedReviewer?.userId) { approverNodes.value = [{ id: 1, userId: matchedReviewer.userId }]; nextApproverId = 2; } } currentProductId.value = row.productId || 0 // 关键:编辑时加载规格型号下拉选项,才能反显 productModelId if (currentProductId.value) { @@ -397,13 +469,29 @@ const submitForm = () => { proxy.$refs.formRef.validate(valid => { if (valid) { const hasEmptyApprover = approverNodes.value.some(node => !node.userId); if (hasEmptyApprover) { proxy.$modal.msgError("请为所有审批节点选择审批人!"); return; } const approveUserIds = approverNodes.value.map(node => node.userId).join(","); const firstApproverName = userList.value.find(item => String(item.userId) === String(approverNodes.value[0]?.userId)) ?.nickName || ""; form.value.inspectType = 0 if (operationType.value === "add") { tableData.value.forEach((item) => { delete item.id }) } const data = {...form.value, qualityInspectParams: tableData.value} const data = { ...form.value, reviewName: firstApproverName, approveUserIds, // 兼容后端不同字段命名 auditName: firstApproverName, qualityInspectParams: tableData.value, } if (operationType.value === "add") { qualityInspectAdd(data).then(res => { proxy.$modal.msgSuccess("提交成功"); @@ -464,6 +552,8 @@ // 关闭弹框 const closeDia = () => { proxy.resetForm("formRef"); approverNodes.value = [{ id: 1, userId: null }]; nextApproverId = 2; tableData.value = []; testStandardOptions.value = []; form.value.testStandardId = ''; @@ -488,4 +578,54 @@ cursor: not-allowed; } .approver-nodes-container { display: flex; flex-wrap: wrap; gap: 16px; padding: 16px; background-color: #f8f9fa; border-radius: 4px; border: 1px solid #e4e7ed; } .approver-node-item { flex: 0 0 calc(33.333% - 12px); min-width: 200px; padding: 12px; background-color: #fff; border-radius: 4px; border: 1px solid #dcdfe6; transition: all 0.3s; } .approver-node-item:hover { border-color: #409eff; box-shadow: 0 2px 8px rgba(64, 158, 255, 0.1); } .approver-node-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; } .approver-node-label { font-size: 13px; font-weight: 500; color: #606266; } @media (max-width: 1200px) { .approver-node-item { flex: 0 0 calc(50% - 8px); } } @media (max-width: 768px) { .approver-node-item { flex: 0 0 100%; } } </style> src/views/salesManagement/salesLedger/index.vue
@@ -1675,6 +1675,46 @@ title="选择入库产品" width="60%" :close-on-click-modal="false"> <div style="margin-bottom: 12px;"> <el-form> <el-form-item required> <template #label> <div style="display: flex; align-items: center; justify-content: space-between; width: 100%;"> <span>审批人选择:</span> <el-button type="primary" size="small" @click="addStockApproverNode" icon="Plus">新增节点</el-button> </div> </template> <div class="approver-nodes-container"> <div v-for="(node, index) in stockApproverNodes" :key="node.id" class="approver-node-item"> <div class="approver-node-header"> <span class="approver-node-label">审批节点 {{ index + 1 }}</span> <el-button v-if="stockApproverNodes.length > 1" type="danger" size="small" text @click="removeStockApproverNode(index)" icon="Delete">删除</el-button> </div> <el-select v-model="node.userId" placeholder="请选择审批人" filterable clearable style="width: 100%;"> <el-option v-for="item in stockApproverOptions" :key="item.userId" :label="item.userName" :value="item.userId" /> </el-select> </div> </div> </el-form-item> </el-form> </div> <el-table :data="stockProductList" border stripe @@ -1815,6 +1855,15 @@ const selectedStockProductIds = ref([]); const stockLoading = ref(false); const currentStockLedgerId = ref(null); const stockApproverOptions = ref([]); const stockApproverNodes = ref([{ id: 1, userId: null }]); let nextStockApproverId = 2; const addStockApproverNode = () => { stockApproverNodes.value.push({ id: nextStockApproverId++, userId: null }); }; const removeStockApproverNode = index => { stockApproverNodes.value.splice(index, 1); }; const ledgerQrDialogVisible = ref(false); const ledgerQrCompositeUrl = ref(""); @@ -2957,22 +3006,36 @@ currentStockLedgerId.value = id; selectedStockProductIds.value = []; stockProductList.value = []; stockApproverNodes.value = [{ id: 1, userId: null }]; nextStockApproverId = 2; stockDialogVisible.value = true; stockLoading.value = true; try { const approverRes = await approveUserList({ approveType: 9 }); stockApproverOptions.value = Array.isArray(approverRes?.data) ? approverRes.data.map(item => ({ userId: item.userId, userName: item.userName, })) : []; const res = await productList({ salesLedgerId: id, type: 1 }); stockProductList.value = []; stockProductList.value = res.data.filter(item => item.productStockStatus == 0 || item.productStockStatus == 1) || []; } catch (e) { proxy?.$modal?.msgError?.("获取产品列表失败"); proxy?.$modal?.msgError?.("获取产品或审批人失败"); } finally { stockLoading.value = false; } }; const submitStock = async () => { const hasEmptyApprover = stockApproverNodes.value.some(node => !node.userId); if (hasEmptyApprover) { ElMessage.warning("请为所有审批节点选择审批人"); return; } if (selectedStockProductIds.value.length === 0) { ElMessage.warning("请选择至少一个产品进行入库"); return; @@ -2990,9 +3053,16 @@ proxy?.$modal?.loading?.("正在入库,请稍候..."); try { const approveUserIds = stockApproverNodes.value.map(node => node.userId).join(","); const approveUserName = stockApproverNodes.value .map(node => stockApproverOptions.value.find(item => String(item.userId) === String(node.userId))?.userName) .filter(Boolean) .join(","); await salesStock({ salesLedgerId: currentStockLedgerId.value, salesLedgerProducts: selectedStockProductIds.value, approveUserIds, approveUserName, }); proxy?.$modal?.msgSuccess?.("入库成功"); stockDialogVisible.value = false; @@ -4793,4 +4863,54 @@ .ledger-qr-save-btn { margin-bottom: 12px; } .approver-nodes-container { display: flex; flex-wrap: wrap; gap: 16px; padding: 16px; background-color: #f8f9fa; border-radius: 4px; border: 1px solid #e4e7ed; } .approver-node-item { flex: 0 0 calc(33.333% - 12px); min-width: 200px; padding: 12px; background-color: #fff; border-radius: 4px; border: 1px solid #dcdfe6; transition: all 0.3s; } .approver-node-item:hover { border-color: #409eff; box-shadow: 0 2px 8px rgba(64, 158, 255, 0.1); } .approver-node-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; } .approver-node-label { font-size: 13px; font-weight: 500; color: #606266; } @media (max-width: 1200px) { .approver-node-item { flex: 0 0 calc(50% - 8px); } } @media (max-width: 768px) { .approver-node-item { flex: 0 0 100%; } } </style>