multiple/assets/favicon/RFSYLogo.png
multiple/assets/favicon/RFSYfavicon.ico
multiple/assets/favicon/XHKSfavicon.ico
multiple/assets/logo/RFSYLogo.png
multiple/assets/logo/XHKSLogo.png
src/views/collaborativeApproval/sealManagement/index.vue
@@ -7,7 +7,6 @@ </div> </template> <!-- 用印申请管理 --> <div class="tab-content"> <el-row :gutter="20" class="mb-20 "> @@ -177,6 +176,7 @@ const sealFormRef = ref() const userList = ref([]) const sealForm = reactive({ id: null, applicationNum: '', title: '', sealType: '', @@ -241,9 +241,9 @@ // 用印申请表格列配置(需在 getStatusText/getSealTypeText 等之后定义) const sealTableColumn = ref([ { label: '申请编号', prop: 'applicationNum',}, { label: '申请编号', prop: 'applicationNum' }, { label: '申请标题', prop: 'title', showOverflowTooltip: true }, { label: '申请人', prop: 'createUserName', }, { label: '申请人', prop: 'createUserName' }, { label: '所属部门', prop: 'department', width: 150 }, { label: '用印类型', @@ -261,22 +261,28 @@ formatData: (v) => getStatusText(v), formatType: (v) => getStatusType(v) }, { label: '审批人', prop: 'approveUserName', width: 100 }, { dataType: 'action', label: '操作', width: 200, width: 250, fixed: 'right', align: 'center', operation: [ { name: '审批', clickFun: (row) => approveSeal(row), showHide: (row) => row.status === 'pending' showHide: (row) => row.status === 'pending' && Number(userStore.id) === row.approveUserId }, { name: '拒绝', clickFun: (row) => rejectSeal(row), showHide: (row) => row.status === 'pending' showHide: (row) => row.status === 'pending' && Number(userStore.id) === row.approveUserId }, { name: '重新申请', clickFun: (row) => reapplySeal(row), showHide: (row) => row.status === 'rejected' && Number(userStore.id) === row.createUser }, { name: '详情', clickFun: (row) => viewSealDetail(row) } ] @@ -287,8 +293,6 @@ const searchSealApplications = () => { page.current=1 getSealApplicationList() // ElMessage.success('搜索完成') } // 重置印章申请搜索 const resetSealSearch = () => { @@ -297,16 +301,36 @@ sealSearchForm.applicationNum = '' searchSealApplications() } // 重新申请用印 const reapplySeal = (row) => { // 预填表单数据 Object.assign(sealForm, { id: row.id, applicationNum: row.applicationNum, title: row.title, sealType: row.sealType, reason: row.reason, approveUserId: row.approveUserId, urgency: row.urgency || 'normal', status: 'pending', storageBlobDTOs: row.storageBlobVOList || [] }) showSealApplyDialog.value = true } // 提交用印申请 const submitSealApplication = async () => { try { await sealFormRef.value.validate() addSealApplication(sealForm).then(res => { const request = sealForm.id ? updateSealApplication : addSealApplication request(sealForm).then(res => { if(res.code == 200){ ElMessage.success('申请提交成功') ElMessage.success(sealForm.id ? '重新申请成功' : '申请提交成功') closeSealApplyDialog() getSealApplicationList() Object.assign(sealForm, { id: null, applicationNum: '', title: '', sealType: '', @@ -320,14 +344,15 @@ }).catch(err => { console.log(err.msg) }) } catch (error) { } } // 关闭用印申请对话框 const closeSealApplyDialog = () => { // 清空表单数据 Object.assign(sealForm, { id: null, applicationNum: '', title: '', sealType: '', @@ -399,6 +424,7 @@ inputErrorMessage: '拒绝原因不能为空' }).then(({ value }) => { row.status = 'rejected' row.reason = value updateSealApplication(row).then(res => { if(res.code == 200){ ElMessage.success('已拒绝申请') src/views/officeProcessAutomation/ApproveManage/approve-list/approveListConstants.js
@@ -457,6 +457,9 @@ currentNodeIndex: 0, approvalRecords, rejectReason: approvalRecords.find(r => r.result === "rejected")?.opinion || "", purchaseContractNumber: row.purchaseContractNumber || "", quotationNo: row.quotationNo || "", shippingNo: row.shippingNo || "", }; } src/views/officeProcessAutomation/ApproveManage/approve-list/components/ApproveDetailPanel.vue
@@ -35,9 +35,116 @@ </div> <div class="detail-block"> <div class="detail-block-title">填报内容</div> <FormPayloadFields :fields="formResolved.fields" <!-- 默认表单展示 --> <FormPayloadFields v-if="!isSpecialApprovalType" :fields="formResolved.fields" :form-payload="formResolved.formPayload" readonly /> <!-- 发货审批详情 --> <template v-else-if="row.businessType === 7"> <div v-if="detailData.shippingInfo" class="shipment-detail"> <el-divider content-position="left">发货详情</el-divider> <el-descriptions :column="2" border> <el-descriptions-item label="销售订单">{{ detailData.shippingInfo.salesContractNo || "--" }}</el-descriptions-item> <el-descriptions-item label="发货订单号">{{ detailData.shippingInfo.shippingNo || "--" }}</el-descriptions-item> <el-descriptions-item label="客户名称">{{ detailData.shippingInfo.customerName || "--" }}</el-descriptions-item> <el-descriptions-item label="发货类型">{{ detailData.shippingInfo.type || "--" }}</el-descriptions-item> <el-descriptions-item label="发货日期">{{ detailData.shippingInfo.shippingDateDate || "--" }}</el-descriptions-item> <el-descriptions-item label="审核状态">{{ detailData.shippingInfo.status || "--" }}</el-descriptions-item> <el-descriptions-item label="发货车牌号">{{ detailData.shippingInfo.shippingCarNumber || "--" }}</el-descriptions-item> <el-descriptions-item label="快递公司">{{ detailData.shippingInfo.expressCompany || "--" }}</el-descriptions-item> <el-descriptions-item label="快递单号" :span="2">{{ detailData.shippingInfo.expressNumber || "--" }}</el-descriptions-item> </el-descriptions> <div v-if="detailData.shippingProductDetailDtoList.length" style="margin-top: 20px;"> <h4>产品明细</h4> <el-table :data="detailData.shippingProductDetailDtoList" border size="small" style="width: 100%"> <el-table-column label="批号" prop="batchNo" min-width="160" show-overflow-tooltip /> <el-table-column label="产品名称" prop="productName" min-width="160" show-overflow-tooltip /> <el-table-column label="规格型号" prop="specificationModel" min-width="160" show-overflow-tooltip /> <el-table-column label="发货数量" prop="deliveryQuantity" min-width="120" align="center" /> </el-table> </div> </div> </template> <!-- 采购审批详情 --> <template v-else-if="row.businessType === 5"> <div v-if="detailData" class="procurement-detail"> <el-divider content-position="left">采购详情</el-divider> <el-descriptions :column="2" border> <el-descriptions-item label="采购合同号">{{ detailData.purchaseContractNumber || "--" }}</el-descriptions-item> <el-descriptions-item label="供应商名称">{{ detailData.supplierName || "--" }}</el-descriptions-item> <el-descriptions-item label="项目名称">{{ detailData.projectName || "--" }}</el-descriptions-item> <el-descriptions-item label="销售合同号">{{ detailData.salesContractNo || "--" }}</el-descriptions-item> <el-descriptions-item label="签订日期">{{ detailData.executionDate || "--" }}</el-descriptions-item> <el-descriptions-item label="录入日期">{{ detailData.entryDate || "--" }}</el-descriptions-item> <el-descriptions-item label="付款方式">{{ detailData.paymentMethod || "--" }}</el-descriptions-item> <el-descriptions-item label="合同金额" :span="2"> <span style="font-size: 18px; color: #e6a23c; font-weight: bold;"> ¥{{ Number(detailData.contractAmount ?? 0).toFixed(2) }} </span> </el-descriptions-item> </el-descriptions> <div v-if="detailData.productData.length" style="margin-top: 20px;"> <h4>产品明细</h4> <el-table :data="detailData.productData" border style="width: 100%"> <el-table-column prop="productCategory" label="产品名称" /> <el-table-column prop="specificationModel" label="规格型号" /> <el-table-column prop="unit" label="单位" /> <el-table-column prop="quantity" label="数量" /> <el-table-column prop="taxInclusiveUnitPrice" label="含税单价"> <template #default="scope">¥{{ Number(scope.row.taxInclusiveUnitPrice ?? 0).toFixed(2) }}</template> </el-table-column> <el-table-column prop="taxInclusiveTotalPrice" label="含税总价"> <template #default="scope">¥{{ Number(scope.row.taxInclusiveTotalPrice ?? 0).toFixed(2) }}</template> </el-table-column> </el-table> </div> </div> </template> <!-- 报价审批详情 --> <template v-else-if="row.businessType === 6"> <div v-if="detailData" class="quotation-detail"> <el-divider content-position="left">报价详情</el-divider> <el-descriptions :column="2" border> <el-descriptions-item label="报价单号">{{ detailData.quotationNo || "--" }}</el-descriptions-item> <el-descriptions-item label="客户名称">{{ detailData.customer || "--" }}</el-descriptions-item> <el-descriptions-item label="业务员">{{ detailData.salesperson || "--" }}</el-descriptions-item> <el-descriptions-item label="报价日期">{{ detailData.quotationDate || "--" }}</el-descriptions-item> <el-descriptions-item label="有效期至">{{ detailData.validDate || "--" }}</el-descriptions-item> <el-descriptions-item label="付款方式">{{ detailData.paymentMethod || "--" }}</el-descriptions-item> <el-descriptions-item label="报价总额" :span="2"> <span style="font-size: 18px; color: #e6a23c; font-weight: bold;"> ¥{{ Number(detailData.totalAmount ?? 0).toFixed(2) }} </span> </el-descriptions-item> </el-descriptions> <div v-if="detailData.products.length" style="margin-top: 20px;"> <h4>产品明细</h4> <el-table :data="detailData.products" border style="width: 100%"> <el-table-column prop="product" label="产品名称" /> <el-table-column prop="specification" label="规格型号" /> <el-table-column prop="unit" label="单位" /> <el-table-column prop="unitPrice" label="单价"> <template #default="scope">¥{{ Number(scope.row.unitPrice ?? 0).toFixed(2) }}</template> </el-table-column> </el-table> </div> <div v-if="detailData.remark" style="margin-top: 20px;"> <h4>备注</h4> <p>{{ detailData.remark }}</p> </div> </div> </template> </div> <div v-if="attachmentList.length" class="detail-block"> @@ -86,10 +193,22 @@ const props = defineProps({ row: { type: Object, default: () => ({}) }, detailData: { type: Object, default: () => ({}) }, }); const formResolved = computed(() => resolveInstanceFormFields(props.row)); // 是否为特殊审批类型(采购、发货、报价) const isSpecialApprovalType = computed(() => { return [5, 7, 6].includes(props.row.businessType); }); // 详情数据(直接使用传入的 detail-data 参数) const detailData = computed(() => { return props.detailData || {}; }); const attachmentList = computed(() => { const list = props.row.storageBlobVOList || props.row.storageBlobDTOs || []; return Array.isArray(list) ? list : []; src/views/officeProcessAutomation/ApproveManage/approve-list/index.vue
@@ -172,7 +172,7 @@ class="approve-detail-dialog" > <div class="approve-detail-body"> <ApproveDetailPanel :row="detailRow" /> <ApproveDetailPanel :row="detailRow" :detail-data="detailData" /> <div class="detail-block"> <div class="detail-block-title"> 审批流程({{ detailRow.tasks?.length || detailRow.flowNodes?.length || 0 }} 项) @@ -290,7 +290,7 @@ destroy-on-close @closed="approveOpinion = ''" > <ApproveDetailPanel :row="approveDialog.row" /> <ApproveDetailPanel :row="approveDialog.row" :detail-data="detailData" /> <div class="detail-block mt16"> <div class="detail-block-title"> 审批流程({{ approveDialog.row?.tasks?.length || approveDialog.row?.flowNodes?.length || 0 }} 项) @@ -369,6 +369,7 @@ tableColumn, detailDialog, detailRow, detailData, reimburseDialog, approveDialog, approveOpinion, src/views/officeProcessAutomation/ApproveManage/approve-list/useApproveList.js
@@ -10,6 +10,9 @@ saveApprovalInstance, updateApprovalInstance, } from "@/api/officeProcessAutomation/approvalInstance.js"; import { getQuotationList } from "@/api/salesManagement/salesQuotation.js"; import { getPurchaseByCode } from "@/api/procurementManagement/procurementLedger.js"; import { getDeliveryDetailByShippingNo } from "@/api/salesManagement/deliveryLedger.js"; import useUserStore from "@/store/modules/user"; import { Search } from "@element-plus/icons-vue"; import { ElMessage, ElMessageBox } from "element-plus"; @@ -77,6 +80,7 @@ const detailDialog = reactive({ visible: false }); const detailRow = ref({}); const detailData = ref({}); const approveDialog = reactive({ visible: false, row: null }); const approveOpinion = ref(""); @@ -220,7 +224,7 @@ fetchBusinessTypeOptions(), listApprovalTemplate(TEMPLATE_TYPE_CUSTOM), ]); submitBusinessTypeOptions.value = typeOptions; submitBusinessTypeOptions.value = typeOptions.filter((x) => ![5, 6, 7].includes(x.value)); allSubmitTemplates.value = unwrapTemplateList(customRes) .filter((row) => mapEnabledFromApi(row.enabled)) .map(mapSubmitTemplateCard); @@ -288,11 +292,46 @@ await openReimburseDetail(row, "detail"); return; } detailRow.value = { ...row }; // 报价审批:用审批事由字段承载的"报价单号"去查报价列表 if (row.businessType === 6) { const quotationNo = row?.quotationNo; if (quotationNo) { const res = await getQuotationList({ quotationNo }); const records = res?.data?.records || []; detailData.value = records[0] || {}; } } // 采购审批:用审批事由字段承载的"采购合同号"去查采购详情 else if (row.businessType === 5) { const purchaseContractNumber = row?.purchaseContractNumber; if (purchaseContractNumber) { const res = await getPurchaseByCode({ purchaseContractNumber }); detailData.value = res || {}; } } // 发货审批:用审批事由字段承载的"发货单号"去查发货详情 else if (row.businessType === 7) { const shippingNo = row?.shippingNo; if (shippingNo) { const res = await getDeliveryDetailByShippingNo({ shippingNo }); detailData.value = res?.data || res || {}; } } // 其他审批类型 else { detailData.value = {}; } detailDialog.visible = true; } async function openApprove(row) { if (inferReimburseModuleKeyFromInstance(row)) { approveOpinion.value = ""; await openReimburseDetail(row, "approve"); @@ -300,6 +339,38 @@ } approveDialog.row = { ...row }; approveOpinion.value = ""; // 报价审批:用审批事由字段承载的"报价单号"去查报价列表 if (row.businessType === 6) { const quotationNo = row?.quotationNo; if (quotationNo) { const res = await getQuotationList({ quotationNo }); const records = res?.data?.records || []; detailData.value = records[0] || {}; } } // 采购审批:用审批事由字段承载的"采购合同号"去查采购详情 else if (row.businessType === 5) { const purchaseContractNumber = row?.purchaseContractNumber; if (purchaseContractNumber) { const res = await getPurchaseByCode({ purchaseContractNumber }); detailData.value = res || {}; } } // 发货审批:用审批事由字段承载的"发货单号"去查发货详情 else if (row.businessType === 7) { const shippingNo = row?.shippingNo; if (shippingNo) { const res = await getDeliveryDetailByShippingNo({ shippingNo }); detailData.value = res?.data || res || {}; } } // 其他审批类型 else { detailData.value = {}; } approveDialog.visible = true; } @@ -586,6 +657,7 @@ tableColumn, detailDialog, detailRow, detailData, reimburseDialog, approveDialog, approveOpinion, src/views/officeProcessAutomation/ApproveManage/approve-template/index.vue
@@ -380,23 +380,18 @@ <template v-if="detailAttachments.length"> <el-tag <div class="detail-attachment-list"> <div v-for="(f, i) in detailAttachments" :key="i" class="detail-attachment-tag" type="info" effect="plain" class="detail-attachment-item" @click="openAttachmentFile(f)" > {{ attachmentDisplayName(f) }} </el-tag> <el-icon class="attachment-icon"><Document /></el-icon> <span class="attachment-name">{{ attachmentDisplayName(f) }}</span> <el-icon class="attachment-download"><Download /></el-icon> </div> </div> </template> @@ -422,7 +417,7 @@ <script setup> import { ArrowRight, Plus, RefreshRight } from "@element-plus/icons-vue"; import { ArrowRight, Document, Download, Plus, RefreshRight } from "@element-plus/icons-vue"; import { ElMessage } from "element-plus"; @@ -525,6 +520,14 @@ } function openAttachmentFile(file) { const url = file?.url || file?.previewURL || file?.downloadURL || file?.previewUrl || ""; if (url) { window.open(url, "_blank"); } else { ElMessage.warning("无法打开该附件"); } } function unwrapArray(payload) { @@ -795,10 +798,40 @@ } .detail-attachment-tag { .detail-attachment-list { display: flex; flex-wrap: wrap; gap: 8px; } margin: 0 8px 8px 0; .detail-attachment-item { display: flex; align-items: center; gap: 6px; padding: 8px 12px; background: var(--el-fill-color-light); border-radius: 6px; cursor: pointer; transition: background 0.2s; } .detail-attachment-item:hover { background: var(--el-fill-color); } .attachment-icon { font-size: 16px; color: var(--el-text-color-regular); } .attachment-name { font-size: 14px; color: var(--el-text-color-primary); } .attachment-download { font-size: 14px; color: var(--el-text-color-secondary); } .text-muted { src/views/officeProcessAutomation/ApproveManage/approve-template/useApproveTemplate.js
@@ -214,10 +214,21 @@ }); } function openFormDialog(mode, row) { async function openFormDialog(mode, row) { formDialog.mode = mode; formDialog.title = mode === "add" ? "新建审批模板" : "编辑审批模板"; if (mode === "edit" && row?.id) { // 编辑时先查询详情获取完整数据(包含附件) try { const res = await getApprovalTemplateDetail(row.id); const detailData = mapTemplateFromApi(unwrapTemplateDetail(res)); resetForm(detailData); } catch { resetForm(row); } } else { resetForm(mode === "edit" ? row : null); } formDialog.visible = true; } src/views/productionPlan/productionPlan/index.vue
@@ -775,6 +775,7 @@ mergeForm.totalAssignedQuantity = totalAssignedQuantity; mergeForm.planCompleteTime = firstRow.requiredDate || ""; mergeForm.productId = firstRow.productId || ""; mergeForm.createTime = dayjs().format("YYYY-MM-DD HH:mm:ss"); mergeForm.ids = selectedRows.value.map(row => row.id); // 打开弹窗