| | |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" |
| | | @click="handleQuery"> 搜索 </el-button> |
| | | @click="handleQuery"> 搜索 |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | |
| | | </el-button> |
| | | <el-button type="primary" |
| | | plain |
| | | @click="handleImport">导入</el-button> |
| | | @click="handleImport">导入 |
| | | </el-button> |
| | | <el-button @click="handleOut">导出</el-button> |
| | | <el-button type="danger" |
| | | plain |
| | | @click="handleDelete">删除</el-button> |
| | | @click="handleDelete">删除 |
| | | </el-button> |
| | | <el-button type="primary" |
| | | plain |
| | | @click="handlePrint">打印</el-button> |
| | | @click="handlePrint">打印 |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | <el-table :data="tableData" |
| | |
| | | width="100px" |
| | | align="center"> |
| | | <template #default="scope"> |
| | | <el-tag v-if="scope.row.approveStatus === 1 && (!scope.row.shippingDate || !scope.row.shippingCarNumber)" |
| | | type="success">充足</el-tag> |
| | | <el-tag v-else-if="scope.row.approveStatus === 0 && (scope.row.shippingDate || scope.row.shippingCarNumber)" |
| | | type="success">已出库</el-tag> |
| | | <el-tag |
| | | v-if="scope.row.approveStatus === 1 && scope.row.noQuantity !== 0" |
| | | type="success">充足 |
| | | </el-tag> |
| | | <el-tag |
| | | v-else-if="scope.row.approveStatus === 0 && scope.row.noQuantity === 0" |
| | | type="success">已出库 |
| | | </el-tag> |
| | | <el-tag v-else |
| | | type="danger">不足</el-tag> |
| | | type="danger">不足 |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="发货状态" |
| | |
| | | <template #default="scope"> |
| | | <div> |
| | | <el-tag type="success" |
| | | v-if="scope.row.shippingCarNumber">{{ scope.row.shippingCarNumber }}</el-tag> |
| | | v-if="scope.row.shippingCarNumber">{{ scope.row.shippingCarNumber }} |
| | | </el-tag> |
| | | <el-tag v-else |
| | | type="info">-</el-tag> |
| | | type="info">- |
| | | </el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | <div> |
| | | <div v-if="scope.row.shippingDate">{{ scope.row.shippingDate }}</div> |
| | | <el-tag v-else |
| | | type="info">-</el-tag> |
| | | type="info">- |
| | | </el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="数量" |
| | | prop="quantity" /> |
| | | <el-table-column label="待发货数量" |
| | | prop="noQuantity"/> |
| | | <el-table-column label="税率(%)" |
| | | prop="taxRate" /> |
| | | <el-table-column label="含税单价(元)" |
| | |
| | | <el-button link |
| | | type="primary" |
| | | @click="openForm('edit', scope.row)" |
| | | :disabled="!scope.row.isEdit || scope.row.hasProductionRecord || !canEditLedger(scope.row)">编辑</el-button> |
| | | :disabled="!scope.row.isEdit || scope.row.hasProductionRecord || !canEditLedger(scope.row)">编辑 |
| | | </el-button> |
| | | <el-button link |
| | | type="primary" |
| | | @click="openFileDialog(scope.row)">附件</el-button> |
| | | @click="openFileDialog(scope.row)">附件 |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | |
| | | prop="entryDate"> |
| | | <el-button v-if="operationType !== 'view'" |
| | | type="primary" |
| | | @click="openProductForm('add')">添加</el-button> |
| | | @click="openProductForm('add')">添加 |
| | | </el-button> |
| | | <el-button v-if="operationType !== 'view'" |
| | | plain |
| | | type="danger" |
| | | @click="deleteProduct">删除</el-button> |
| | | @click="deleteProduct">删除 |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-row> |
| | | <el-table :data="productData" |
| | |
| | | type="primary" |
| | | size="small" |
| | | :disabled="isProductShipped(scope.row)" |
| | | @click="openProductForm('edit', scope.row,scope.$index)">编辑</el-button> |
| | | @click="openProductForm('edit', scope.row,scope.$index)">编辑 |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | |
| | | style="max-width: 260px;" |
| | | @change="fetchQuotationList" /> |
| | | <el-button type="primary" |
| | | @click="fetchQuotationList">搜索</el-button> |
| | | @click="fetchQuotationList">搜索 |
| | | </el-button> |
| | | <el-button @click="resetQuotationSearch">重置</el-button> |
| | | </div> |
| | | <el-table :data="quotationList" |
| | |
| | | <template #default="scope"> |
| | | <el-button type="primary" |
| | | link |
| | | @click="applyQuotation(scope.row)">选择</el-button> |
| | | @click="applyQuotation(scope.row)">选择 |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | |
| | | placeholder="请选择" |
| | | clearable |
| | | @change="calculateFromTaxRate"> |
| | | <el-option label="1" |
| | | value="1" /> |
| | | <el-option label="6" |
| | | value="6" /> |
| | | <el-option label="13" |
| | | value="13" /> |
| | | <el-option |
| | | v-for="dict in tax_rate" |
| | | :key="dict.value" |
| | | :label="dict.label" |
| | | :value="dict.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | 仅支持 xls/xlsx,大小不超过 10MB。 |
| | | <el-button link |
| | | type="primary" |
| | | @click="downloadTemplate">下载导入模板</el-button> |
| | | @click="downloadTemplate">下载导入模板 |
| | | </el-button> |
| | | </div> |
| | | </template> |
| | | </el-upload> |
| | | </FormDialog> |
| | | <!-- // todo 附件预览相关 --> |
| | | <!-- 附件列表弹窗 --> |
| | | <FileList v-if="fileDialogVisible" v-model:visible="fileDialogVisible" record-type="sales_ledger" :record-id="recordId" /> |
| | | <FileList v-if="fileDialogVisible" v-model:visible="fileDialogVisible" record-type="sales_ledger" |
| | | :record-id="recordId"/> |
| | | <!-- 打印预览弹窗 --> |
| | | <el-dialog v-model="printPreviewVisible" |
| | | title="打印预览" |
| | |
| | | <div class="print-preview-container"> |
| | | <div class="print-preview-header"> |
| | | <el-button type="primary" |
| | | @click="executePrint">执行打印</el-button> |
| | | @click="executePrint">执行打印 |
| | | </el-button> |
| | | <el-button @click="printPreviewVisible = false">关闭预览</el-button> |
| | | </div> |
| | | <div class="print-preview-content"> |
| | |
| | | </tr> |
| | | <tr v-if="!item.products || item.products.length === 0"> |
| | | <td colspan="6" |
| | | style="text-align: center; color: #999;">暂无产品数据</td> |
| | | style="text-align: center; color: #999;">暂无产品数据 |
| | | </td> |
| | | </tr> |
| | | </tbody> |
| | | <tfoot> |
| | |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="批号:" |
| | | prop="batchNo"> |
| | | <el-table :data="deliveryForm.batchNoList" |
| | | border |
| | | size="small" |
| | | max-height="260" |
| | | style="width: 100%;"> |
| | | <el-table-column label="批号" |
| | | prop="batchNo" |
| | | min-width="180"/> |
| | | <el-table-column label="数量" |
| | | min-width="120" |
| | | align="center"> |
| | | <template #default="scope"> |
| | | {{ getDeliveryBatchQuantity(scope.row) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="发货数量" |
| | | min-width="160" |
| | | align="center"> |
| | | <template #default="scope"> |
| | | <el-input-number v-model="scope.row.deliveryQuantity" |
| | | :min="0" |
| | | :max="getDeliveryBatchDeliveryMax(scope.row)" |
| | | :precision="2" |
| | | :step="0.01" |
| | | controls-position="right" |
| | | @change="handleDeliveryBatchQuantityChange(scope.row)" |
| | | style="width: 100%;"/> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="submitDelivery">确认发货</el-button> |
| | | @click="submitDelivery">确认发货 |
| | | </el-button> |
| | | <el-button @click="closeDeliveryDia">取消</el-button> |
| | | </div> |
| | | </template> |
| | |
| | | delLedgerFile, |
| | | getProductInventory, |
| | | } from "@/api/salesManagement/salesLedger.js"; |
| | | import {getStockInventoryByModelId} from "@/api/inventoryManagement/stockInventory.js"; |
| | | import { modelList, productTreeList } from "@/api/basicData/product.js"; |
| | | import useFormData from "@/hooks/useFormData.js"; |
| | | import dayjs from "dayjs"; |
| | |
| | | const route = useRoute(); |
| | | const userStore = useUserStore(); |
| | | const { proxy } = getCurrentInstance(); |
| | | const { tax_rate } = proxy.useDict("tax_rate"); |
| | | const tableData = ref([]); |
| | | const productData = ref([]); |
| | | const selectedRows = ref([]); |
| | |
| | | // 发货相关 |
| | | const deliveryFormVisible = ref(false); |
| | | const currentDeliveryRow = ref(null); |
| | | const getDeliveryBatchQuantity = item => { |
| | | const quantity = item?.qualitity |
| | | ?? item?.quantity |
| | | ?? item?.unLockedQuantity |
| | | ?? item?.qualifiedUnLockedQuantity |
| | | ?? item?.qualifiedQuantity |
| | | ?? item?.stockQuantity; |
| | | return quantity ?? 0; |
| | | }; |
| | | const getCurrentDeliveryRowQuantity = () => { |
| | | return Number(currentDeliveryRow.value?.noQuantity || 0); |
| | | }; |
| | | const getDeliveryBatchDeliveryMax = row => { |
| | | const productQuantity = getCurrentDeliveryRowQuantity(); |
| | | const batchQuantity = Number(getDeliveryBatchQuantity(row) || 0); |
| | | const otherBatchTotal = (deliveryForm.value.batchNoList || []).reduce( |
| | | (sum, item) => { |
| | | if (item?.id === row?.id) return sum; |
| | | return sum + Number(item?.deliveryQuantity || 0); |
| | | }, |
| | | 0 |
| | | ); |
| | | const remainingProductQuantity = Math.max( |
| | | 0, |
| | | productQuantity - otherBatchTotal |
| | | ); |
| | | return Math.max(0, Math.min(batchQuantity, remainingProductQuantity)); |
| | | }; |
| | | const handleDeliveryBatchQuantityChange = row => { |
| | | const max = getDeliveryBatchDeliveryMax(row); |
| | | const currentValue = Number(row?.deliveryQuantity || 0); |
| | | if (currentValue > max) { |
| | | row.deliveryQuantity = max; |
| | | proxy.$modal.msgWarning("发货数量不能超过这个产品的数量"); |
| | | } |
| | | }; |
| | | const getSelectedDeliveryBatchRows = () => { |
| | | return (deliveryForm.value.batchNoList || []).filter( |
| | | item => Number(item?.deliveryQuantity || 0) > 0 |
| | | ); |
| | | }; |
| | | const getDeliveryBatchNoList = async productModelId => { |
| | | if (!productModelId) return []; |
| | | const res = await getStockInventoryByModelId(productModelId); |
| | | const rawList = Array.isArray(res?.data) |
| | | ? res.data |
| | | : res?.data?.records || res?.data?.rows || []; |
| | | const seenIds = new Set(); |
| | | return rawList.filter(item => { |
| | | if (!item?.id || !item?.batchNo || seenIds.has(item.id)) { |
| | | return false; |
| | | } |
| | | seenIds.add(item.id); |
| | | return true; |
| | | }).map(item => ({ |
| | | ...item, |
| | | deliveryQuantity: 0, |
| | | })); |
| | | }; |
| | | const deliveryFormData = reactive({ |
| | | deliveryForm: { |
| | | type: "货车", // 货车, 快递 |
| | |
| | | } |
| | | return null; // 没有找到节点,返回null |
| | | }; |
| | | |
| | | function convertIdToValue(data) { |
| | | return data.map(item => { |
| | | const { id, children, ...rest } = item; |
| | |
| | | return newItem; |
| | | }); |
| | | } |
| | | |
| | | // 根据名称反查产品大类 id,便于仅存名称时的反显 |
| | | function findNodeIdByLabel(nodes, label) { |
| | | if (!label) return null; |
| | |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | // 表格选择数据 |
| | | const handleSelectionChange = selection => { |
| | | // 过滤掉子数据 |
| | |
| | | |
| | | quotationDialogVisible.value = false; |
| | | }; |
| | | |
| | | function changs(val) { |
| | | console.log(val); |
| | | } |
| | | |
| | | // 提交表单 |
| | | const submitForm = () => { |
| | | proxy.$refs["formRef"].validate(valid => { |
| | |
| | | */ |
| | | const getShippingStatusText = row => { |
| | | // 如果已发货(有发货日期或车牌号),显示"已发货" |
| | | if (row.shippingDate || row.shippingCarNumber) { |
| | | return "已发货"; |
| | | } |
| | | // if (row.shippingDate || row.shippingCarNumber) { |
| | | // return "已发货"; |
| | | // } |
| | | |
| | | // 获取发货状态字段 |
| | | const status = row.shippingStatus; |
| | |
| | | */ |
| | | const getShippingStatusType = row => { |
| | | // 如果已发货(有发货日期或车牌号),显示绿色 |
| | | if (row.shippingDate || row.shippingCarNumber) { |
| | | if (row.shippingStatus === "已发货") { |
| | | return "success"; |
| | | } |
| | | |
| | |
| | | const shippingStatus = row.shippingStatus; |
| | | |
| | | // 如果已发货(有发货日期或车牌号),不能再次发货 |
| | | if (row.shippingDate || row.shippingCarNumber) { |
| | | if (shippingStatus === "已发货") { |
| | | return false; |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | // 打开发货弹框 |
| | | const openDeliveryForm = row => { |
| | | const openDeliveryForm = async row => { |
| | | // 检查是否可以发货 |
| | | if (!canShip(row)) { |
| | | proxy.$modal.msgWarning( |
| | |
| | | } |
| | | |
| | | currentDeliveryRow.value = row; |
| | | const batchNoList = await getDeliveryBatchNoList( |
| | | row.productModelId || row.modelId |
| | | ); |
| | | deliveryForm.value = { |
| | | type: "货车", |
| | | batchNo: [], |
| | | batchNoList, |
| | | }; |
| | | deliveryFormVisible.value = true; |
| | | }; |
| | |
| | | const submitDelivery = () => { |
| | | proxy.$refs["deliveryFormRef"].validate(valid => { |
| | | if (valid) { |
| | | const selectedBatchRows = getSelectedDeliveryBatchRows(); |
| | | if (selectedBatchRows.length === 0) { |
| | | proxy.$modal.msgWarning("请至少填写一个批号的发货数量"); |
| | | return; |
| | | } |
| | | const totalDeliveryQuantity = selectedBatchRows.reduce( |
| | | (sum, item) => sum + Number(item.deliveryQuantity || 0), |
| | | 0 |
| | | ); |
| | | const currentRowQuantity = Number(currentDeliveryRow.value?.quantity || 0); |
| | | if (currentRowQuantity > 0 && totalDeliveryQuantity > currentRowQuantity) { |
| | | proxy.$modal.msgWarning("批号发货总数不能超过当前产品数量"); |
| | | return; |
| | | } |
| | | // 保存当前展开的行ID,以便发货后重新加载子表格数据 |
| | | const currentExpandedKeys = [...expandedRowKeys.value]; |
| | | const salesLedgerId = currentDeliveryRow.value.salesLedgerId; |
| | | deliveryForm.value.batchNo = selectedBatchRows.map(item => item.id); |
| | | const productModelId = currentDeliveryRow.value.productModelId || currentDeliveryRow.value.modelId; |
| | | addShippingInfo({ |
| | | salesLedgerId: salesLedgerId, |
| | | salesLedgerProductId: currentDeliveryRow.value.id, |
| | | type: deliveryForm.value.type, |
| | | batchNo: deliveryForm.value.batchNo, |
| | | batchNoDetailList: selectedBatchRows.map(item => ({ |
| | | stockInventoryId: item.id, |
| | | batchNo: item.batchNo, |
| | | quantity: Number(item.deliveryQuantity || 0), |
| | | productModelId: productModelId, |
| | | })), |
| | | }).then(() => { |
| | | proxy.$modal.msgSuccess("发货成功"); |
| | | closeDeliveryDia(); |
| | |
| | | justify-content: space-between; |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .print-preview-dialog { |
| | | .el-dialog__body { |
| | | padding: 0; |