| | |
| | | <el-input v-model="searchForm.customerName" placeholder="请输入" clearable prefix-icon="Search" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="销售合同号:"> |
| | | <el-input v-model="searchForm.salesContractNo" placeholder="请输入" clearable prefix-icon="Search" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="项目名称:"> |
| | | <el-input v-model="searchForm.projectName" placeholder="请输入" clearable prefix-icon="Search" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <!-- <el-form-item label="销售合同号:">--> |
| | | <!-- <el-input v-model="searchForm.salesContractNo" placeholder="请输入" clearable prefix-icon="Search"--> |
| | | <!-- @change="handleQuery" />--> |
| | | <!-- </el-form-item>--> |
| | | <!-- <el-input v-model="form.salesContractNo" placeholder="可手动输入或自动生成" clearable :disabled="operationType === 'view'">--> |
| | | <el-form-item label="销售订单号:"> |
| | | <el-input v-model="form.salesContractNo" placeholder="可手动输入或自动生成" clearable :disabled="operationType === 'view'" /> |
| | | </el-form-item> |
| | | <el-form-item label="录入日期:"> |
| | | <el-date-picker v-model="searchForm.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange" |
| | | placeholder="请选择" clearable @change="changeDaterange" /> |
| | |
| | | <el-table-column align="center" type="selection" width="55" fixed="left"/> |
| | | <el-table-column type="expand" width="60" fixed="left"> |
| | | <template #default="props"> |
| | | <el-table :data="props.row.children" border show-summary :summary-method="summarizeChildrenTable"> |
| | | <el-table :data="props.row.children" border show-summary :summary-method="(param) => summarizeChildrenTable(param, props.row)"> |
| | | <el-table-column align="center" label="序号" type="index"/> |
| | | <el-table-column label="产品大类" prop="productCategory" /> |
| | | <el-table-column label="规格型号" prop="specificationModel" /> |
| | |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="数量" prop="quantity" :formatter="formattedNumber" /> |
| | | <el-table-column label="数量" prop="quantity" /> |
| | | <el-table-column label="税率(%)" prop="taxRate" /> |
| | | <el-table-column label="含税单价(元)" prop="taxInclusiveUnitPrice" :formatter="formattedNumber" /> |
| | | <el-table-column label="含税总价(元)" prop="taxInclusiveTotalPrice" :formatter="formattedNumber" /> |
| | | <el-table-column label="不含税总价(元)" prop="taxExclusiveTotalPrice" :formatter="formattedNumber" /> |
| | | <el-table-column label="含税单价(元)" prop="taxInclusiveUnitPrice" :formatter="sensitiveAmountFormatter" /> |
| | | <el-table-column label="含税总价(元)" prop="taxInclusiveTotalPrice" :formatter="sensitiveAmountFormatter" /> |
| | | <el-table-column label="不含税总价(元)" prop="taxExclusiveTotalPrice" :formatter="sensitiveAmountFormatter" /> |
| | | <!--操作--> |
| | | <el-table-column Width="60px" label="操作" align="center"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | link |
| | | type="primary" |
| | | type="primary" |
| | | size="small" |
| | | :disabled="!canShip(scope.row)" |
| | | @click="openDeliveryForm(scope.row)"> |
| | |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column align="center" label="序号" type="index" width="60" /> |
| | | <el-table-column label="销售合同号" prop="salesContractNo" width="180" show-overflow-tooltip /> |
| | | <el-table-column label="销售订单号" prop="salesContractNo" width="180" show-overflow-tooltip /> |
| | | <el-table-column label="客户名称" prop="customerName" width="300" show-overflow-tooltip /> |
| | | <el-table-column label="业务员" prop="salesman" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="项目名称" prop="projectName" width="180" show-overflow-tooltip /> |
| | |
| | | <el-table-column label="其它说明事项" prop="remarks" width="200" show-overflow-tooltip /> |
| | | <el-table-column fixed="right" label="操作" min-width="200" align="center"> |
| | | <template #default="scope"> |
| | | <el-button link type="primary" size="small" @click="openForm('edit', scope.row)" :disabled="!scope.row.isEdit">编辑</el-button> |
| | | <el-button link type="primary" size="small" @click="exportSalesContracts(scope.row)">导出销售合同</el-button> |
| | | <!-- <el-button link type="primary" size="small" @click="openForm('view', scope.row)">详情</el-button>--> |
| | | <el-button link type="primary" size="small" @click="downLoadFile(scope.row)">附件</el-button> |
| | | <!-- <el-button link type="primary" size="small" @click="openDeliveryForm(scope.row)">发货</el-button>--> |
| | | <el-button link type="primary" @click="openForm('edit', scope.row)" :disabled="!scope.row.isEdit || scope.row.hasProductionRecord || !canEditLedger(scope.row)">编辑</el-button> |
| | | <el-button link type="primary" @click="downLoadFile(scope.row)">附件</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | |
| | | :operation-type="operationType" @close="closeDia" @confirm="submitForm" @cancel="closeDia"> |
| | | <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef"> |
| | | <!-- 报价单导入入口:放在表单顶部,选择后反显客户/业务员等 --> |
| | | <el-row v-if="operationType === 'add'" style="margin-bottom: 10px;"> |
| | | <el-col :span="24" style="text-align: right;"> |
| | | <el-button type="primary" plain @click="openQuotationDialog"> |
| | | 从销售报价导入 |
| | | </el-button> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="销售合同号:" prop="salesContractNo"> |
| | | <el-input v-model="form.salesContractNo" placeholder="自动生成" clearable disabled /> |
| | | <el-form-item label="销售订单号:" prop="salesContractNo"> |
| | | <el-input v-model="form.salesContractNo" placeholder="可手动输入或自动生成" clearable :disabled="operationType === 'view'" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="业务员:" prop="salesman"> |
| | | <el-select v-model="form.salesman" placeholder="请选择" clearable :disabled="operationType === 'view'" filterable> |
| | | <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName" |
| | | :value="item.nickName" /> |
| | | <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName" :value="item.nickName" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <!-- 第2行:客户名称 + 签订地点 --> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="客户名称:" prop="customerId"> |
| | | <el-select v-model="form.customerId" placeholder="请选择" clearable :disabled="operationType === 'view'" filterable> |
| | | <el-option v-for="item in customerOption" :key="item.id" :label="item.customerName" :value="item.id"> |
| | | {{ |
| | | item.customerName |
| | | }} |
| | | {{ item.customerName + "——" + item.taxpayerIdentificationNumber }} |
| | | </el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="项目名称:" prop="projectName"> |
| | | <el-input v-model="form.projectName" placeholder="请输入" clearable :disabled="operationType === 'view'" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="签订地点:" prop="placeOfSinging"> |
| | | <el-input v-model="form.placeOfSinging" placeholder="请输入" clearable :disabled="operationType === 'view'" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="签订日期:" prop="executionDate"> |
| | | <el-date-picker style="width: 100%" v-model="form.executionDate" value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" type="date" placeholder="请选择" clearable :disabled="operationType === 'view'" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="付款方式"> |
| | | <el-input v-model="form.paymentMethod" placeholder="请输入" clearable :disabled="operationType === 'view'" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="录入人:" prop="entryPerson"> |
| | | <el-select v-model="form.entryPerson" |
| | | filterable |
| | | default-first-option |
| | | :reserve-keyword="false" placeholder="请选择" clearable @change="changs"> |
| | | <el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="录入日期:" prop="entryDate"> |
| | | <el-date-picker style="width: 100%" v-model="form.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" |
| | | type="date" placeholder="请选择" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <!-- 第3行:签订日期 + 付款方式 --> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="交货日期:" prop="entryDate"> |
| | | <el-date-picker style="width: 100%" v-model="form.deliveryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" |
| | | type="date" placeholder="请选择" clearable /> |
| | | <el-form-item label="签订日期:" prop="executionDate"> |
| | | <el-date-picker style="width: 100%" v-model="form.executionDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="date" placeholder="请选择" clearable :disabled="operationType === 'view'" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="签订地点:" prop="placeOfSinging"> |
| | | <el-input v-model="form.placeOfSinging" placeholder="请输入" clearable :disabled="operationType === 'view'" /> |
| | | <el-col :span="12"> |
| | | <el-form-item label="付款方式" prop="paymentMethod"> |
| | | <el-input v-model="form.paymentMethod" placeholder="请输入" clearable :disabled="operationType === 'view'" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <!-- 第4行:录入人 + 录入日期 --> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="录入人:" prop="entryPerson"> |
| | | <el-select v-model="form.entryPerson" filterable default-first-option :reserve-keyword="false" placeholder="请选择" clearable @change="changs"> |
| | | <el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="录入日期:" prop="entryDate"> |
| | | <el-date-picker style="width: 100%" v-model="form.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="date" placeholder="请选择" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <!-- 第5行:交货日期(单独居中) --> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="交货日期:" prop="deliveryDate"> |
| | | <el-date-picker style="width: 100%" v-model="form.deliveryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="date" placeholder="请选择" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"></el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-form-item label="产品信息:" prop="entryDate"> |
| | |
| | | <el-col :span="12"> |
| | | <el-form-item label="税率(%):" prop="taxRate"> |
| | | <el-select v-model="productForm.taxRate" placeholder="请选择" clearable @change="calculateFromTaxRate"> |
| | | <el-option label="1" value="1" /> |
| | | <el-option label="6" value="6" /> |
| | | <el-option label="13" value="13" /> |
| | | <el-option label="0" :value="0" /> |
| | | <el-option label="1" :value="1" /> |
| | | <el-option label="6" :value="6" /> |
| | | <el-option label="13" :value="13" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | <el-form-item label="含税单价(元):" prop="taxInclusiveUnitPrice"> |
| | | <el-input-number :step="0.01" :min="0" v-model="productForm.taxInclusiveUnitPrice" style="width: 100%" |
| | | :precision="3" |
| | | placeholder="请输入" clearable @change="calculateFromUnitPrice" /> |
| | | placeholder="请输入" clearable @change="calculateFromQuantity" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | |
| | | <div> |
| | | <el-button |
| | | type="danger" |
| | | size="small" |
| | | @click="removeApproverNode(index)" |
| | | v-if="approverNodes.length > 1" |
| | | >删除</el-button> |
| | |
| | | unit: "", |
| | | quantity: "", |
| | | taxInclusiveUnitPrice: "", |
| | | taxRate: "", |
| | | taxRate: 0, |
| | | taxInclusiveTotalPrice: "", |
| | | taxExclusiveTotalPrice: "", |
| | | invoiceType: "", |
| | |
| | | }); |
| | | }; |
| | | const formattedNumber = (row, column, cellValue) => { |
| | | if (cellValue === undefined || cellValue === null || cellValue === "") { |
| | | return "0.00"; |
| | | } |
| | | return parseFloat(cellValue).toFixed(3); |
| | | }; |
| | | const findLedgerRecordByRow = (row) => { |
| | | if (!row) return null; |
| | | if ( |
| | | row.maintainer !== undefined || |
| | | row.maintainerName !== undefined || |
| | | row.entryPerson !== undefined || |
| | | row.entryPersonName !== undefined |
| | | ) { |
| | | return row; |
| | | } |
| | | if (row.salesLedgerId !== undefined && row.salesLedgerId !== null) { |
| | | return tableData.value.find((item) => String(item.id) === String(row.salesLedgerId)) || null; |
| | | } |
| | | return null; |
| | | }; |
| | | const isCurrentUserMaintainer = (row) => { |
| | | const ledgerRecord = findLedgerRecordByRow(row); |
| | | if (!ledgerRecord) return true; |
| | | const currentUserId = String(userStore.id ?? ""); |
| | | const currentNickName = String(userStore.nickName ?? "").trim(); |
| | | const maintainerId = ledgerRecord.maintainerId ?? ledgerRecord.entryPerson; |
| | | const maintainerName = |
| | | ledgerRecord.maintainerName ?? ledgerRecord.maintainer ?? ledgerRecord.entryPersonName; |
| | | if (maintainerId !== undefined && maintainerId !== null && String(maintainerId) !== "") { |
| | | return String(maintainerId) === currentUserId; |
| | | } |
| | | if (maintainerName !== undefined && maintainerName !== null && String(maintainerName).trim() !== "") { |
| | | return String(maintainerName).trim() === currentNickName; |
| | | } |
| | | return true; |
| | | }; |
| | | const canEditLedger = (row) => isCurrentUserMaintainer(row); |
| | | const canDeleteLedger = (row) => isCurrentUserMaintainer(row); |
| | | const sensitiveAmountFormatter = (row, column, cellValue) => { |
| | | if (!isCurrentUserMaintainer(row)) { |
| | | return "*****"; |
| | | } |
| | | return formattedNumber(row, column, cellValue); |
| | | }; |
| | | // 获取tree子数据 |
| | | const getModels = (value) => { |
| | |
| | | }); |
| | | }; |
| | | // 子表合计方法 |
| | | const summarizeChildrenTable = (param) => { |
| | | const summarizeChildrenTable = (param, parentRow) => { |
| | | if (!isCurrentUserMaintainer(parentRow)) { |
| | | const { columns } = param; |
| | | return columns.map((column, index) => { |
| | | if (index === 0) { |
| | | return "合计"; |
| | | } |
| | | if (["taxInclusiveUnitPrice", "taxInclusiveTotalPrice", "taxExclusiveTotalPrice"].includes(column.property)) { |
| | | return "*****"; |
| | | } |
| | | return ""; |
| | | }); |
| | | } |
| | | return proxy.summarizeTable(param, [ |
| | | "taxInclusiveUnitPrice", |
| | | "taxInclusiveTotalPrice", |
| | | "taxExclusiveTotalPrice", |
| | | ], { |
| | | taxInclusiveUnitPrice: { decimalPlaces: 3 }, |
| | | taxInclusiveTotalPrice: { decimalPlaces: 3 }, |
| | | taxExclusiveTotalPrice: { decimalPlaces: 3 }, |
| | | }); |
| | | taxInclusiveUnitPrice: { decimalPlaces: 3 }, |
| | | taxInclusiveTotalPrice: { decimalPlaces: 3 }, |
| | | taxExclusiveTotalPrice: { decimalPlaces: 3 }, |
| | | }); |
| | | }; |
| | | // 判断是否能编辑 |
| | | const canEditLedger = (row) => { |
| | | // 如果是维护人,则可以编辑 |
| | | return Number(row.entryPerson) === Number(userStore.id); |
| | | }; |
| | | |
| | | // 判断是否能删除 |
| | | const canDeleteLedger = (row) => { |
| | | // 如果是维护人,则可以删除 |
| | | return Number(row.entryPerson) === Number(userStore.id); |
| | | }; |
| | | |
| | | // 判断是否是维护人(用于权限校验) |
| | | const isMaintainer = (row) => { |
| | | return row.entryPerson === userStore.id; |
| | | }; |
| | | |
| | | // 打开弹框 |
| | | const openForm = async (type, row) => { |
| | | if (type === "edit" && row && !canEditLedger(row)) { |
| | |
| | | productData.value = products.map((p) => { |
| | | const quantity = Number(p.quantity ?? 0) || 0; |
| | | const unitPrice = Number(p.unitPrice ?? 0) || 0; |
| | | const taxRate = "0"; // 默认 13%,便于直接提交(如需可在产品中自行修改) |
| | | const taxRate = Number(p.taxRate ?? 0) || 0; // 默认 13%,便于直接提交(如需可在产品中自行修改) |
| | | const taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(3); |
| | | const taxExclusiveTotalPrice = proxy.calculateTaxExclusiveTotalPrice(taxInclusiveTotalPrice, taxRate, 3); |
| | | return { |
| | |
| | | } |
| | | |
| | | productOperationType.value = type; |
| | | productForm.value = {}; |
| | | productForm.value = { |
| | | taxRate: 0, |
| | | invoiceType: "增普票" |
| | | }; |
| | | proxy.resetForm("productFormRef"); |
| | | if (type === "edit") { |
| | | productForm.value = { ...row }; |
| | |
| | | const submitProduct = () => { |
| | | proxy.$refs["productFormRef"].validate((valid) => { |
| | | if (valid) { |
| | | productForm.value.taxRate = productForm.value.taxRate?productForm.value.taxRate:0; |
| | | if (operationType.value === "edit") { |
| | | submitProductEdit(); |
| | | } else { |
| | |
| | | /** 判断单个产品是否已发货(根据shippingStatus判断,已发货或审核通过不可编辑和删除) */ |
| | | const isProductShipped = (product) => { |
| | | if (!product) return false; |
| | | |
| | | const status = String(product.shippingStatus || "").trim(); |
| | | // 如果发货状态是"已发货"或"审核通过",则不可编辑和删除 |
| | | return status === "已发货" || status === "审核通过"; |
| | |
| | | <div class="print-page"> |
| | | <div class="delivery-note"> |
| | | <div class="header"> |
| | | <div class="company-name">阳光彩印有限责任公司</div> |
| | | <div class="document-title">零售发货单</div> |
| | | </div> |
| | | |
| | |
| | | </div> |
| | | <div> |
| | | <span class="label">客户名称:</span> |
| | | <span class="value">${item.customerName || '张爱有'}</span> |
| | | <span class="value">${item.customerName}</span> |
| | | </div> |
| | | </div> |
| | | <div class="info-row"> |