feat(采购退货): 增加退货详情查看功能并完善退货流程
- 新增采购退货单详情查看接口与弹窗展示
- 采购台账和采购报表增加退货相关字段显示
- 优化退货单创建流程,增加退货数量校验与金额计算
- 使用PIMTable组件重构退货单列表,提升可维护性
- 修复退货单创建表单的数据绑定与校验逻辑
| | |
| | | data |
| | | }); |
| | | } |
| | | |
| | | // 查看详情 |
| | | // purchaseReturnOrders/selectById/xxx |
| | | export function getPurchaseReturnOrderDetail(id) { |
| | | return request({ |
| | | url: "/purchaseReturnOrders/selectById/" + id, |
| | | method: "get", |
| | | }); |
| | | } |
| | |
| | | prop="unit" /> |
| | | <el-table-column label="数量" |
| | | prop="quantity" /> |
| | | <el-table-column label="可用数量" |
| | | prop="availableQuality" /> |
| | | <el-table-column label="退货数量" |
| | | prop="returnQuality" /> |
| | | |
| | | <el-table-column label="税率(%)" |
| | | prop="taxRate" /> |
| | | <el-table-column label="含税单价(元)" |
| | |
| | | <span class="stat-label">商品种类:</span> |
| | | <span class="stat-value">{{ businessSummaryStats.productTypes }}</span> |
| | | </div> |
| | | <div class="stat-item"> |
| | | <span class="stat-label">退款总额:</span> |
| | | <span class="stat-value">{{ businessSummaryStats.returnAmount }}</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | |
| | | } |
| | | }, |
| | | { |
| | | label: '采购金额', |
| | | label: '退货数量', |
| | | prop: 'returnQuantity', |
| | | width: 120, |
| | | formatData: (val) => { |
| | | return val ? parseFloat(val).toLocaleString() : '0' |
| | | } |
| | | }, |
| | | { |
| | | label: '退货金额', |
| | | prop: 'returnAmount', |
| | | width: 120, |
| | | formatData: (val) => { |
| | | return val ? `¥${parseFloat(val).toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}` : '¥0.00' |
| | | } |
| | | }, |
| | | { |
| | | label: '退款储量', |
| | | prop: 'purchaseAmount', |
| | | formatData: (val) => { |
| | | return val ? `¥${parseFloat(val).toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}` : '¥0.00' |
| | |
| | | businessSummaryStats.value.totalAmount = businessSummaryData.value.reduce((sum, item) => { |
| | | return sum + (parseFloat(item.purchaseAmount) || 0) |
| | | }, 0) |
| | | businessSummaryStats.value.productTypes = new Set(businessSummaryData.value.map(item => item.productCategory)).size |
| | | businessSummaryStats.value.returnAmount = businessSummaryData.value.reduce((sum, item) => { |
| | | return sum + (parseFloat(item.returnAmount) || 0) |
| | | }, 0) |
| | | } else { |
| | | businessSummaryStats.value = { |
| | | totalAmount: 0, |
| | |
| | | v-model="formState.no" |
| | | :placeholder="formState.isDefaultNo ? '使用系统编号' : '请输入退料单号'" |
| | | :disabled="formState.isDefaultNo" |
| | | style="width: 240px" |
| | | > |
| | | <template #append> |
| | | <el-checkbox v-model="formState.isDefaultNo" size="large" @change="handleChangeIsDefaultNo" /> |
| | |
| | | v-for="item in supplierOptions" |
| | | :key="item.id" |
| | | :label="item.supplierName" |
| | | :value="item.id" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="项目" |
| | | prop="projectId" |
| | | > |
| | | <el-select |
| | | v-model="formState.projectId" |
| | | placeholder="请选择项目" |
| | | style="width: 240px" |
| | | @focus="fetchProjectOptions" |
| | | > |
| | | <el-option |
| | | v-for="item in projectOptions" |
| | | :key="item.id" |
| | | :label="item.name" |
| | | :value="item.id" |
| | | /> |
| | | </el-select> |
| | |
| | | :reserve-keyword="false" |
| | | style="width: 240px" |
| | | @focus="fetchUserOptions" |
| | | @change="formState.preparedUserName = userOptions.find(item => item.userId === formState.preparedUserId)?.nickName || ''" |
| | | > |
| | | <el-option |
| | | v-for="item in userOptions" |
| | |
| | | style="width: 240px" |
| | | :reserve-keyword="false" |
| | | @focus="fetchUserOptions" |
| | | @change="formState.returnUserName = userOptions.find(item => item.userId === formState.returnUserId)?.nickName || ''" |
| | | > |
| | | <el-option |
| | | v-for="item in userOptions" |
| | |
| | | label="备注:" |
| | | prop="remark" |
| | | > |
| | | <el-input v-model="formState.remark" type="textarea" placeholder="请输入备注"/> |
| | | <el-input style="width: 240px" v-model="formState.remark" :rows="1" type="textarea" placeholder="请输入备注"/> |
| | | </el-form-item> |
| | | |
| | | <div style="margin: 20px 0;"> |
| | |
| | | width="70" /> |
| | | <el-table-column label="数量" |
| | | prop="quantity" |
| | | width="70" /> |
| | | width="100" /> |
| | | <el-table-column label="可退货数量" |
| | | prop="availableQuality" |
| | | width="130" /> |
| | | <el-table-column label="退货数量" |
| | | prop="returnQuantity" |
| | | width="180"> |
| | |
| | | <el-input-number v-model="scope.row.returnQuantity" |
| | | controls-position="right" |
| | | :step="1" |
| | | :min="1" |
| | | :max="scope.row.quantity" |
| | | :min="0" |
| | | :max="getReturnQtyMax(scope.row)" |
| | | :disabled="getReturnQtyMax(scope.row) <= 0" |
| | | @change="syncReturnTotal(scope.row)" |
| | | required |
| | | placeholder="请输入退货数量" /> |
| | | </template> |
| | |
| | | prop="taxInclusiveUnitPrice" |
| | | :formatter="formattedNumber" |
| | | width="150" /> |
| | | <el-table-column label="含税总价(元)" |
| | | <el-table-column label="退货总价(元)" |
| | | prop="taxInclusiveTotalPrice" |
| | | :formatter="formattedNumber" |
| | | width="150" /> |
| | | <el-table-column label="不含税总价(元)" |
| | | prop="taxExclusiveTotalPrice" |
| | | :formatter="formattedNumber" |
| | | width="150" /> |
| | | width="180"> |
| | | <template #default="scope"> |
| | | {{ formatAmount(getReturnTotal(scope.row)) || '--' }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="是否质检" |
| | | prop="isChecked" |
| | | width="150"> |
| | |
| | | <el-form-item |
| | | label="成交金额:" |
| | | prop="totalAmount" |
| | | :rules="[ |
| | | { |
| | | required: true, |
| | | message: '请输入成交金额', |
| | | trigger: 'change', |
| | | } |
| | | ]" |
| | | > |
| | | <el-input-number v-model="formState.totalAmount" |
| | | controls-position="right" |
| | | :step="0.01" |
| | | :precision="2" |
| | | style="width: 100%;" |
| | | @change="handleChangeTotalAmount" |
| | | placeholder="请输入成交金额"/> |
| | | </el-form-item> |
| | | <el-form-item label="收款方式" prop="incomeType" :rules="[ |
| | | { |
| | | required: true, |
| | | message: '请选择收款方式', |
| | | trigger: 'change', |
| | | } |
| | | ]"> |
| | | <el-select |
| | | style="width: 240px;" |
| | | v-model="formState.incomeType" |
| | | placeholder="请选择" |
| | | clearable |
| | | |
| | | > |
| | | <el-option :label="item.label" :value="item.value" v-for="(item,index) in payment_methods" :key="index" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref, computed, getCurrentInstance} from "vue"; |
| | | import {ref, computed, getCurrentInstance, watch, defineAsyncComponent} from "vue"; |
| | | import {createPurchaseReturnOrder} from "@/api/procurementManagement/purchase_return_order.js"; |
| | | import {getOptions, purchaseList} from "@/api/procurementManagement/procurementLedger.js"; |
| | | import {userListNoPageByTenantId} from "@/api/system/user.js"; |
| | | const ProductList = defineAsyncComponent(() => import("@/views/procurementManagement/purchaseReturnOrder/ProductList.vue")); |
| | | import { |
| | | productList, |
| | | } from "@/api/procurementManagement/procurementLedger.js"; |
| | | const props = defineProps({ |
| | | visible: { |
| | | type: Boolean, |
| | |
| | | } |
| | | }); |
| | | let { proxy } = getCurrentInstance() |
| | | const { payment_methods } = proxy.useDict("payment_methods"); |
| | | const emit = defineEmits(['update:visible', 'completed']); |
| | | |
| | | // 响应式数据(替代选项式的 data) |
| | |
| | | no: '', |
| | | isDefaultNo: true, |
| | | returnType: 0, |
| | | incomeType: undefined, |
| | | remark: '', |
| | | supplierId: undefined, |
| | | projectId: undefined, |
| | |
| | | }); |
| | | // 供应商选项 |
| | | const supplierOptions = ref([]) |
| | | // 项目选项 |
| | | const projectOptions = ref([]) |
| | | // 项目阶段选项 |
| | | const projectStageOptions = ref([ |
| | | { |
| | |
| | | return parseFloat(cellValue).toFixed(2); |
| | | }; |
| | | |
| | | const formatAmount = (value) => { |
| | | if (value === null || value === undefined || value === '') { |
| | | return '--' |
| | | } |
| | | const num = Number(value) |
| | | if (Number.isNaN(num)) { |
| | | return '--' |
| | | } |
| | | return num.toFixed(2) |
| | | } |
| | | |
| | | const toNumber = (val) => { |
| | | const num = Number(val) |
| | | return Number.isNaN(num) ? 0 : num |
| | | } |
| | | |
| | | const getReturnTotal = (row) => { |
| | | const qty = toNumber(row?.returnQuantity) |
| | | const unitPrice = toNumber(row?.taxInclusiveUnitPrice) |
| | | const total = qty * unitPrice |
| | | return Number(total.toFixed(2)) |
| | | } |
| | | |
| | | const syncReturnTotal = (row) => { |
| | | if (!row) { |
| | | return |
| | | } |
| | | row.taxInclusiveTotalPrice = getReturnTotal(row) |
| | | } |
| | | |
| | | const getReturnQtyMax = (row) => { |
| | | const max = Number(row?.availableQuality) |
| | | if (Number.isNaN(max) || max < 0) { |
| | | return 0 |
| | | } |
| | | return max |
| | | } |
| | | |
| | | const closeModal = () => { |
| | | isShow.value = false; |
| | | }; |
| | |
| | | param, |
| | | [ |
| | | "quantity", |
| | | "availableQuality", |
| | | "returnQuantity", |
| | | "taxInclusiveUnitPrice", |
| | | "taxInclusiveTotalPrice", |
| | |
| | | { |
| | | quantity: { noDecimal: true }, // 不保留小数 |
| | | returnQuantity: { noDecimal: true }, // 不保留小数 |
| | | availableQuality: { noDecimal: true }, // 不保留小数 |
| | | } |
| | | ); |
| | | }; |
| | | |
| | | const handleChangeTotalDiscountAmount= () => { |
| | | formState.value.totalAmount = formState.value.totalDiscountAmount * -1 |
| | | syncTotalAmount() |
| | | } |
| | | |
| | | const handleChangeTotalAmount= () => { |
| | | formState.value.totalDiscountAmount = formState.value.totalAmount * -1 |
| | | const syncTotalAmount = () => { |
| | | const rows = formState.value.purchaseReturnOrderProductsDtos || [] |
| | | const baseAmount = rows.reduce((sum, item) => { |
| | | return sum + toNumber(item.taxInclusiveTotalPrice) |
| | | }, 0) |
| | | const discount = toNumber(formState.value.totalDiscountAmount) |
| | | // 成交金额 = 产品退货总价合计 - 折扣额 |
| | | formState.value.totalAmount = Number((baseAmount - discount).toFixed(2)) |
| | | } |
| | | |
| | | // 获取供应商选项 |
| | |
| | | }); |
| | | } |
| | | |
| | | // 获取项目选项 |
| | | const fetchProjectOptions = () => { |
| | | if (projectOptions.value.length > 0) { |
| | | return |
| | | } |
| | | // todo 项目选项 |
| | | } |
| | | |
| | | // 获取用户选项 |
| | | const fetchUserOptions = () => { |
| | |
| | | // 处理改变供应商数据 |
| | | const handleChangeSupplierId = () => { |
| | | formState.value.purchaseLedgerId = undefined |
| | | formState.value.supplierName = supplierOptions.value.find(item => item.id === formState.value.supplierId)?.supplierName || '' |
| | | fetchPurchaseLedgerOptions() |
| | | } |
| | | |
| | |
| | | const fetchPurchaseLedgerOptions = () => { |
| | | purchaseLedgerOptions.value = [] |
| | | if (formState.value.supplierId) { |
| | | purchaseList({supplierId: formState.value.supplierId}).then((res) => { |
| | | purchaseList({supplierId: formState.value.supplierId,approvalStatus:3}).then((res) => { |
| | | purchaseLedgerOptions.value = res.rows; |
| | | }); |
| | | } |
| | | } |
| | | |
| | | // 处理改变采购台账数据 |
| | | const handleChangePurchaseLedgerId = () => { |
| | | formState.value.purchaseReturnOrderProductsDtos = [] |
| | | const handleChangePurchaseLedgerId = async () => { |
| | | const res = await productList({ salesLedgerId: formState.value.purchaseLedgerId, type: 2 }); |
| | | formState.value.purchaseReturnOrderProductsDtos = res.data.map(item => ({ |
| | | ...item, |
| | | returnQuantity: undefined, |
| | | taxInclusiveTotalPrice: 0, |
| | | salesLedgerProductId: item.id, |
| | | })) |
| | | syncTotalAmount() |
| | | } |
| | | |
| | | // 处理改变是否默认编号 |
| | |
| | | const newProducts = selectedRows.filter(item => !existingIds.has(item.id)).map(item => ({ |
| | | ...item, |
| | | returnQuantity: undefined, |
| | | taxInclusiveTotalPrice: 0, |
| | | salesLedgerProductId: item.id, |
| | | })); |
| | | formState.value.purchaseReturnOrderProductsDtos.push(...newProducts); |
| | | syncTotalAmount() |
| | | } |
| | | |
| | | // 删除单项产品 |
| | | const delProduct = (index) => { |
| | | formState.value.purchaseReturnOrderProductsDtos.splice(index, 1) |
| | | syncTotalAmount() |
| | | } |
| | | |
| | | // 提交表单 |
| | | const handleSubmit = () => { |
| | | // 验证退货数量 |
| | | const hasEmptyReturnQuantity = formState.value.purchaseReturnOrderProductsDtos.some(item => !item.returnQuantity || item.returnQuantity <= 0); |
| | | if (hasEmptyReturnQuantity) { |
| | | proxy.$modal.msgError("请为所有产品填写退货数量"); |
| | | return; |
| | | const productList = formState.value.purchaseReturnOrderProductsDtos || [] |
| | | |
| | | productList.forEach(syncReturnTotal) |
| | | |
| | | if (productList.length === 0) { |
| | | proxy.$modal.msgError("请先选择产品") |
| | | return |
| | | } |
| | | |
| | | // 逐行校验退货数量:任意一行未填/非法/超限都不允许提交 |
| | | const invalidRowIndex = productList.findIndex((item) => { |
| | | const qty = Number(item.returnQuantity) |
| | | const maxQty = Number(item.availableQuality) |
| | | |
| | | if (item.returnQuantity === null || item.returnQuantity === undefined || item.returnQuantity === "") { |
| | | return true |
| | | } |
| | | if (Number.isNaN(qty) || qty <= 0) { |
| | | return true |
| | | } |
| | | if (!Number.isNaN(maxQty) && maxQty > 0 && qty > maxQty) { |
| | | return true |
| | | } |
| | | return false |
| | | }) |
| | | |
| | | if (invalidRowIndex !== -1) { |
| | | proxy.$modal.msgError(`第${invalidRowIndex + 1}行退货数量未填写或不合法`) |
| | | return |
| | | } |
| | | |
| | | proxy.$refs["formRef"].validate(valid => { |
| | |
| | | }) |
| | | }; |
| | | |
| | | watch( |
| | | () => formState.value.purchaseReturnOrderProductsDtos, |
| | | (rows) => { |
| | | (rows || []).forEach(syncReturnTotal) |
| | | syncTotalAmount() |
| | | }, |
| | | { deep: true } |
| | | ) |
| | | |
| | | defineExpose({ |
| | | closeModal, |
| | | handleSubmit, |
| | |
| | | </div> |
| | | |
| | | <div class="table_list"> |
| | | <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange" :row-key="row => row.id" style="width: 100%" height="calc(100vh - 18.5em)"> |
| | | <el-table-column align="center" type="selection" width="55" /> |
| | | <el-table-column align="center" label="序号" type="index" width="60" /> |
| | | <el-table-column label="退料单号" prop="no" show-overflow-tooltip /> |
| | | <el-table-column label="退货方式" prop="returnType" show-overflow-tooltip /> |
| | | <el-table-column label="供应商名称" prop="supplierName" show-overflow-tooltip /> |
| | | <el-table-column label="关联单号" prop="purchaseContractNumber" show-overflow-tooltip /> |
| | | <el-table-column label="退料人" prop="returnUserName" show-overflow-tooltip /> |
| | | <el-table-column label="备注" prop="remark" show-overflow-tooltip /> |
| | | <el-table-column label="创建人" prop="createUserName" show-overflow-tooltip /> |
| | | <el-table-column label="创建时间" prop="createTime" show-overflow-tooltip /> |
| | | <el-table-column label="最近更新时间" prop="updateTime" show-overflow-tooltip /> |
| | | <el-table-column fixed="right" label="操作" min-width="60" align="center"> |
| | | <template #default="scope"> |
| | | <el-button link type="primary" size="small" style="color: #67C23A">详情</el-button> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :tableLoading="tableLoading" |
| | | :isSelection="true" |
| | | :page="page" |
| | | :height="'calc(100vh - 18.5em)'" |
| | | @selection-change="handleSelectionChange" |
| | | @pagination="paginationChange" |
| | | > |
| | | <template #operation="{ row }"> |
| | | <el-button link type="primary" size="small" style="color: #67C23A" @click="handleDetail(row)">详情</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <pagination v-show="total > 0" :total="total" layout="total, sizes, prev, pager, next, jumper" |
| | | :page="page.current" :limit="page.size" @pagination="paginationChange" /> |
| | | </PIMTable> |
| | | </div> |
| | | <new v-if="isShowNewModal" |
| | | v-model:visible="isShowNewModal" |
| | | @completed="handleQuery" /> |
| | | |
| | | <el-dialog |
| | | v-model="detailVisible" |
| | | title="采购退货详情" |
| | | width="1200" |
| | | destroy-on-close |
| | | > |
| | | <div v-loading="detailLoading"> |
| | | <el-descriptions :column="3" border> |
| | | <el-descriptions-item label="退料单号">{{ detailData.no || '--' }}</el-descriptions-item> |
| | | <el-descriptions-item label="退货方式">{{ getReturnTypeLabel(detailData.returnType) }}</el-descriptions-item> |
| | | <el-descriptions-item label="供应商名称">{{ detailData.supplierName || '--' }}</el-descriptions-item> |
| | | <el-descriptions-item label="项目阶段">{{ getProjectPhaseLabel(detailData.projectPhase) }}</el-descriptions-item> |
| | | <el-descriptions-item label="关联单号">{{ detailData.purchaseContractNumber || '--' }}</el-descriptions-item> |
| | | <el-descriptions-item label="制作日期">{{ detailData.preparedAt || '--' }}</el-descriptions-item> |
| | | <el-descriptions-item label="制单人">{{ detailData.preparedUserName || '--' }}</el-descriptions-item> |
| | | <el-descriptions-item label="退料人">{{ detailData.returnUserName || '--' }}</el-descriptions-item> |
| | | <el-descriptions-item label="整单折扣额">{{ formatAmount(detailData.totalDiscountAmount) }}</el-descriptions-item> |
| | | <el-descriptions-item label="整单折扣率">{{ detailData.totalDiscountRate ?? '--' }}</el-descriptions-item> |
| | | <el-descriptions-item label="成交金额">{{ formatAmount(detailData.totalAmount) }}</el-descriptions-item> |
| | | <el-descriptions-item label="创建人">{{ detailData.createUserName || '--' }}</el-descriptions-item> |
| | | <el-descriptions-item label="创建时间">{{ detailData.createTime || '--' }}</el-descriptions-item> |
| | | <el-descriptions-item label="最近更新时间">{{ detailData.updateTime || '--' }}</el-descriptions-item> |
| | | <el-descriptions-item label="备注" :span="3">{{ detailData.remark || '--' }}</el-descriptions-item> |
| | | </el-descriptions> |
| | | |
| | | <el-divider content-position="left">产品列表</el-divider> |
| | | |
| | | <el-table |
| | | :data="detailProducts" |
| | | border |
| | | max-height="420" |
| | | style="width: 100%" |
| | | > |
| | | <el-table-column align="center" label="序号" type="index" width="60" /> |
| | | <el-table-column label="产品大类" prop="productCategory" min-width="120" show-overflow-tooltip /> |
| | | <el-table-column label="规格型号" prop="specificationModel" min-width="140" show-overflow-tooltip /> |
| | | <el-table-column label="单位" prop="unit" width="80" /> |
| | | <el-table-column label="数量" prop="quantity" width="80" /> |
| | | <el-table-column label="退货数量" prop="returnQuantity" width="100" /> |
| | | <el-table-column label="库存预警数量" prop="warnNum" width="120" /> |
| | | <el-table-column label="税率(%)" prop="taxRate" width="90" /> |
| | | <el-table-column label="含税单价(元)" prop="taxInclusiveUnitPrice" width="130"> |
| | | <template #default="scope">{{ formatAmount(scope.row.taxInclusiveUnitPrice) }}</template> |
| | | </el-table-column> |
| | | <el-table-column label="含税总价(元)" prop="taxInclusiveTotalPrice" width="130"> |
| | | <template #default="scope">{{ formatAmount(scope.row.taxInclusiveTotalPrice) }}</template> |
| | | </el-table-column> |
| | | <el-table-column label="不含税总价(元)" prop="taxExclusiveTotalPrice" width="140"> |
| | | <template #default="scope">{{ formatAmount(scope.row.taxExclusiveTotalPrice) }}</template> |
| | | </el-table-column> |
| | | <el-table-column label="是否质检" prop="isChecked" width="100" align="center"> |
| | | <template #default="scope"> |
| | | <el-tag :type="scope.row.isChecked ? 'success' : 'info'"> |
| | | {{ scope.row.isChecked ? '是' : '否' }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | <template #footer> |
| | | <el-button @click="detailVisible = false">关闭</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import pagination from '@/components/PIMTable/Pagination.vue' |
| | | import { ref, reactive, toRefs, onMounted } from 'vue' |
| | | import {findPurchaseReturnOrderListPage} from "@/api/procurementManagement/purchase_return_order.js"; |
| | | import PIMTable from '@/components/PIMTable/PIMTable.vue' |
| | | import { ref, reactive, toRefs, onMounted, defineAsyncComponent, getCurrentInstance } from 'vue' |
| | | const { proxy } = getCurrentInstance() |
| | | import {findPurchaseReturnOrderListPage, getPurchaseReturnOrderDetail} from "@/api/procurementManagement/purchase_return_order.js"; |
| | | const New = defineAsyncComponent(() => import("@/views/procurementManagement/purchaseReturnOrder/New.vue")); |
| | | const tableData = ref([]) |
| | | const selectedRows = ref([]) |
| | |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }) |
| | | const total = ref(0) |
| | | const detailVisible = ref(false) |
| | | const detailLoading = ref(false) |
| | | const detailData = ref({}) |
| | | const detailProducts = ref([]) |
| | | // 是否显示新增弹框 |
| | | const isShowNewModal = ref(false) |
| | | const returnTypeOptions = [ |
| | | { label: '退货退款', value: 0 }, |
| | | { label: '拒收', value: 1 }, |
| | | ] |
| | | const projectPhaseOptions = [ |
| | | { label: '立项', value: 0 }, |
| | | { label: '设计', value: 1 }, |
| | | { label: '采购', value: 2 }, |
| | | { label: '生产', value: 3 }, |
| | | { label: '出货', value: 4 }, |
| | | ] |
| | | const tableColumn = ref([ |
| | | { |
| | | label: '退料单号', |
| | | prop: 'no', |
| | | }, |
| | | { |
| | | label: '退货方式', |
| | | prop: 'returnType', |
| | | formatData: (val) => returnTypeOptions.find(item => item.value === val)?.label || '--', |
| | | }, |
| | | { |
| | | label: '供应商名称', |
| | | prop: 'supplierName', |
| | | width: 180, |
| | | }, |
| | | { |
| | | label: '项目阶段', |
| | | prop: 'projectPhase', |
| | | width: 100, |
| | | formatData: (val) => projectPhaseOptions.find(item => String(item.value) === String(val))?.label || '--', |
| | | }, |
| | | { |
| | | label: '关联单号', |
| | | prop: 'purchaseContractNumber', |
| | | width: 160, |
| | | }, |
| | | { |
| | | label: '制作日期', |
| | | prop: 'preparedAt', |
| | | width: 130, |
| | | }, |
| | | { |
| | | label: '制单人', |
| | | prop: 'preparedUserName', |
| | | width: 110, |
| | | }, |
| | | { |
| | | label: '退料人', |
| | | prop: 'returnUserName', |
| | | width: 110, |
| | | }, |
| | | |
| | | { |
| | | label: '整单折扣额', |
| | | prop: 'totalDiscountAmount', |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: '整单折扣率', |
| | | prop: 'totalDiscountRate', |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: '成交金额', |
| | | prop: 'totalAmount', |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: '创建人', |
| | | prop: 'createUserName', |
| | | width: 110, |
| | | }, |
| | | { |
| | | label: '创建时间', |
| | | prop: 'createTime', |
| | | width: 170, |
| | | }, |
| | | { |
| | | label: '最近更新时间', |
| | | prop: 'updateTime', |
| | | width: 170, |
| | | }, |
| | | { |
| | | label: '备注', |
| | | prop: 'remark', |
| | | width: 180, |
| | | }, |
| | | { |
| | | fixed: 'right', |
| | | label: '操作', |
| | | dataType: 'slot', |
| | | slot: 'operation', |
| | | width: 100, |
| | | align: 'center', |
| | | }, |
| | | ]) |
| | | const data = reactive({ |
| | | searchForm: { |
| | | no: '', |
| | |
| | | getList() |
| | | } |
| | | |
| | | const handleDetail = (row) => { |
| | | if (!row?.id) { |
| | | proxy?.$modal?.msgWarning('未获取到单据ID') |
| | | return |
| | | } |
| | | detailVisible.value = true |
| | | detailLoading.value = true |
| | | getPurchaseReturnOrderDetail(row.id).then(res => { |
| | | const payload = res?.data || {} |
| | | detailData.value = payload |
| | | // 拼接连个对象成一个对象,方便展示 item 和 item.salesLedgerProduct 里的字段 |
| | | |
| | | |
| | | detailProducts.value = |
| | | payload.purchaseReturnOrderProductsDetailVoList.map(item => ({ ...item, ...item.salesLedgerProduct })) || |
| | | [] |
| | | }).catch(() => { |
| | | proxy?.$modal?.msgError('获取详情失败') |
| | | }).finally(() => { |
| | | detailLoading.value = false |
| | | }) |
| | | } |
| | | |
| | | |
| | | const paginationChange = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | |
| | | findPurchaseReturnOrderListPage({ ...searchForm.value, ...page }).then(res => { |
| | | tableLoading.value = false |
| | | tableData.value = res.data.records |
| | | total.value = res.data.total |
| | | page.total = res.data.total |
| | | }).catch(() => { |
| | | tableLoading.value = false |
| | | }) |
| | |
| | | selectedRows.value = selection.filter(item => item.id); |
| | | } |
| | | |
| | | const getReturnTypeLabel = (value) => { |
| | | return returnTypeOptions.find(item => String(item.value) === String(value))?.label || '--' |
| | | } |
| | | |
| | | const getProjectPhaseLabel = (value) => { |
| | | return projectPhaseOptions.find(item => String(item.value) === String(value))?.label || '--' |
| | | } |
| | | |
| | | const formatAmount = (value) => { |
| | | if (value === null || value === undefined || value === '') { |
| | | return '--' |
| | | } |
| | | const num = Number(value) |
| | | if (Number.isNaN(num)) { |
| | | return value |
| | | } |
| | | return num.toFixed(2) |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getList() |
| | | }) |