| | |
| | | prop="projectName" |
| | | width="320" |
| | | show-overflow-tooltip /> --> |
| | | <el-table-column label="审批状态" |
| | | prop="approvalStatus" |
| | | width="100" |
| | | show-overflow-tooltip> |
| | | <template #default="scope"> |
| | | <el-tag |
| | | :type="getApprovalStatusType(scope.row.approvalStatus)" |
| | | size="small"> |
| | | {{ approvalStatusText[scope.row.approvalStatus] || '未知状态' }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="签订日期" |
| | | prop="executionDate" |
| | | 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="user in userList" |
| | | :key="user.userId" |
| | | :label="user.nickName" |
| | | :value="user.userId" |
| | | /> |
| | | </el-select> |
| | | </div> |
| | | </div> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-form-item label="产品信息:" |
| | | prop="entryDate"> |
| | |
| | | type="danger" |
| | | @click="deleteProduct">删除</el-button> |
| | | </el-form-item> |
| | | <div class="select-button-group" |
| | | style="width: 500px; margin: 20px 0;" |
| | | v-if="operationType === 'add'"> |
| | | <el-select filterable |
| | | allow-create |
| | | :reserve-keyword="true" |
| | | :default-first-option="false" |
| | | clearable |
| | | v-model="templateName" |
| | | :input-value="filterInputValue" |
| | | @filter-change="onTemplateFilterChange" |
| | | @change="onTemplateChange" |
| | | @focus="getTemplateList" |
| | | style="width: 500px;" |
| | | placeholder="请选择模版或者输入新的模版名称后选择" |
| | | class="no-arrow-select"> |
| | | <el-option v-for="item in templateList" |
| | | :key="item.id || item.value" |
| | | :label="item.templateName" |
| | | :value="item.templateName"> |
| | | <div style="display: flex; justify-content: space-between; align-items: center;"> |
| | | <span>{{ item.templateName }}</span> |
| | | <el-icon |
| | | v-if="item.id" |
| | | class="delete-icon" |
| | | @click.stop="handleDeleteTemplate(item)" |
| | | style="cursor: pointer; color: #f56c6c; font-size: 14px; margin-left: 8px;"> |
| | | <Delete /> |
| | | </el-icon> |
| | | </div> |
| | | </el-option> |
| | | </el-select> |
| | | <!-- 按钮:与 Select 高度匹配,去掉左侧边框,无缝衔接 --> |
| | | <el-button size="small" |
| | | style="height: 32px;margin-left: 8px;" |
| | | @click="handleButtonClick" |
| | | :disabled="!templateName || templateName.trim() === '' || (!currentTemplateId && isTemplateNameDuplicate)"> |
| | | 保存 |
| | | </el-button> |
| | | </div> |
| | | </el-row> |
| | | <el-table :data="productData" |
| | | border |
| | |
| | | |
| | | const userStore = useUserStore(); |
| | | |
| | | // 审批人节点(仿销售台账发货审批人) |
| | | 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); |
| | | }; |
| | | |
| | | // 订单审批状态显示文本 |
| | | const approvalStatusText = { |
| | | 1: "待审核", |
| | | 2: "审批中", |
| | | 3: "审批通过", |
| | | 4: "审批失败", |
| | | }; |
| | | |
| | | // 获取审批状态标签类型 |
| | | const getApprovalStatusType = (status) => { |
| | | const typeMap = { |
| | | 1: "info", // 待审核 - 灰色 |
| | | 2: "warning", // 审批中 - 橙色 |
| | | 3: "success", // 审批通过 - 绿色 |
| | | 4: "danger", // 审批失败 - 红色 |
| | | }; |
| | | return typeMap[status] || ""; |
| | | }; |
| | | |
| | | const templateName = ref(""); |
| | | const filterInputValue = ref(""); |
| | | const templateList = ref([]); |
| | |
| | | rules: { |
| | | purchaseContractNumber: [ |
| | | { required: true, message: "请输入", trigger: "blur" }, |
| | | ], |
| | | approverId: [ |
| | | { required: true, message: "请选择审批人", trigger: "change" }, |
| | | ], |
| | | projectName: [ |
| | | { required: true, message: "请输入项目名称", trigger: "blur" }, |
| | |
| | | } |
| | | |
| | | try { |
| | | // 获取审批人ID字符串 |
| | | const approveUserIds = approverNodes.value |
| | | .filter(node => node.userId) |
| | | .map(node => node.userId) |
| | | .join(","); |
| | | |
| | | let params = { |
| | | productData: proxy.HaveJson(productData.value), |
| | | supplierId: form.value.supplierId, |
| | | paymentMethod: form.value.paymentMethod, |
| | | recorderId: form.value.recorderId, |
| | | projectName: form.value.projectName, |
| | | approveUserIds: approveUserIds, |
| | | templateName: templateName.value.trim(), |
| | | }; |
| | | console.log("template params ===>", params, "currentTemplateId:", currentTemplateId.value); |
| | |
| | | }; |
| | | // 打开弹框 |
| | | const openForm = async (type, row) => { |
| | | // 编辑时检查审核状态,只有待审核(1)和审批失败(4)才能编辑 |
| | | if (type === "edit" && row) { |
| | | if (row.approvalStatus !== 1 && row.approvalStatus !== 4) { |
| | | proxy.$modal.msgWarning("只有待审核和审批失败状态的记录才能编辑"); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | await getTemplateList(); |
| | | operationType.value = type; |
| | | form.value = {}; |
| | |
| | | templateName.value = ""; |
| | | filterInputValue.value = ""; |
| | | isTemplateNameDuplicate.value = false; |
| | | // 重置审批人节点(默认一个空节点) |
| | | approverNodes.value = [{ id: 1, userId: null }]; |
| | | nextApproverId = 2; |
| | | try { |
| | | // 并行加载基础数据 |
| | | const [userRes, salesRes, supplierRes] = await Promise.all([ |
| | |
| | | form.value = { ...purchaseRes }; |
| | | productData.value = purchaseRes.productData || []; |
| | | fileList.value = purchaseRes.salesLedgerFiles || []; |
| | | // 如果编辑时有审批人,解析审批人ID字符串并设置到节点中 |
| | | if (purchaseRes.approveUserIds) { |
| | | const approverIds = purchaseRes.approveUserIds.split(","); |
| | | approverNodes.value = approverIds.map((id, index) => ({ |
| | | id: index + 1, |
| | | userId: Number(id) |
| | | })); |
| | | nextApproverId = approverIds.length + 1; |
| | | } |
| | | } catch (error) { |
| | | console.error("加载采购台账数据失败:", error); |
| | | proxy.$modal.msgError("加载数据失败"); |
| | |
| | | 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(","); |
| | | |
| | | if (productData.value.length > 0) { |
| | | // 新增时,需要从每个产品对象中删除 id 字段 |
| | | let processedProductData = productData.value; |
| | |
| | | } |
| | | form.value.tempFileIds = tempFileIds; |
| | | form.value.type = 2; |
| | | form.value.approveUserIds = approveUserIds; |
| | | |
| | | // 如果salesLedgerId为空,则不传递salesContractNo |
| | | if (!form.value.salesLedgerId) { |
| | |
| | | // 关闭弹框 |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef"); |
| | | // 重置审批人节点(默认一个空节点) |
| | | approverNodes.value = [{ id: 1, userId: null }]; |
| | | nextApproverId = 2; |
| | | dialogFormVisible.value = false; |
| | | }; |
| | | // 打开产品弹框 |
| | |
| | | .select-button-group { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | // 审批人节点容器样式 |
| | | .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; |
| | | |
| | | &: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%; |
| | | } |
| | | } |
| | | |
| | | // 删除图标样式 |