Commit 66700587 by zhangtw

入库页面优化,导出功能优化

parent 563b3de0
<template> <template>
<div class="app-container"> <div class="app-container">
<!-- 标题栏 + 操作按钮(对齐字典页面) --> <!-- 标题栏 + 操作按钮 -->
<PageTitle> <PageTitle>
<template #buttons> <template #buttons>
<el-button <el-button
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
</template> </template>
</PageTitle> </PageTitle>
<!-- 搜索区域(对齐字典页面的page-wrapper-search组件) --> <!-- 搜索区域 -->
<div class="page-container"> <div class="page-container">
<page-wrapper-search <page-wrapper-search
:model="queryParams" :model="queryParams"
...@@ -61,7 +61,6 @@ ...@@ -61,7 +61,6 @@
@search="handleQuery" @search="handleQuery"
@reset="resetQuery" @reset="resetQuery"
> >
<!-- ========== 新增:入库日期范围选择器 ========== -->
<el-form-item label="入库日期" prop="inboundDateRange"> <el-form-item label="入库日期" prop="inboundDateRange">
<el-date-picker <el-date-picker
v-model="inboundDateRange" v-model="inboundDateRange"
...@@ -109,7 +108,6 @@ ...@@ -109,7 +108,6 @@
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
<!-- 新增:搜索页货主选择 -->
<el-form-item label="货主" prop="ownerId"> <el-form-item label="货主" prop="ownerId">
<el-input <el-input
v-model="queryOwnerName" v-model="queryOwnerName"
...@@ -150,7 +148,7 @@ ...@@ -150,7 +148,7 @@
</el-form-item> </el-form-item>
</page-wrapper-search> </page-wrapper-search>
<!-- 表格区域(对齐字典页面的样式) --> <!-- 表格区域 -->
<div class="table-container"> <div class="table-container">
<el-table <el-table
v-loading="loading" v-loading="loading"
...@@ -162,38 +160,40 @@ ...@@ -162,38 +160,40 @@
<el-table-column label="入库单号" align="center" prop="orderId" min-width="200"/> <el-table-column label="入库单号" align="center" prop="orderId" min-width="200"/>
<el-table-column label="批次号" align="center" prop="batchId" min-width="200"/> <el-table-column label="批次号" align="center" prop="batchId" min-width="200"/>
<el-table-column label="系统编号" align="center" prop="systemNo" min-width="200"/> <el-table-column label="系统编号" align="center" prop="systemNo" min-width="200"/>
<!-- 新增:表格显示货主名称 -->
<el-table-column label="货主" align="center" prop="ownerName" min-width="200"/> <el-table-column label="货主" align="center" prop="ownerName" min-width="200"/>
<el-table-column label="入库类型" align="center" prop="orderTypeId" :show-overflow-tooltip="true" min-width="200"> <el-table-column label="入库类型" align="center" prop="orderTypeId" show-overflow-tooltip min-width="200">
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag <el-tag
:type="getDictListClass('inbound_outbound_type',scope.row.orderTypeId)" :type="getDictTagClass('inbound_outbound_type', scope.row.orderTypeId)"
size="small"> size="small"
{{ getDictLabel('inbound_outbound_type',scope.row.orderTypeId) }} >
{{ getDictLabel('inbound_outbound_type', scope.row.orderTypeId) }}
</el-tag> </el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="订单类型" align="center" prop="orderType" show-overflow-tooltip min-width="200">
<el-table-column label="订单类型" align="center" prop="orderType" :show-overflow-tooltip="true" min-width="200">
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag <el-tag
:type="getDictListClass('order_type',scope.row.orderType)" :type="getDictTagClass('order_type', scope.row.orderType)"
size="small"> size="small"
{{ getDictLabel('order_type',scope.row.orderType) }} >
{{ getDictLabel('order_type', scope.row.orderType) }}
</el-tag> </el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="入库单状态" align="center" prop="orderStatus" min-width="200"> <el-table-column label="入库单状态" align="center" prop="orderStatus" min-width="200">
<!-- 状态显示 -->
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag :type="getDictListClass('inbound_status',scope.row.orderStatus+'')" size="small" min-width="200"> <el-tag
{{ getDictLabel('inbound_status',scope.row.orderStatus+"") }} :type="getDictTagClass('inbound_status', scope.row.orderStatus + '')"
size="small"
>
{{ getDictLabel('inbound_status', scope.row.orderStatus + "") }}
</el-tag> </el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="入库时间" align="center" prop="inboundDate" min-width="200"> <el-table-column label="入库时间" align="center" prop="inboundDate" min-width="200">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ parseTime(scope.row.inboundDate,'{y}-{m}-{d}') }}</span> {{ parseTime(scope.row.inboundDate, '{y}-{m}-{d}') }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
...@@ -210,7 +210,7 @@ ...@@ -210,7 +210,7 @@
icon="el-icon-success" icon="el-icon-success"
@click="handleConfirm(scope.row)" @click="handleConfirm(scope.row)"
v-hasPermi="['inventory:inbound:confirm']" v-hasPermi="['inventory:inbound:confirm']"
v-show="!(scope.row.orderStatus === 2)" v-if="scope.row.orderStatus !== 2"
>确认入库</el-button> >确认入库</el-button>
<el-button <el-button
size="mini" size="mini"
...@@ -225,7 +225,7 @@ ...@@ -225,7 +225,7 @@
icon="el-icon-edit" icon="el-icon-edit"
@click="handleUpdate(scope.row)" @click="handleUpdate(scope.row)"
v-hasPermi="['inventory:inbound:edit']" v-hasPermi="['inventory:inbound:edit']"
v-show="!(scope.row.orderStatus === 2)" v-if="scope.row.orderStatus !== 2"
>修改</el-button> >修改</el-button>
<el-button <el-button
size="mini" size="mini"
...@@ -233,16 +233,16 @@ ...@@ -233,16 +233,16 @@
icon="el-icon-delete" icon="el-icon-delete"
@click="handleDelete(scope.row)" @click="handleDelete(scope.row)"
v-hasPermi="['inventory:inbound:remove']" v-hasPermi="['inventory:inbound:remove']"
v-show="!(scope.row.orderStatus === 2)" v-if="scope.row.orderStatus !== 2"
>删除</el-button> >删除</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
</div> </div>
<!-- 分页组件(位置对齐) --> <!-- 分页组件 -->
<pagination <pagination
v-show="total>0" v-show="total > 0"
:total="total" :total="total"
:page.sync="queryParams.pageNum" :page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize" :limit.sync="queryParams.pageSize"
...@@ -250,10 +250,16 @@ ...@@ -250,10 +250,16 @@
/> />
</div> </div>
<!-- 添加或修改入库对话框(样式对齐) --> <!-- 添加/修改入库对话框 -->
<el-dialog :title="title" :visible.sync="open" width="1200px" append-to-body> <el-dialog
<el-form ref="form" :model="form" :rules="rules" label-width="80px"> :title="title"
<!-- 表单内容保持不变 --> v-model="open"
:visible.sync="open"
width="1200px"
append-to-body
destroy-on-close
>
<el-form ref="formRef" :model="form" :rules="rules" label-width="80px">
<el-divider content-position="center">入库单基础信息</el-divider> <el-divider content-position="center">入库单基础信息</el-divider>
<el-row :gutter="24"> <el-row :gutter="24">
<el-col :span="12"> <el-col :span="12">
...@@ -280,8 +286,7 @@ ...@@ -280,8 +286,7 @@
type="date" type="date"
value-format="yyyy-MM-dd" value-format="yyyy-MM-dd"
placeholder="请选择入库日期" placeholder="请选择入库日期"
> />
</el-date-picker>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
...@@ -319,32 +324,6 @@ ...@@ -319,32 +324,6 @@
</el-col> </el-col>
</el-row> </el-row>
<!-- <el-divider content-position="center">入库其他信息</el-divider> -->
<!-- <el-row :gutter="24">
<el-col :span="12">
<div class="form-col">
<el-form-item label="计划量" prop="totalPlannedQuantity">
<el-input v-model="form.totalPlannedQuantity" placeholder="请输入计划量" />
</el-form-item>
<el-form-item label="总件数" prop="totalPackages">
<el-input v-model="form.totalPackages" placeholder="请输入总件数" />
</el-form-item>
<el-form-item label="仓库" prop="warehouseId">
<el-input v-model="form.warehouseId" placeholder="请输入仓库ID" />
</el-form-item>
</div>
</el-col>
<el-col :span="12">
<el-form-item label="实际量" prop="totalActualQuantity">
<el-input v-model="form.totalActualQuantity" placeholder="请输入实际量" />
</el-form-item>
<el-form-item label="负责人" prop="opUserName">
<el-input v-model="form.opUserName" placeholder="请输入负责人" />
</el-form-item>
</el-col>
</el-row> -->
<el-form-item label="备注" prop="remark"> <el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" /> <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
</el-form-item> </el-form-item>
...@@ -385,43 +364,37 @@ ...@@ -385,43 +364,37 @@
<!-- 入库单详情弹窗 --> <!-- 入库单详情弹窗 -->
<el-dialog <el-dialog
title="入库单详细信息" title="入库单详细信息"
v-model="detailOpen"
:visible.sync="detailOpen" :visible.sync="detailOpen"
width="1200px" width="1200px"
append-to-body append-to-body
class="scrollable-dialog" class="scrollable-dialog"
> >
<div class="detail-container"> <div class="detail-container">
<!-- 基础信息展示 --> <el-descriptions :column="2" class="mb20" border>
<el-descriptions :column="2" border class="mb20">
<el-descriptions-item label="入库单号">{{ detailForm.orderId || '-' }}</el-descriptions-item> <el-descriptions-item label="入库单号">{{ detailForm.orderId || '-' }}</el-descriptions-item>
<el-descriptions-item label="系统编号">{{ detailForm.systemNo || '-' }}</el-descriptions-item> <el-descriptions-item label="系统编号">{{ detailForm.systemNo || '-' }}</el-descriptions-item>
<el-descriptions-item label="批次号">{{ detailForm.batchId || '-' }}</el-descriptions-item> <el-descriptions-item label="批次号">{{ detailForm.batchId || '-' }}</el-descriptions-item>
<el-descriptions-item label="货主">{{ detailForm.ownerName || detailForm.ownerId || '-' }}</el-descriptions-item> <el-descriptions-item label="货主">{{ detailForm.ownerName || detailForm.ownerId || '-' }}</el-descriptions-item>
<el-descriptions-item label="入库类型"> <el-descriptions-item label="入库类型">
{{ getDictLabel('inbound_outbound_type',detailForm.orderTypeId) }} {{ getDictLabel('inbound_outbound_type', detailForm.orderTypeId) }}
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item label="订单类型"> <el-descriptions-item label="订单类型">
{{ getDictLabel('order_type',detailForm.orderType) }} {{ getDictLabel('order_type', detailForm.orderType) }}
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item label="入库日期">{{ detailForm.inboundDate || '-' }}</el-descriptions-item> <el-descriptions-item label="入库日期">{{ detailForm.inboundDate || '-' }}</el-descriptions-item>
<!-- <el-descriptions-item label="负责人">{{ detailForm.opUserName || '-' }}</el-descriptions-item> -->
<!-- <el-descriptions-item label="计划量">{{ detailForm.totalPlannedQuantity || '-' }}</el-descriptions-item>
<el-descriptions-item label="实际量">{{ detailForm.totalActualQuantity || '-' }}</el-descriptions-item> -->
<!-- <el-descriptions-item label="总件数">{{ detailForm.totalPackages || '-' }}</el-descriptions-item> -->
<!-- <el-descriptions-item label="仓库">{{ detailForm.warehouseId || '-' }}</el-descriptions-item> -->
<el-descriptions-item label="备注" :span="2"> <el-descriptions-item label="备注" :span="2">
<div class="remark-text">{{ detailForm.remark || '-' }}</div> <div class="remark-text">{{ detailForm.remark || '-' }}</div>
</el-descriptions-item> </el-descriptions-item>
</el-descriptions> </el-descriptions>
<!-- 明细信息展示 -->
<el-divider content-position="center">入库单明细信息</el-divider> <el-divider content-position="center">入库单明细信息</el-divider>
<InboundItems <InboundItems
ref="detailItemsRef" ref="detailItemsRef"
v-model="detailForm.inboundOrderItemsList" v-model="detailForm.inboundOrderItemsList"
:embedded="true" :embedded="true"
:inboundOrderId="detailForm.inboundOrderId" :inboundOrderId="detailForm.inboundOrderId"
:isEditable="isEditable" :isEditable="false"
:show-search-form="false" :show-search-form="false"
:show-pagination="false" :show-pagination="false"
:show-toolbar="false" :show-toolbar="false"
...@@ -437,8 +410,15 @@ ...@@ -437,8 +410,15 @@
<el-button @click="detailOpen = false">关闭</el-button> <el-button @click="detailOpen = false">关闭</el-button>
</div> </div>
</el-dialog> </el-dialog>
<!-- 物料选择弹窗 --> <!-- 物料选择弹窗 -->
<el-dialog title="选择物料" :visible.sync="materialSelectOpen" width="1200px" append-to-body> <el-dialog
title="选择物料"
v-model="materialSelectOpen"
width="1200px"
append-to-body
destroy-on-close
>
<MaterialSelector <MaterialSelector
v-model="selectedMaterialIds" v-model="selectedMaterialIds"
:multiple="true" :multiple="true"
...@@ -453,7 +433,7 @@ ...@@ -453,7 +433,7 @@
<!-- 导入弹窗 --> <!-- 导入弹窗 -->
<import-excel <import-excel
ref="import" ref="importRef"
title="导入" title="导入"
import-url="/inventory/inbound/import" import-url="/inventory/inbound/import"
template-url="/inventory/inbound/importTemplate" template-url="/inventory/inbound/importTemplate"
...@@ -463,16 +443,16 @@ ...@@ -463,16 +443,16 @@
@orderTypeChange="handleOrderTypeChange" @orderTypeChange="handleOrderTypeChange"
:orderTypeRequired="true" :orderTypeRequired="true"
/> />
<!-- 选择器组件 -->
<OwnerSelector <OwnerSelector
v-model="ownerSelectorVisible" v-model="ownerSelectorVisible"
@selected="handleOwnerSelected" @selected="handleOwnerSelected"
/> />
<!-- 仓库选择组件 -->
<WarehouseSelector <WarehouseSelector
v-model="warehouseSelectorVisible" v-model="warehouseSelectorVisible"
@selected="handleWarehouseSelected" @selected="handleWarehouseSelected"
/> />
<!-- 库位选择组件 -->
<LocationSelector <LocationSelector
v-model="locationSelectorVisible" v-model="locationSelectorVisible"
@selected="handleLocationSelected" @selected="handleLocationSelected"
...@@ -481,13 +461,19 @@ ...@@ -481,13 +461,19 @@
</template> </template>
<script> <script>
import { listInbound, getInbound, delInbound, addInbound, updateInbound } from "@/api/inventory/inbound" import {
listInbound,
getInbound,
delInbound,
addInbound,
updateInbound
} from "@/api/inventory/inbound"
import { listInbound_itemsAndMname } from "@/api/inventory/inbound_items" import { listInbound_itemsAndMname } from "@/api/inventory/inbound_items"
import { batchAddInventory } from "@/api/inventory/inventory" import { batchAddInventory } from "@/api/inventory/inventory"
import InboundItems from "@/views/inventory/inbound_items/index.vue" import InboundItems from "@/views/inventory/inbound_items/index.vue"
import PageTitle from "@/components/PageTitle" // 引入字典页面的标题组件 import PageTitle from "@/components/PageTitle"
import PageWrapperSearch from "@/components/Search/PageWrapperSearch" // 引入搜索包装组件 import PageWrapperSearch from "@/components/Search/PageWrapperSearch"
import MaterialSelector from "@/views/inventory/materials/materialsSeletor.vue"; import MaterialSelector from "@/views/inventory/materials/materialsSeletor.vue"
import ImportExcel from "@/components/ImportExcel/index" import ImportExcel from "@/components/ImportExcel/index"
import OwnerSelector from "@/views/compononents/OwnerSelector.vue" import OwnerSelector from "@/views/compononents/OwnerSelector.vue"
import WarehouseSelector from "@/views/compononents/WarehouseSelector.vue" import WarehouseSelector from "@/views/compononents/WarehouseSelector.vue"
...@@ -495,7 +481,7 @@ import LocationSelector from "@/views/compononents/LocationSelector.vue" ...@@ -495,7 +481,7 @@ import LocationSelector from "@/views/compononents/LocationSelector.vue"
export default { export default {
name: "Inbound", name: "Inbound",
dicts: ['inbound_outbound_type','order_type','inbound_status'], dicts: ['inbound_outbound_type', 'order_type', 'inbound_status'],
components: { components: {
InboundItems, InboundItems,
PageTitle, PageTitle,
...@@ -508,447 +494,464 @@ export default { ...@@ -508,447 +494,464 @@ export default {
}, },
data() { data() {
return { return {
// 日期组件返回数组 // 日期范围
inboundDateRange: null, inboundDateRange: null,
// 货主选择相关(对齐退库组件) // 货主选择
queryOwnerName: null, queryOwnerName: '',
ownerSelectorVisible: false, ownerSelectorVisible: false,
ownerSelectTarget: 'form', // 标记当前货主选择的目标:query-搜索页,form-表单页 ownerSelectTarget: 'form',
// 仓库和库位选择相关 // 仓库/库位选择
warehouseSelectorVisible: false, warehouseSelectorVisible: false,
locationSelectorVisible: false, locationSelectorVisible: false,
currentEditRow: null, currentEditRow: null,
currentEditRowWarehousesId: null, // 物料选择
// 可编辑状态
isEditable: true,
// 物料组件显示
materialSelectOpen: false, materialSelectOpen: false,
selectedMaterialIds: [], selectedMaterialIds: [],
inboundItemsUpdateStatus: false,
// 组件带来的选中的物料详情(code、name)
selectedMaterials: [], selectedMaterials: [],
// 详情弹窗
detailOpen: false, detailOpen: false,
detailForm: {}, // 新增详情表单数据 detailForm: {},
// 组件监听修改时的orderId变化 // 基础状态
inboundOrderId: null,
// 选中的明细项
selectedItems: [],
// 遮罩层
loading: true, loading: true,
// 选中数组
ids: [], ids: [],
// 非单个禁用
single: true, single: true,
// 非多个禁用
multiple: true, multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0, total: 0,
// 入库表格数据
inboundList: [], inboundList: [],
// 弹出层标题 // 编辑弹窗
title: "", title: "",
// 是否显示弹出层
open: false, open: false,
// 查询参数 inboundOrderId: null,
// 查询参数(规范化初始值)
queryParams: { queryParams: {
pageNum: 1, pageNum: 1,
pageSize: 10, pageSize: 10,
orderId: null, orderId: '',
orderTypeId: null, orderTypeId: '',
systemNo: null, systemNo: '',
batchId: null, batchId: '',
warehouseId: null, warehouseId: '',
ownerId: null, // 货主ID(搜索用) ownerId: '',
ownerName: null, // 货主名称(搜索用) ownerName: '',
ownerCode: null, // 货主编码(搜索用) ownerCode: '',
orderStatus: null, orderStatus: '',
orderType: null, orderType: '',
inboundDateStart: null,// 开始日期(搜索用) inboundDateStart: '',
inboundDateEnd: null // 结束日期(搜索用) inboundDateEnd: ''
}, },
// 表单参数(对齐退库组件的货主字段 // 表单参数(规范化初始值 + 合理默认
form: { form: {
id: null, id: '',
orderId: null, orderId: '',
orderTypeId: null, orderTypeId: '',
batchId: null, batchId: '',
warehouseId: null, warehouseId: '',
warehousesName: null, warehousesName: '',
ownerId: null, // 货主ID ownerId: '',
ownerName: null, // 货主名称 ownerName: '',
ownerCode: null, // 货主编码 ownerCode: '',
orderStatus: 1, orderStatus: 1,
referenceNo: null, referenceNo: '',
plannedArrivalDate: undefined, plannedArrivalDate: '',
actualArrivalDate: undefined, actualArrivalDate: '',
inboundDate: this.formatDate(new Date()), // 入库日期 inboundDate: this.formatDate(new Date()),
totalPlannedQuantity: null, totalPlannedQuantity: 0,
totalActualQuantity: null, totalActualQuantity: 0,
totalPackages: null, totalPackages: 0,
remark: null, remark: '',
opUserName: null, opUserName: '',
isUsed: null, isUsed: '',
sortNo: null, sortNo: '',
createTime: null, createTime: '',
createUserCode: null, createUserCode: '',
updateTime: null, updateTime: '',
updateUserCode: null, updateUserCode: '',
// 明细列表
inboundOrderItemsList: [] inboundOrderItemsList: []
}, },
// 表单校验 // 表单校验规则
rules: { rules: {
orderId: [ orderId: [{ required: true, message: "入库单号不能为空", trigger: "blur" }],
{ required: true, message: "入库单号不能为空", trigger: "blur" } orderTypeId: [{ required: true, message: "入库类型不能为空", trigger: "blur" }],
], systemNo: [{ required: true, message: "系统编号不能为空", trigger: "blur" }],
orderTypeId: [ batchId: [{ required: true, message: "批次号不能为空", trigger: "blur" }],
{ required: true, message: "入库类型不能为空", trigger: "blur" } ownerId: [{ required: true, message: "货主不能为空", trigger: "change" }]
],
systemNo: [
{ required: true, message: "系统编号不能为空", trigger: "blur" }
],
batchId: [
{ required: true, message: "批次号不能为空", trigger: "blur" }
],
ownerId: [ // 新增货主必填校验
{ required: true, message: "货主不能为空", trigger: "change" }
]
} }
} }
}, },
mounted() {
},
created() { created() {
this.getList() this.getList()
}, },
methods: { methods: {
// 日期格式化方法(兼容不同浏览器的日期格式) /**
* 日期格式化(补零处理)
* @param {Date} date 日期对象
* @returns {string} 格式化后的日期字符串
*/
formatDate(date) { formatDate(date) {
const year = date.getFullYear(); const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从0开始,补0 const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0'); // 日期补0 const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`; return `${year}-${month}-${day}`;
}, },
/** 查询入库列表 */ /**
getList() { * 查询入库列表(异步优化 + 错误捕获)
this.loading = true */
listInbound(this.queryParams).then(response => { async getList() {
this.inboundList = response.rows try {
this.total = response.total this.loading = true;
this.loading = false const res = await listInbound(this.queryParams);
}).catch(() => { this.inboundList = res.rows || [];
this.loading = false this.total = res.total || 0;
}) } catch (error) {
}, this.$message.error('查询入库列表失败:' + (error.message || '网络异常'));
handleOrderTypeChange(selection) { console.error('入库列表查询失败:', error);
this.form.orderTypeId = selection } finally {
}, this.loading = false;
/** 获取状态样式类型 */ }
getStatusType(status) {
const item = this.inBoundStatusOptions.find(item => item.orderStatus === status)
return item ? item.type : 'info'
},
/** 获取状态类型名称 */
getStatusName(status) {
const item = this.inBoundStatusOptions.find(item => item.orderStatus === status)
return item ? item.orderStatusName : status
}, },
/**
* 获取字典标签(通用方法)
* @param {string} dictType 字典类型
* @param {*} value 字典值
* @returns {string} 字典标签
*/
getDictLabel(dictType, value) { getDictLabel(dictType, value) {
// 1. 空值/字典不存在时返回默认值
if (!value || !this.dict?.type?.[dictType]) return '-'; if (!value || !this.dict?.type?.[dictType]) return '-';
// 2. 从字典数组中匹配 value 对应的 label
const dictItem = this.dict.type[dictType].find(item => item.value === value); const dictItem = this.dict.type[dictType].find(item => item.value === value);
return dictItem?.label || '-'; return dictItem?.label || '-';
}, },
getDictListClass(dictType, value){
// 1. 空值/字典不存在时返回默认值 /**
if (!value || !this.dict?.type?.[dictType]) return '-'; * 获取字典标签样式类(语义化命名)
// 2. 从字典数组中匹配 value 对应的 label * @param {string} dictType 字典类型
* @param {*} value 字典值
* @returns {string} 样式类名
*/
getDictTagClass(dictType, value) {
if (!value || !this.dict?.type?.[dictType]) return '';
const dictItem = this.dict.type[dictType].find(item => item.value === value); const dictItem = this.dict.type[dictType].find(item => item.value === value);
return dictItem?.raw?.listClass || ''; return dictItem?.raw?.listClass || '';
}, },
getOrderTypeName(type) {
if (!type) return '未知类型' /**
const item = this.orderTypeOptions.find(item => item.orderType === type) * 搜索按钮操作(日期范围处理优化)
return item ? item.orderTypeName : '未知类型' */
},
/** 搜索按钮操作 */
handleQuery() { handleQuery() {
this.queryParams.pageNum = 1 this.queryParams.pageNum = 1;
// 处理日期范围
if (Array.isArray(this.inboundDateRange) && this.inboundDateRange.length === 2) { if (Array.isArray(this.inboundDateRange) && this.inboundDateRange.length === 2) {
this.queryParams.inboundDateStart = this.inboundDateRange[0]; this.queryParams.inboundDateStart = this.inboundDateRange[0];
this.queryParams.inboundDateEnd = this.inboundDateRange[1]; this.queryParams.inboundDateEnd = this.inboundDateRange[1];
} else { } else {
// 清空开始/结束日期(避免残留旧值) this.queryParams.inboundDateStart = '';
this.queryParams.inboundDateStart = ""; this.queryParams.inboundDateEnd = '';
this.queryParams.inboundDateEnd = "";
} }
this.getList() this.getList();
}, },
/** 重置按钮操作 */ /**
* 重置查询条件(精简逻辑 + 响应式优化)
*/
resetQuery() { resetQuery() {
// this.$refs.queryForm?.resetFields() this.queryOwnerName = '';
this.queryOwnerName = null this.inboundDateRange = null;
this.queryParams = { this.queryParams = {
pageNum: 1, pageNum: 1,
pageSize: 10, pageSize: 10,
orderId: null, orderId: '',
orderTypeId: null, orderTypeId: '',
systemNo: null, systemNo: '',
batchId: null, batchId: '',
warehouseId: null, warehouseId: '',
ownerId: null, ownerId: '',
ownerName: null, ownerName: '',
ownerCode: null, ownerCode: '',
orderStatus: null, orderStatus: '',
orderType: null, orderType: '',
inboundDateStart: null, inboundDateStart: '',
inboundDateEnd: null inboundDateEnd: ''
} };
this.inboundDateRange = null; this.$nextTick(() => this.getList());
this.$nextTick(() => {
// 重新触发查询,加载默认数据
this.handleQuery()
})
}, },
/** 多选框选中数据 */ /**
* 多选框选中事件
* @param {Array} selection 选中行
*/
handleSelectionChange(selection) { handleSelectionChange(selection) {
this.ids = selection.map(item => item.id) this.ids = selection.map(item => item.id);
this.single = selection.length !== 1 this.single = selection.length !== 1;
this.multiple = !selection.length this.multiple = !selection.length;
}, },
/** 新增按钮操作 */ /**
* 新增入库单
*/
handleAdd() { handleAdd() {
this.reset() this.resetForm();
this.open = true this.open = true;
this.title = "添加入库" this.title = "添加入库";
}, },
/** 修改按钮操作 */ /**
handleUpdate(row) { * 修改入库单
this.reset(); * @param {Object} row 选中行数据
*/
async handleUpdate(row) {
try {
this.resetForm();
const id = row?.id || this.ids[0];
if (!id) return this.$message.warning('请选择要修改的入库单');
let id = row.id; const res = await getInbound(id);
if(id === undefined){ const data = res.data || {};
id = this.ids[0]
} // 禁用已提交的入库单修改
getInbound(id).then(response => { if (data.orderStatus === 2) {
if(response.data.orderStatus === 2){ return this.$modal.msgWarning("该入库单已提交,不能修改");
this.$modal.msgWarning("该入库单已提交,不能修改");
return;
} }
this.form = response.data || {};
// 货主回显 // 表单赋值 + 回显优化
this.form.ownerName = response.data.ownerName || response.data.ownerCode || response.data.ownerId; this.form = {
// // 仓库回显 ...data,
// this.form.warehousesName = response.data.warehousesName || response.data.warehouseId || '-'; ownerName: data.ownerName || data.ownerCode || data.ownerId,
inboundOrderItemsList: (data.inboundOrderItemsList || []).map(item => ({
// 明细行回显(核心:同步仓库/库位名称)
if (this.form.inboundOrderItemsList && this.form.inboundOrderItemsList.length) {
this.form.inboundOrderItemsList = this.form.inboundOrderItemsList.map(item => ({
...item, ...item,
// 仓库名称兜底
warehousesName: item.warehousesName || item.warehouseId || '-', warehousesName: item.warehousesName || item.warehouseId || '-',
// 库位名称/编码兜底
locationName: item.locationName || item.locationCode || item.locationId || '-', locationName: item.locationName || item.locationCode || item.locationId || '-',
locationCode: item.locationCode || item.locationId || '-', locationCode: item.locationCode || item.locationId || '-',
orderTypeId: item.orderTypeId || 1 orderTypeId: item.orderTypeId || 1
})); }))
} };
console.log(this.form.inboundOrderItemsList)
this.inboundOrderId = id; this.inboundOrderId = id;
// 强制触发子组件的 value 监听(关键)
this.$nextTick(() => { this.$nextTick(() => {
this.$refs.inboundItemsRef?.handlePagination(); this.$refs.inboundItemsRef?.handlePagination();
this.$refs.inboundItemsRef?.calculateTotals(); this.$refs.inboundItemsRef?.calculateTotals();
}); });
this.open = true; this.open = true;
this.title = "修改入库单"; this.title = "修改入库单";
}); } catch (error) {
this.$message.error('获取入库单详情失败:' + (error.message || '网络异常'));
console.error('修改入库单失败:', error);
}
}, },
/** 查看详情 */
handleDetail(row) { /**
this.reset() * 查看入库单详情
const id = row.id * @param {Object} row 选中行数据
this.isEditable = false */
getInbound(id).then(response => { async handleDetail(row) {
// 加载明细数据到详情 try {
this.detailForm = response.data; const id = row?.id;
if (!id) return this.$message.warning('请选择要查看的入库单');
if(this.detailForm.inboundOrderItemsList && this.detailForm.inboundOrderItemsList.length){
this.detailForm.inboundOrderItemsList = this.detailForm.inboundOrderItemsList.map(item => ({ const res = await getInbound(id);
this.detailForm = {
...res.data,
ownerName: res.data.ownerName || res.data.ownerCode || res.data.ownerId,
inboundOrderItemsList: (res.data.inboundOrderItemsList || []).map(item => ({
...item, ...item,
orderTypeId: this.detailForm.orderTypeId orderTypeId: res.data.orderTypeId
})); })),
inboundOrderId: id
};
this.detailOpen = true;
} catch (error) {
this.$message.error('获取入库单详情失败:' + (error.message || '网络异常'));
console.error('查看入库单详情失败:', error);
} }
// 适配货主回显
this.detailForm.ownerName = response.data.ownerName || response.data.ownerCode || response.data.ownerId
this.detailForm.inboundOrderId = id
this.detailOpen = true
})
}, },
// 打开货主选择器(区分搜索/表单场景)
/**
* 打开货主选择器
* @param {string} target 目标场景:query/form
*/
openOwnerSelector(target = 'form') { openOwnerSelector(target = 'form') {
this.ownerSelectTarget = target this.ownerSelectTarget = target;
this.ownerSelectorVisible = true this.ownerSelectorVisible = true;
}, },
// 货主选择回调(对齐退库组件逻辑)
/**
* 货主选择回调
* @param {Object} owner 选中的货主
*/
handleOwnerSelected(owner) { handleOwnerSelected(owner) {
if (!owner) return if (!owner) return;
// 搜索页选择货主
if (this.ownerSelectTarget === 'query') { if (this.ownerSelectTarget === 'query') {
this.queryParams.ownerId = owner.ownerId // 搜索页货主选择
this.queryParams.ownerCode = owner.ownerCode this.queryParams.ownerId = owner.ownerId;
this.queryOwnerName = owner.ownerName || owner.ownerCode this.queryParams.ownerCode = owner.ownerCode;
this.handleQuery() // 选择后立即搜索 this.queryOwnerName = owner.ownerName || owner.ownerCode;
this.getList();
} else { } else {
// 表单页选择货主 // 表单页货主选择
this.form.ownerId = owner.ownerId this.form.ownerId = owner.ownerId;
this.form.ownerCode = owner.ownerCode this.form.ownerCode = owner.ownerCode;
this.form.ownerName = owner.ownerName this.form.ownerName = owner.ownerName;
} }
this.ownerSelectorVisible = false this.ownerSelectorVisible = false;
}, },
// 清空搜索页货主
/**
* 清空搜索页货主
*/
clearQueryOwner() { clearQueryOwner() {
this.queryOwnerName = null this.queryOwnerName = '';
this.queryParams.ownerId = null this.queryParams.ownerId = '';
this.queryParams.ownerCode = null this.queryParams.ownerCode = '';
this.queryParams.ownerName = null this.getList();
this.handleQuery() // 清空后重新搜索
}, },
// 清空表单页货主
/**
* 清空表单页货主
*/
clearFormOwner() { clearFormOwner() {
this.form.ownerId = null this.form.ownerId = '';
this.form.ownerCode = null this.form.ownerCode = '';
this.form.ownerName = null this.form.ownerName = '';
// 清除货主字段校验 this.$refs.formRef?.clearValidate('ownerId');
this.$refs.form?.clearValidate('ownerId')
}, },
// 打开仓库选择器
/**
* 打开仓库选择器
* @param {Object} row 编辑行
*/
openWarehouseSelector(row) { openWarehouseSelector(row) {
this.currentEditRow = row this.currentEditRow = row;
this.warehouseSelectorVisible = true this.warehouseSelectorVisible = true;
}, },
// 仓库选择回调
/**
* 仓库选择回调
* @param {Object} warehouse 选中的仓库
*/
handleWarehouseSelected(warehouse) { handleWarehouseSelected(warehouse) {
if (this.currentEditRow) { if (!warehouse || !this.currentEditRow) return;
// 1. 用 $set 赋值,确保响应式
this.$set(this.currentEditRow, 'warehouseId', warehouse.warehouseId); this.$set(this.currentEditRow, 'warehouseId', warehouse.warehouseId);
this.$set(this.currentEditRow, 'warehousesName', warehouse.warehousesName); this.$set(this.currentEditRow, 'warehousesName', warehouse.warehousesName);
// 2. 通知子组件刷新(关键:触发 displayData 的响应式更新)
this.$refs.inboundItemsRef?.syncDataToParent(); this.$refs.inboundItemsRef?.syncDataToParent();
this.$refs.inboundItemsRef?.calculateTotals(); this.$refs.inboundItemsRef?.calculateTotals();
} else {
this.form.warehouseId = warehouse.warehouseId;
this.form.warehousesName = warehouse.warehousesName;
}
this.warehouseSelectorVisible = false; this.warehouseSelectorVisible = false;
}, },
// 打开库位选择器
/**
* 打开库位选择器
* @param {Object} row 编辑行
*/
openLocationSelector(row) { openLocationSelector(row) {
this.currentEditRow = row this.currentEditRow = row;
// this.currentEditRowWarehousesId = row.warehouseId // 传递仓库ID给库位选择器 this.locationSelectorVisible = true;
this.locationSelectorVisible = true
}, },
// 库位选择回调
/**
* 库位选择回调
* @param {Object} location 选中的库位
*/
handleLocationSelected(location) { handleLocationSelected(location) {
if (this.currentEditRow) { if (!location || !this.currentEditRow) return;
// 1. 用 $set 赋值,确保响应式
this.$set(this.currentEditRow, 'locationId', location.locationId); this.$set(this.currentEditRow, 'locationId', location.locationId);
this.$set(this.currentEditRow, 'locationCode', location.locationCode); this.$set(this.currentEditRow, 'locationCode', location.locationCode);
this.$set(this.currentEditRow, 'locationName', location.locationName); this.$set(this.currentEditRow, 'locationName', location.locationName);
// 2. 通知子组件刷新
this.$refs.inboundItemsRef?.syncDataToParent(); this.$refs.inboundItemsRef?.syncDataToParent();
this.$refs.inboundItemsRef?.calculateTotals(); this.$refs.inboundItemsRef?.calculateTotals();
}
this.locationSelectorVisible = false; this.locationSelectorVisible = false;
}, },
// 打开物料选择弹窗
/**
* 打开物料选择弹窗
* @param {boolean} status 是否显示
*/
showMaterials(status) { showMaterials(status) {
this.materialSelectOpen = status this.materialSelectOpen = status;
if (status) { // 只有打开弹窗时才清空选择 if (status) {
this.selectedMaterialIds = [] // 先清空父组件数据 this.selectedMaterialIds = [];
this.selectedMaterials = [] this.selectedMaterials = [];
this.$nextTick(() => { this.$nextTick(() => this.$refs.materialSelector?.clearSelection());
// 确保弹窗渲染完成后再调用子组件方法
this.$refs.materialSelector?.clearSelection()
})
} }
}, },
// 物料选择变化回调 /**
* 物料选择变化回调
* @param {Array} selectedRows 选中的物料行
*/
handleMaterialChange(selectedRows) { handleMaterialChange(selectedRows) {
this.selectedMaterials = selectedRows this.selectedMaterials = selectedRows || [];
}, },
// 确认选择物料并添加到明细 /**
* 确认选择物料并添加到明细
*/
confirmMaterialSelect() { confirmMaterialSelect() {
if (this.selectedMaterials.length === 0) { if (this.selectedMaterials.length === 0) {
this.$message.warning("请选择物料") return this.$message.warning("请选择物料");
return }
// 过滤重复物料
const newMaterials = this.selectedMaterials.filter(material =>
!this.form.inboundOrderItemsList.some(item => item.materialId === material.id)
);
if (newMaterials.length === 0) {
return this.$message.warning("所选物料已全部添加,无需重复添加");
} }
// 将选中的物料添加到入库明细 // 添加新物料到明细
this.selectedMaterials.forEach(material => { newMaterials.forEach(material => {
// 检查是否已存在该物料,避免重复添加
// const exists = this.form.inboundOrderItemsList.some(
// item => item.materialId === material.materialId
// )
const exists = false
if (!exists) {
this.form.inboundOrderItemsList.push({ this.form.inboundOrderItemsList.push({
materialId: material.id, materialId: material.id,
sapNo: material.sapNo, sapNo: material.sapNo,
materialName: material.materialName, // 仅用于展示 materialName: material.materialName,
batchCode: null, batchCode: '',
warehouseId: null, warehouseId: '',
warehousesName: null, warehousesName: '',
locationId: null, locationId: '',
locationName: null, locationName: '',
plannedQuantity: 0, plannedQuantity: 0,
actualQuantity: 0, actualQuantity: 0,
unitPrice: 0, unitPrice: 0,
totalAmount: 0, totalAmount: 0,
actualPackages: 0, actualPackages: 0,
divisor: 0 divisor: 0
}) });
} else { });
// this.$message.warning(`物料 ${material.materialName} 已存在,跳过添加`)
} this.$refs.inboundItemsRef?.handleAddItem(newMaterials);
}) this.materialSelectOpen = false;
this.materialSelectOpen = false this.$message.success(`成功添加 ${newMaterials.length} 个物料`);
this.$refs.inboundItemsRef.handleAddItem(this.selectedMaterials)
this.$message.success(`成功添加 ${this.selectedMaterials.length} 个物料`)
}, },
/** 确认入库操作 */
async handleConfirm(row) { // 标记为 async 函数 /**
* 确认入库操作
* @param {Object} row 选中行数据
*/
async handleConfirm(row) {
try { try {
// 第一步:确认弹窗
await this.$confirm('确认要入库吗?', '提示', { await this.$confirm('确认要入库吗?', '提示', {
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '取消', cancelButtonText: '取消',
type: 'warning' type: 'warning'
}) });
// 第二步:等待 listInbound_items 执行完成 // 查询入库明细
const queryForm = { const queryForm = { pageNum: 1, pageSize: 9999, inboundOrderId: row.id };
pageNum: 1, const res = await listInbound_itemsAndMname(queryForm);
pageSize: 9999, const items = res.rows || [];
inboundOrderId: row.id
if (items.length === 0) {
return this.$message.warning('暂无入库明细数据,无法确认入库');
} }
const response = await listInbound_itemsAndMname(queryForm)
row.inboundOrderItemsList = response.rows.map(item => { // 组装库存数据
return { const inventoryItems = items.map(item => ({
...item, ...item,
inventoryType: row.orderTypeId, inventoryType: row.orderTypeId,
warehousesId: item.warehouseId, warehousesId: item.warehouseId,
...@@ -958,233 +961,250 @@ export default { ...@@ -958,233 +961,250 @@ export default {
unitWeight: item.unitWeight, unitWeight: item.unitWeight,
isUsed: 1, isUsed: 1,
unitPrice: item.unitPrice unitPrice: item.unitPrice
}; }));
})
// 第三步:确保数据存在后调用入库接口
if (!row.inboundOrderItemsList || row.inboundOrderItemsList.length === 0) {
this.$message.warning('暂无入库明细数据,无法确认入库')
return
}
await batchAddInventory(row.inboundOrderItemsList) // 批量添加库存
await batchAddInventory(inventoryItems);
// 第四步:操作成功提示 // 更新入库单状态
// this.$modal.msgSuccess("确认成功") row.orderStatus = 2;
this.$message.success('确认入库成功') await updateInbound(row);
row.orderStatus = 2
updateInbound(row).then(() => { this.$message.success('确认入库成功');
this.getList() this.getList();
})
} catch (error) { } catch (error) {
// 捕获取消确认/接口失败的异常
if (error !== 'cancel') { if (error !== 'cancel') {
this.$message.error('确认入库失败:' + (error.msg || '网络异常')) this.$message.error('确认入库失败:' + (error.msg || error.message || '网络异常'));
console.log(error) console.error('确认入库失败:', error);
} }
} }
}, },
/** 删除按钮操作 */ /**
handleDelete(row) { * 删除入库单
const ids = row.id || this.ids * @param {Object} row 选中行数据
this.$confirm((row.orderId ? '是否确认删除入库单编号为"' + row.orderId + '"的数据项?' : '是否确认删除选中的' + ids.length + '条入库单'), '提示', { */
type: 'warning' async handleDelete(row) {
}).then(() => { try {
return delInbound(ids) const ids = row?.id || this.ids;
}).then(() => { if (!ids || ids.length === 0) {
this.getList() return this.$message.warning('请选择要删除的入库单');
this.$message.success("删除成功") }
}).catch(() => {})
const confirmText = row?.orderId
? `是否确认删除入库单编号为"${row.orderId}"的数据项?`
: `是否确认删除选中的${ids.length}条入库单`;
await this.$confirm(confirmText, '提示', { type: 'warning' });
await delInbound(ids);
this.$message.success("删除成功");
this.getList();
} catch (error) {
if (error !== 'cancel') {
this.$message.error('删除失败:' + (error.message || '网络异常'));
console.error('删除入库单失败:', error);
}
}
}, },
/** 提交按钮 */ /**
submitForm() { * 提交表单(新增/修改)
this.$refs["form"].validate(valid => { */
if (!valid) return async submitForm() {
try {
// 表单校验
const valid = await this.$refs.formRef.validate();
if (!valid) return;
// 验证明细表 // 明细校验
const errors = this.$refs.inboundItemsRef ? this.$refs.inboundItemsRef.validate() : [] const errors = this.$refs.inboundItemsRef?.validate() || [];
if (errors.length > 0) { if (errors.length > 0) {
this.$message.error(errors.join(';')) return this.$message.error(errors.join(';'));
return
} }
// 确保明细项数量大于0 // 验证明细数量
if (!this.form.inboundOrderItemsList || this.form.inboundOrderItemsList.length === 0) { if (this.form.inboundOrderItemsList.length === 0) {
this.$message.warning('请至少添加一条入库明细') return this.$message.warning('请至少添加一条入库明细');
return
} }
// 自动计算总数 // 计算总数
this.calculateTotals() this.calculateTotals();
// 提交数据 // 组装提交数据
const submitData = { const submitData = {
...this.form, ...this.form,
inboundOrderItemsList: this.form.inboundOrderItemsList.map(item => ({ inboundOrderItemsList: this.form.inboundOrderItemsList.map(item => ({
...item, ...item,
orderId: this.form.orderId, // 确保明细项有主表ID orderId: this.form.orderId,
batchId: this.form.batchId, batchId: this.form.batchId,
inboundOrderId: this.form.id || null, inboundOrderId: this.form.id || ''
})) }))
} };
if (this.form.id != null) {
updateInbound(submitData).then(response => { // 提交数据
this.$message.success("修改成功") if (this.form.id) {
this.open = false await updateInbound(submitData);
this.getList() this.$message.success("修改成功");
})
} else { } else {
addInbound(submitData).then(response => { await addInbound(submitData);
this.$message.success("新增成功") this.$message.success("新增成功");
this.open = false }
this.getList()
}) this.open = false;
this.getList();
} catch (error) {
this.$message.error('提交失败:' + (error.message || '网络异常'));
console.error('表单提交失败:', error);
} }
})
}, },
/** 取消按钮 */ /**
* 取消弹窗
*/
cancel() { cancel() {
this.open = false this.open = false;
this.inboundOrderId = null this.inboundOrderId = '';
this.reset() this.resetForm();
}, },
/** 表单重置 */ /**
reset() { * 重置表单
*/
resetForm() {
this.form = { this.form = {
id: null, id: '',
orderId: null, orderId: '',
orderTypeId: null, orderTypeId: '',
batchId: null, batchId: '',
warehouseId: null, warehouseId: '',
warehousesName: null, warehousesName: '',
ownerId: null, ownerId: '',
ownerName: null, ownerName: '',
ownerCode: null, ownerCode: '',
orderStatus: 1, orderStatus: 1,
referenceNo: null, referenceNo: '',
plannedArrivalDate: null, plannedArrivalDate: '',
actualArrivalDate: null, actualArrivalDate: '',
inboundDate: this.formatDate(new Date()), inboundDate: this.formatDate(new Date()),
totalPlannedQuantity: 0, totalPlannedQuantity: 0,
totalActualQuantity: 0, totalActualQuantity: 0,
totalPackages: 0, totalPackages: 0,
remark: null, remark: '',
opUserName: null, opUserName: '',
isUsed: null, isUsed: '',
sortNo: null, sortNo: '',
createTime: null, createTime: '',
createUserCode: null, createUserCode: '',
updateTime: null, updateTime: '',
updateUserCode: null, updateUserCode: '',
inboundOrderItemsList: [] inboundOrderItemsList: []
} };
if (this.$refs.inboundItemsRef) { this.$refs.inboundItemsRef?.resetEmbeddedData();
this.$refs.inboundItemsRef.resetEmbeddedData() this.$refs.formRef?.resetFields();
}
if (this.$refs.form) {
this.$refs.form.resetFields()
}
}, },
/** 导入按钮操作 */
/**
* 导入按钮操作
*/
handleImport() { handleImport() {
this.$refs.import.show() this.$refs.importRef?.show();
}, },
getTemplateName(){
if(this.form.orderTypeId === '1'){ /**
return "入库单导入模板" * 获取导入模板名称
}else if(this.form.orderTypeId === '2'){ * @returns {string} 模板名称
return "成品入库单导入模板" */
}else if(this.form.orderTypeId === '3'){ getTemplateName() {
return "退料TRDC入库单导入模板" const typeMap = {
} '1': "入库单导入模板",
'2': "成品入库单导入模板",
'3': "退料TRDC入库单导入模板"
};
return typeMap[this.form.orderTypeId] || "入库单导入模板";
}, },
/** 处理明细项选择变化 */
/**
* 处理订单类型变化
* @param {*} selection 选中值
*/
handleOrderTypeChange(selection) {
this.form.orderTypeId = selection;
},
// ========== 明细项相关方法 ==========
handleItemsSelectionChange(selection) { handleItemsSelectionChange(selection) {
this.selectedItems = selection this.selectedItems = selection;
}, },
/** 处理明细数据变化 */
handleItemsDataChange(items) { handleItemsDataChange(items) {
this.form.inboundOrderItemsList = items this.form.inboundOrderItemsList = items;
this.calculateTotals() this.calculateTotals();
}, },
/** 处理总数变化 */
handleTotalsChange(totals) { handleTotalsChange(totals) {
this.form.totalPlannedQuantity = totals.plannedQuantity this.form.totalPlannedQuantity = totals.plannedQuantity;
this.form.totalActualQuantity = totals.actualQuantity this.form.totalActualQuantity = totals.actualQuantity;
this.form.totalPackages = totals.packages this.form.totalPackages = totals.packages;
}, },
/** 添加明细项回调 */
handleItemAdded(item) { handleItemAdded(item) {
// 为新项设置orderId item.orderId = this.form.orderId;
item.orderId = this.form.orderId
}, },
/** 行保存回调 */ handleRowSaved() {},
handleRowSaved(row) {
// 可以在这里添加保存后的逻辑
},
/** 行删除回调 */ handleRowDeleted() {
handleRowDeleted(row) { this.$message.success('删除成功');
this.$message.success('删除成功')
}, },
/** 批量删除回调 */
handleBatchDelete(ids) { handleBatchDelete(ids) {
this.$message.success(`成功删除 ${ids.length} `) this.$message.success(`成功删除 ${ids.length} 项`);
}, },
/** 单元格变化回调 */ handleCellChange({ prop }) {
handleCellChange({ row, prop, value }) { if (['plannedQuantity', 'actualQuantity'].includes(prop)) {
// 可以在这里处理特定字段的变化 this.calculateTotals();
if (prop === 'plannedQuantity' || prop === 'actualQuantity') {
this.calculateTotals()
} }
}, },
/** 计算总数 */ /**
* 计算明细总数
*/
calculateTotals() { calculateTotals() {
if (!this.form.inboundOrderItemsList || this.form.inboundOrderItemsList.length === 0) { if (!this.form.inboundOrderItemsList || this.form.inboundOrderItemsList.length === 0) {
this.form.totalPlannedQuantity = 0 this.form.totalPlannedQuantity = 0;
this.form.totalActualQuantity = 0 this.form.totalActualQuantity = 0;
this.form.totalPackages = 0 this.form.totalPackages = 0;
return return;
} }
const totals = this.form.inboundOrderItemsList.reduce( const totals = this.form.inboundOrderItemsList.reduce((acc, item) => {
(acc, item) => { acc.plannedQuantity += parseFloat(item.plannedQuantity) || 0;
acc.plannedQuantity += parseFloat(item.plannedQuantity) || 0 acc.actualQuantity += parseFloat(item.actualQuantity) || 0;
acc.actualQuantity += parseFloat(item.actualQuantity) || 0 acc.packages += parseFloat(item.plannedPackages) || 0;
acc.packages += parseFloat(item.plannedPackages) || 0 return acc;
return acc }, { plannedQuantity: 0, actualQuantity: 0, packages: 0 });
},
{ plannedQuantity: 0, actualQuantity: 0, packages: 0 }
)
this.form.totalPlannedQuantity = totals.plannedQuantity this.form.totalPlannedQuantity = totals.plannedQuantity;
this.form.totalActualQuantity = totals.actualQuantity this.form.totalActualQuantity = totals.actualQuantity;
this.form.totalPackages = totals.packages this.form.totalPackages = totals.packages;
}, },
/** 导出按钮操作 */ /**
* 导出按钮操作
*/
handleExport() { handleExport() {
const params = { ...this.queryParams } const params = { ...this.queryParams };
delete params.pageNum delete params.pageNum;
delete params.pageSize delete params.pageSize;
this.download('inventory/inbound/export', params, `inbound_${new Date().getTime()}.xlsx`) this.download('inventory/inbound/export', params, `inbound_${new Date().getTime()}.xlsx`);
} }
} }
} }
</script> </script>
<style scoped> <style scoped>
/* 对齐字典页面的样式类名和布局 */
.page-container { .page-container {
padding: 16px; padding: 16px;
background: #fff; background: #fff;
...@@ -1197,8 +1217,8 @@ export default { ...@@ -1197,8 +1217,8 @@ export default {
} }
.scrollable-dialog .el-dialog__body { .scrollable-dialog .el-dialog__body {
max-height: 80vh; /* 最大高度80%视口高度 */ max-height: 80vh;
overflow-y: auto; /* 超出滚动 */ overflow-y: auto;
padding: 20px; padding: 20px;
} }
...@@ -1216,8 +1236,17 @@ export default { ...@@ -1216,8 +1236,17 @@ export default {
margin-bottom: 20px; margin-bottom: 20px;
} }
/* 统一对话框底部按钮样式 */
.dialog-footer { .dialog-footer {
text-align: right; text-align: right;
} }
/* 优化表格边框和交互 */
:deep(.el-table) {
--el-table-row-hover-bg-color: #f8f9fa;
}
/* 优化弹窗内描述列表样式 */
:deep(.el-descriptions) {
--el-descriptions-item-label-color: #606266;
}
</style> </style>
\ No newline at end of file
...@@ -14,6 +14,7 @@ import com.alibaba.excel.exception.ExcelAnalysisException; ...@@ -14,6 +14,7 @@ import com.alibaba.excel.exception.ExcelAnalysisException;
import com.ruoyi.common.annotation.Excel; import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.entity.SysDictData; import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.uuid.UUID; import com.ruoyi.common.utils.uuid.UUID;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
...@@ -24,6 +25,7 @@ import com.ruoyi.inventory.domain.vo.inboundVO.InboundTRDCTemplateVO; ...@@ -24,6 +25,7 @@ import com.ruoyi.inventory.domain.vo.inboundVO.InboundTRDCTemplateVO;
import com.ruoyi.inventory.domain.vo.inboundVO.InboundTemplateVO; import com.ruoyi.inventory.domain.vo.inboundVO.InboundTemplateVO;
import com.ruoyi.inventory.service.impl.InboundOrdersServiceImpl; import com.ruoyi.inventory.service.impl.InboundOrdersServiceImpl;
import com.ruoyi.system.service.ISysDictDataService; import com.ruoyi.system.service.ISysDictDataService;
import org.apache.commons.collections4.MapUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
...@@ -66,6 +68,10 @@ public class InboundOrdersController extends BaseController ...@@ -66,6 +68,10 @@ public class InboundOrdersController extends BaseController
List<InboundOrders> list = inboundOrdersService.selectInboundOrdersList(inboundOrders); List<InboundOrders> list = inboundOrdersService.selectInboundOrdersList(inboundOrders);
return getDataTable(list); return getDataTable(list);
} }
/**
* 获取字典映射表
*/
private Map<Object, Object> getDictMap(String dictType) { private Map<Object, Object> getDictMap(String dictType) {
List<SysDictData> dictList = iSysDictDataService.selectDictDataByType(dictType); List<SysDictData> dictList = iSysDictDataService.selectDictDataByType(dictType);
Map<Object, Object> dictMap = new HashMap<>(); Map<Object, Object> dictMap = new HashMap<>();
...@@ -80,32 +86,74 @@ public class InboundOrdersController extends BaseController ...@@ -80,32 +86,74 @@ public class InboundOrdersController extends BaseController
@PreAuthorize("@ss.hasPermi('inventory:inbound:export')") @PreAuthorize("@ss.hasPermi('inventory:inbound:export')")
@Log(title = "入库单主", businessType = BusinessType.EXPORT) @Log(title = "入库单主", businessType = BusinessType.EXPORT)
@PostMapping("/export") @PostMapping("/export")
public void export(HttpServletResponse response, InboundOrders inboundOrders) public void export(HttpServletResponse response, InboundOrders inboundOrders) {
{ // 1. 基础空值校验:查询结果为空时直接导出空表格,避免后续循环NPE
List<InboundItemsTO> list = inboundOrdersService.selectInboundOrdersAndItems(inboundOrders); List<InboundItemsTO> list = inboundOrdersService.selectInboundOrdersAndItems(inboundOrders);
if (list == null || list.isEmpty()) {
ExcelUtil<InboundItemsTO> util = new ExcelUtil<>(InboundItemsTO.class);
// 替换 List.of() 为 Java 8 兼容的空列表创建方式
util.exportExcel(response, new ArrayList<>(), "入库单导出数据");
return;
}
// 2. 字典映射表空值校验:避免字典表为空导致的NPE
Map<Object, Object> colorDictMap = getDictMap("label_color"); Map<Object, Object> colorDictMap = getDictMap("label_color");
colorDictMap = MapUtils.emptyIfNull(colorDictMap); // 空Map转为空集合,避免后续get操作NPE
// 3. 循环处理每条数据,增加全字段空值保护
for (InboundItemsTO inboundItem : list) { for (InboundItemsTO inboundItem : list) {
if (inboundItem != null) { // 跳过空对象
inboundItem.setPackageWeight(inboundItem.getWeight() * (inboundItem.getActualQuantity() / inboundItem.getActualPackages())); if (inboundItem == null) {
inboundItem.setUnitWeight(inboundItem.getWeight() * (inboundItem.getActualQuantity() / inboundItem.getActualPackages())); continue;
inboundItem.setLabelColorName((String) colorDictMap.get(inboundItem.getLabelColor()+"")); }
switch (inboundItem.getOrderTypeId()) {
// ========== 3.1 数学运算安全处理(避免除零/空值运算NPE) ==========
// 初始化默认值,避免空值运算
Double weight = inboundItem.getWeight() == null ? 0.0 : inboundItem.getWeight();
Double actualQuantity = inboundItem.getActualQuantity() == null ? 0.0 : inboundItem.getActualQuantity();
Double actualPackages = inboundItem.getActualPackages() == null ? 1.0 : inboundItem.getActualPackages();
// 安全除法:避免除零异常
double quantityPerPackage = actualPackages == 0 ? 0 : actualQuantity / actualPackages;
// 计算重量(空值保护)
double packageWeight = weight * quantityPerPackage;
// 赋值(避免setter传入null)
inboundItem.setPackageWeight(packageWeight);
inboundItem.setUnitWeight(packageWeight); // 与packageWeight值相同
// ========== 3.2 标签颜色名称映射(空值保护) ==========
String labelColor = inboundItem.getLabelColor() == null ? "" : inboundItem.getLabelColor().toString();
String labelColorName = (String) colorDictMap.get(labelColor);
inboundItem.setLabelColorName(StringUtils.defaultIfBlank(labelColorName, "")); // 空值转为空字符串
// ========== 3.3 订单类型分支处理(空值保护) ==========
String orderTypeId = StringUtils.defaultIfBlank(inboundItem.getOrderTypeId(), "-");
String remark = StringUtils.defaultIfBlank(inboundItem.getRemark(), "-");
String systemNo = StringUtils.defaultIfBlank(inboundItem.getSystemNo(), "-");
String orderId = StringUtils.defaultIfBlank(inboundItem.getOrderId(), "-");
switch (orderTypeId) {
case "1": case "1":
inboundItem.setRelocation(inboundItem.getRemark()); inboundItem.setRelocation(remark);
break; break;
case "2": case "2":
inboundItem.setFinishedLocation(inboundItem.getRemark()); inboundItem.setFinishedLocation(remark);
break; break;
case "3": case "3":
inboundItem.setRemarkTrdc(inboundItem.getRemark()); inboundItem.setRemarkTrdc(remark);
inboundItem.setFinishedSystemNo(inboundItem.getSystemNo()); inboundItem.setFinishedSystemNo(systemNo);
inboundItem.setFinishedOrderId(inboundItem.getOrderId()); inboundItem.setFinishedOrderId(orderId);
break;
// 增加默认分支,避免未匹配的情况
default:
// 可选:记录日志或设置默认值
break; break;
}
} }
} }
ExcelUtil<InboundItemsTO> util = new ExcelUtil<InboundItemsTO>(InboundItemsTO.class); // 4. 导出Excel(最终兜底:确保传入非null列表)
ExcelUtil<InboundItemsTO> util = new ExcelUtil<>(InboundItemsTO.class);
util.exportExcel(response, list, "入库单导出数据"); util.exportExcel(response, list, "入库单导出数据");
} }
......
...@@ -100,7 +100,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" ...@@ -100,7 +100,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="createUserCode != null and createUserCode != ''"> and create_user_code = #{createUserCode}</if> <if test="createUserCode != null and createUserCode != ''"> and create_user_code = #{createUserCode}</if>
<if test="updateUserCode != null and updateUserCode != ''"> and update_user_code = #{updateUserCode}</if> <if test="updateUserCode != null and updateUserCode != ''"> and update_user_code = #{updateUserCode}</if>
</where> </where>
order by date(inbound_date) desc,create_time desc order by order_status asc, date(inbound_date) desc,create_time desc
</select> </select>
<select id="selectInboundOrdersById" parameterType="String" resultMap="InboundOrdersInboundOrderItemsResult"> <select id="selectInboundOrdersById" parameterType="String" resultMap="InboundOrdersInboundOrderItemsResult">
...@@ -334,10 +334,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" ...@@ -334,10 +334,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
ioi.label_color, ioi.voucher_number, m.storage_temperature, ioi.label_color, ioi.voucher_number, m.storage_temperature,
m.hazard_id, io.order_id, io.system_no, io.owner_id, m.hazard_id, io.order_id, io.system_no, io.owner_id,
ioi.label_quantity, io.order_type, io.order_type_id, ioi.remark ioi.label_quantity, io.order_type, io.order_type_id, ioi.remark
from materials as m from inbound_order_items as ioi
inner join inbound_order_items as ioi on ioi.material_id = m.id left join materials as m on ioi.material_id = m.id
inner join inbound_orders as io on ioi.inbound_order_id = io.id left join inbound_orders as io on ioi.inbound_order_id = io.id
inner join storage_locations as sl on ioi.location_id = sl.id left join storage_locations as sl on ioi.location_id = sl.id
order by order_status asc, date(io.inbound_date) desc, io.create_time desc
</select> </select>
<resultMap id="InboundOrderAndItemsMap" type="com.ruoyi.inventory.domain.TO.InboundItemsTO"> <resultMap id="InboundOrderAndItemsMap" type="com.ruoyi.inventory.domain.TO.InboundItemsTO">
<!-- 基础字段映射:SQL字段名 -> Java实体类字段名 --> <!-- 基础字段映射:SQL字段名 -> Java实体类字段名 -->
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论