| | |
| | | <el-button @click="handleOut">导出</el-button> |
| | | <el-button type="danger" plain @click="handleDelete">删除 |
| | | </el-button> |
| | | <el-button type="warning" plain @click="handlePrint">打印单据</el-button> |
| | | </div> |
| | | <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange" |
| | | :expand-row-keys="expandedRowKeys" :row-key="(row) => row.id" show-summary :summary-method="summarizeMainTable" |
| | |
| | | <el-table-column label="可用数量" prop="availableQuality" /> |
| | | <el-table-column label="退货数量" prop="returnQuality" /> |
| | | <el-table-column label="税率(%)" prop="taxRate" /> |
| | | <el-table-column label="含税单价(元)" prop="taxInclusiveUnitPrice" :formatter="unitPriceFormatter" /> |
| | | <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> |
| | |
| | | <el-table-column label="录入人" prop="recorderName" width="120" show-overflow-tooltip /> |
| | | <el-table-column label="录入日期" prop="entryDate" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="备注" prop="remarks" width="200" show-overflow-tooltip /> |
| | | <el-table-column fixed="right" label="操作" width="180" align="center"> |
| | | <el-table-column fixed="right" label="操作" width="220" align="center"> |
| | | <template #default="scope"> |
| | | <el-button link type="primary" @click="openForm('detail', scope.row)">详情 |
| | | </el-button> |
| | | <el-button link type="primary" @click="openForm('edit', scope.row)" |
| | | :disabled="scope.row.stockInStatus === '完全入库'">编辑 |
| | | </el-button> |
| | | <el-button link type="primary" @click="openFileDialog(scope.row)">附件</el-button> |
| | | <el-button link type="primary" @click="downloadOrder(scope.row.id)">下载</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="录入人:" prop="recorderId"> |
| | | <el-select v-model="form.recorderId" placeholder="请选择" clearable filterable> |
| | | <el-select v-model="form.recorderId" placeholder="请选择" clearable filterable disabled> |
| | | <el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId" /> |
| | | </el-select> |
| | | </el-form-item> |
| | |
| | | <el-table-column label="规格型号" prop="specificationModel" /> |
| | | <el-table-column label="单位" prop="unit" width="70" /> |
| | | <el-table-column label="数量" prop="quantity" width="70" /> |
| | | <el-table-column label="库存预警数量" prop="warnNum" width="120" show-overflow-tooltip /> |
| | | <!-- <el-table-column label="库存预警数量" prop="warnNum" width="120" show-overflow-tooltip />--> |
| | | <el-table-column label="税率(%)" prop="taxRate" width="80" /> |
| | | <el-table-column label="含税单价(元)" prop="taxInclusiveUnitPrice" :formatter="unitPriceFormatter" width="150" /> |
| | | <el-table-column label="含税单价(元)" prop="taxInclusiveUnitPrice" :formatter="formattedNumber" width="150" /> |
| | | <el-table-column label="含税总价(元)" prop="taxInclusiveTotalPrice" :formatter="formattedNumber" width="150" /> |
| | | <el-table-column label="不含税总价(元)" prop="taxExclusiveTotalPrice" :formatter="formattedNumber" width="150" /> |
| | | <el-table-column label="是否质检" prop="isChecked" width="150"> |
| | |
| | | @cancel="closeProductDia"> |
| | | <el-form :model="productForm" label-width="140px" label-position="top" :rules="productRules" ref="productFormRef"> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="产品大类:" prop="productId"> |
| | | <el-tree-select v-model="productForm.productId" placeholder="请选择" clearable filterable check-strictly |
| | | @change="getModels" :data="productOptions" :render-after-expand="false" style="width: 100%" /> |
| | | <el-col :span="12"> |
| | | <el-form-item label="产品大类:" prop="productCategory"> |
| | | <el-input v-model="productForm.productCategory" |
| | | placeholder="点击选择" |
| | | readonly |
| | | @click="showProductSelectDialog = true" |
| | | style="cursor:pointer" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="24"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="规格型号:" prop="productModelId"> |
| | | <el-select v-model="productForm.productModelId" placeholder="请选择" filterable clearable |
| | | @change="getProductModel"> |
| | | <el-option v-for="item in modelOptions" :key="item.id" :label="item.model" :value="item.id" /> |
| | | </el-select> |
| | | <el-input v-model="productForm.specificationModel" |
| | | placeholder="点击选择" |
| | | readonly |
| | | @click="showProductSelectDialog = true" |
| | | style="cursor:pointer" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="含税单价(元):" prop="taxInclusiveUnitPrice"> |
| | | <el-input-number v-model="productForm.taxInclusiveUnitPrice" :precision="6" :step="0.1" :min="0" clearable |
| | | <el-input-number v-model="productForm.taxInclusiveUnitPrice" :precision="6" :step="0.000001" :min="0" clearable |
| | | style="width: 100%" @change="mathNum" /> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="含税总价(元):" prop="taxInclusiveTotalPrice"> |
| | | <el-input-number v-model="productForm.taxInclusiveTotalPrice" :precision="2" :step="0.1" :min="0" |
| | | <el-input-number v-model="productForm.taxInclusiveTotalPrice" :precision="6" :step="0.000001" :min="0" |
| | | clearable style="width: 100%" @change="reverseMathNum('taxInclusiveTotalPrice')" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="不含税总价(元):" prop="taxExclusiveTotalPrice"> |
| | | <el-input-number v-model="productForm.taxExclusiveTotalPrice" :precision="2" :step="0.1" :min="0" |
| | | <el-input-number v-model="productForm.taxExclusiveTotalPrice" :precision="6" :step="0.000001" :min="0" |
| | | clearable style="width: 100%" @change="reverseMathNum('taxExclusiveTotalPrice')" /> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="库存预警数量:" prop="warnNum"> |
| | | <el-input-number v-model="productForm.warnNum" :precision="2" :step="0.1" :min="0" clearable |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <!-- <el-col :span="12">--> |
| | | <!-- <el-form-item label="库存预警数量:" prop="warnNum">--> |
| | | <!-- <el-input-number v-model="productForm.warnNum" :precision="2" :step="0.1" :min="0" clearable--> |
| | | <!-- style="width: 100%" />--> |
| | | <!-- </el-form-item>--> |
| | | <!-- </el-col>--> |
| | | <el-col :span="12"> |
| | | <el-form-item label="是否质检:" prop="isChecked"> |
| | | <el-radio-group v-model="productForm.isChecked"> |
| | |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <!-- <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="是否质检:" prop="isChecked"> |
| | | <el-radio-group v-model="productForm.isChecked"> |
| | | <el-radio label="是" :value="true" /> |
| | | <el-radio label="否" :value="false" /> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row>--> |
| | | </el-form> |
| | | </FormDialog> |
| | | <ProductSelectDialog v-model="showProductSelectDialog" |
| | | @confirm="handleProductSelect" |
| | | single /> |
| | | <FileList v-if="fileListDialogVisible" v-model:visible="fileListDialogVisible" record-type="purchase_ledger" |
| | | :record-id="recordId" /> |
| | | <Detail ref="detailRef" /> |
| | |
| | | productList, |
| | | getPurchaseById, |
| | | getOptions, |
| | | getPrintData, |
| | | getPurchaseTemplateList, |
| | | delPurchaseTemplate, |
| | | } from "@/api/procurementManagement/procurementLedger.js"; |
| | |
| | | const fileList = ref([]); |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { modelList, productTreeList } from "@/api/basicData/product.js"; |
| | | import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue"; |
| | | import dayjs from "dayjs"; |
| | | import FileUpload from "@/components/AttachmentUpload/file/index.vue"; |
| | | import { tableAmountFormatter, formatDecimal, buildAmountSummaryFormat } from '@/utils/numberFormat'; |
| | | import { downloadPurchaseJpg, printPurchaseMulti } from "@/utils/documentPrint.js"; |
| | | |
| | | const userStore = useUserStore(); |
| | | |
| | |
| | | const { form, rules } = toRefs(data); |
| | | const { form: searchForm } = useFormData({ |
| | | ...data.searchForm, |
| | | // 设置录入日期范围为当天 |
| | | entryDate: [ |
| | | dayjs().startOf("day").format("YYYY-MM-DD"), |
| | | dayjs().endOf("day").format("YYYY-MM-DD"), |
| | | ], |
| | | entryDateStart: dayjs().startOf("day").format("YYYY-MM-DD"), |
| | | entryDateEnd: dayjs().endOf("day").format("YYYY-MM-DD"), |
| | | }); |
| | | |
| | | // 产品表单弹框数据 |
| | | const productFormVisible = ref(false); |
| | | const showProductSelectDialog = ref(false); |
| | | const productOperationType = ref(""); |
| | | const productOperationIndex = ref(""); |
| | | const currentId = ref(""); |
| | |
| | | isChecked: false, |
| | | }, |
| | | productRules: { |
| | | productId: [{ required: true, message: "请选择", trigger: "change" }], |
| | | productModelId: [{ required: true, message: "请选择", trigger: "change" }], |
| | | productCategory: [{ required: true, message: "请选择产品大类", trigger: "change" }], |
| | | productModelId: [{ required: true, message: "请选择规格型号", trigger: "change" }], |
| | | unit: [{ required: true, message: "请输入", trigger: "blur" }], |
| | | quantity: [{ required: true, message: "请输入", trigger: "blur" }], |
| | | taxInclusiveUnitPrice: [ |
| | | { required: true, message: "请输入", trigger: "blur" }, |
| | | ], |
| | | taxRate: [{ required: true, message: "请选择", trigger: "change" }], |
| | | warnNum: [{ required: true, message: "请选择", trigger: "change" }], |
| | | // warnNum: [{ required: true, message: "请选择", trigger: "change" }], |
| | | taxInclusiveTotalPrice: [ |
| | | { required: true, message: "请输入", trigger: "blur" }, |
| | | ], |
| | |
| | | handleQuery(); |
| | | }; |
| | | |
| | | const formattedNumber = (row, column, cellValue) => { |
| | | return parseFloat(cellValue).toFixed(2); |
| | | }; |
| | | const unitPriceFormatter = (row, column, cellValue) => { |
| | | return parseFloat(cellValue).toFixed(6); |
| | | }; |
| | | const formattedNumber = tableAmountFormatter; |
| | | // 查询列表 |
| | | /** 搜索按钮操作 */ |
| | | const handleQuery = () => { |
| | |
| | | "futureTickets", |
| | | "futureTicketsAmount", |
| | | ], |
| | | { |
| | | ticketsNum: { noDecimal: true }, // 不保留小数 |
| | | futureTickets: { noDecimal: true }, // 不保留小数 |
| | | } |
| | | buildAmountSummaryFormat( |
| | | [ |
| | | "taxInclusiveUnitPrice", |
| | | "taxInclusiveTotalPrice", |
| | | "taxExclusiveTotalPrice", |
| | | "ticketsAmount", |
| | | "futureTicketsAmount", |
| | | ], |
| | | { |
| | | ticketsNum: { noDecimal: true }, |
| | | futureTickets: { noDecimal: true }, |
| | | } |
| | | ) |
| | | ); |
| | | }; |
| | | const paginationChange = obj => { |
| | |
| | | }; |
| | | // 主表合计方法 |
| | | const summarizeMainTable = param => { |
| | | return proxy.summarizeTable(param, ["contractAmount"]); |
| | | return proxy.summarizeTable( |
| | | param, |
| | | ["contractAmount"], |
| | | buildAmountSummaryFormat(["contractAmount"]) |
| | | ); |
| | | }; |
| | | // 子表合计方法 |
| | | const summarizeProTable = param => { |
| | | return proxy.summarizeTable(param, [ |
| | | "taxInclusiveUnitPrice", |
| | | "taxInclusiveTotalPrice", |
| | | "taxExclusiveTotalPrice", |
| | | ]); |
| | | return proxy.summarizeTable( |
| | | param, |
| | | [ |
| | | "taxInclusiveUnitPrice", |
| | | "taxInclusiveTotalPrice", |
| | | "taxExclusiveTotalPrice", |
| | | ], |
| | | buildAmountSummaryFormat([ |
| | | "taxInclusiveUnitPrice", |
| | | "taxInclusiveTotalPrice", |
| | | "taxExclusiveTotalPrice", |
| | | ]) |
| | | ); |
| | | }; |
| | | // 打开弹框 |
| | | const openForm = async (type, row) => { |
| | |
| | | ); |
| | | |
| | | form.value.entryDate = getCurrentDate(); |
| | | form.value.recorderId = userStore.id; |
| | | |
| | | if (type === "add") { |
| | | // 新增时生成采购合同号 |
| | |
| | | await nextTick(); |
| | | } |
| | | }; |
| | | |
| | | // ProductSelectDialog 选中回调 |
| | | const handleProductSelect = (products) => { |
| | | if (!products || !products.length) return; |
| | | const p = products[0]; |
| | | productForm.value.productId = p.productId; |
| | | productForm.value.productCategory = p.productName || ''; |
| | | productForm.value.productModelId = p.id; |
| | | productForm.value.specificationModel = p.model || ''; |
| | | productForm.value.unit = p.unit || ''; |
| | | showProductSelectDialog.value = false; |
| | | }; |
| | | |
| | | const getProductOptions = () => { |
| | | return productTreeList().then(res => { |
| | | productOptions.value = convertIdToValue(res); |
| | |
| | | }); |
| | | }; |
| | | |
| | | // 批量打印采购单 - 多选合并预览 |
| | | const handlePrint = async () => { |
| | | if (selectedRows.value.length === 0) { |
| | | proxy.$modal.msgWarning("请选择要打印的数据"); |
| | | return; |
| | | } |
| | | proxy.$modal.loading("正在加载打印数据..."); |
| | | try { |
| | | const orders = []; |
| | | let companyName = ''; |
| | | for (const row of selectedRows.value) { |
| | | const res = await getPrintData(row.id); |
| | | const data = res.data || res; |
| | | companyName = data.companyName || companyName; |
| | | orders.push({ ledger: data.ledger, products: data.products }); |
| | | } |
| | | printPurchaseMulti(companyName, orders); |
| | | } catch (e) { |
| | | console.error('打印失败:', e); |
| | | proxy.$modal.msgError("打印失败"); |
| | | } finally { |
| | | proxy.$modal.closeLoading(); |
| | | } |
| | | }; |
| | | |
| | | // 获取当前日期并格式化为 YYYY-MM-DD |
| | | function getCurrentDate() { |
| | | const today = new Date(); |
| | |
| | | if (field === "taxInclusiveTotalPrice") { |
| | | // 已知含税总价和数量,反算含税单价 |
| | | if (productForm.value.quantity) { |
| | | productForm.value.taxInclusiveUnitPrice = ( |
| | | productForm.value.taxInclusiveUnitPrice = formatDecimal( |
| | | Number(productForm.value.taxInclusiveTotalPrice) / |
| | | Number(productForm.value.quantity) |
| | | ).toFixed(6); |
| | | ); |
| | | // 确保结果不为负数 |
| | | if (Number(productForm.value.taxInclusiveUnitPrice) < 0) { |
| | | productForm.value.taxInclusiveUnitPrice = "0"; |
| | |
| | | } |
| | | } |
| | | // 反算不含税总价 |
| | | productForm.value.taxExclusiveTotalPrice = ( |
| | | productForm.value.taxExclusiveTotalPrice = formatDecimal( |
| | | Number(productForm.value.taxInclusiveTotalPrice) / |
| | | (1 + taxRate / 100) |
| | | ).toFixed(2); |
| | | ); |
| | | // 确保结果不为负数 |
| | | if (Number(productForm.value.taxExclusiveTotalPrice) < 0) { |
| | | productForm.value.taxExclusiveTotalPrice = "0"; |
| | | } |
| | | } else if (field === "taxExclusiveTotalPrice") { |
| | | // 反算含税总价 |
| | | productForm.value.taxInclusiveTotalPrice = ( |
| | | productForm.value.taxInclusiveTotalPrice = formatDecimal( |
| | | Number(productForm.value.taxExclusiveTotalPrice) * |
| | | (1 + taxRate / 100) |
| | | ).toFixed(2); |
| | | ); |
| | | // 确保结果不为负数 |
| | | if (Number(productForm.value.taxInclusiveTotalPrice) < 0) { |
| | | productForm.value.taxInclusiveTotalPrice = "0"; |
| | | } |
| | | // 已知数量,反算含税单价 |
| | | if (productForm.value.quantity) { |
| | | productForm.value.taxInclusiveUnitPrice = ( |
| | | productForm.value.taxInclusiveUnitPrice = formatDecimal( |
| | | Number(productForm.value.taxInclusiveTotalPrice) / |
| | | Number(productForm.value.quantity) |
| | | ).toFixed(6); |
| | | ); |
| | | // 确保结果不为负数 |
| | | if (Number(productForm.value.taxInclusiveUnitPrice) < 0) { |
| | | productForm.value.taxInclusiveUnitPrice = "0"; |
| | |
| | | fileListDialogVisible.value = true; |
| | | }; |
| | | |
| | | // 下载采购单 |
| | | const downloadOrder = async (id) => { |
| | | try { |
| | | const res = await getPrintData(id); |
| | | const data = res.data || res; |
| | | downloadPurchaseJpg(data.companyName, data.ledger, data.products, '采购单_' + (data.ledger.purchaseContractNumber || id) + '.jpg'); |
| | | } catch (e) { |
| | | console.error('下载失败:', e); |
| | | } |
| | | }; |
| | | |
| | | // 打印采购单 |
| | | const printOrder = async (id) => { |
| | | try { |
| | | const res = await getPrintData(id); |
| | | const data = res.data || res; |
| | | printPurchase(data.companyName, data.ledger, data.products); |
| | | } catch (e) { |
| | | console.error('打印失败:', e); |
| | | } |
| | | }; |
| | | |
| | | // 删除模板 |
| | | const handleDeleteTemplate = async item => { |
| | | if (!item.id) { |