Commit c2162be0 by wangchunyang
parents b1240733 9e20d976
<template>
<div class="material-selector-container" style="overflow: hidden;">
<splitpanes class="default-theme">
<!-- 左侧分类树 -->
<pane size="16" style="overflow: auto;">
<TreeComponent
ref="treeComponent"
:tree-data="categoryTreeData"
:tree-props="treeProps"
:node-key="nodeKey"
:show-search="true"
search-placeholder="请输入分类名称"
:default-expand-all="true"
:highlight-current="true"
:loading="loadingTree"
@node-click="handleTreeClick"
>
<template #node-content="{ node, data }">
<span class="custom-tree-node">{{ node.label }}</span>
</template>
</TreeComponent>
</pane>
<!-- 右侧物料列表 -->
<pane size="84" style="overflow: auto;">
<div style="padding: 10px; display: flex; flex-direction: column;">
<!-- 查询表单 -->
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" label-width="88px">
<el-form-item label="SAP物料号" prop="sapNo">
<el-input
v-model="queryParams.sapNo"
placeholder="请输入SAP物料号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="物料名称" prop="materialName">
<el-input
v-model="queryParams.materialName"
placeholder="请输入物料名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="物料分类" prop="categoryNameInput">
<el-input
v-model="queryParams.categoryNameInput"
placeholder="请输入物料分类"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<!-- 物料表格:修复选择列逻辑,避免锁定 -->
<el-table
ref="materialTable"
v-loading="loading"
:data="materialsList"
@selection-change="handleSelectionChange"
:scroll-x="true"
:row-key="row => row.id"
@row-click="handleRowClick"
:select-on-indeterminate="false"
@select="handleTableSelect"
>
<!-- 修复单选/多选列:单选模式下不限制selectable,通过事件控制唯一选中 -->
<el-table-column
type="selection"
width="55"
align="center"
/>
<el-table-column type="index" label="序号" align="center"/>
<el-table-column label="SAP物料号" align="center" prop="sapNo" />
<el-table-column label="物料名称" align="center" prop="materialName" width="150"/>
<el-table-column label="TS Code" align="center" prop="tsCode" />
<el-table-column label="物料分类" align="center" prop="categoryCode">
<template slot-scope="scope">
{{ scope.row.displayCategory || categoryMap[scope.row.categoryCode] || scope.row.categoryCode || '-' }}
</template>
</el-table-column>
<el-table-column label="规格型号" align="center" prop="specification" />
<el-table-column label="计量单位" align="center" prop="materialUnit" />
<el-table-column label="是否批次管理" align="center" prop="isBatchManaged">
<template slot-scope="scope">
<el-tag :type="scope.row.isBatchManaged === 1 ? 'success' : 'info'" size="mini">
{{ scope.row.isBatchManaged === 1 ? '是' : '否' }}
</el-tag>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
</div>
</pane>
</splitpanes>
</div>
</template>
<script>
import { listMaterials } from "@/api/inventory/materials"
import { listMaterials_category } from "@/api/inventory/materials_category"
import TreeComponent from '@/views/inventory/materials_category/treeComponent.vue'
import { Splitpanes, Pane } from 'splitpanes'
import 'splitpanes/dist/splitpanes.css'
export default {
name: "MaterialSelector",
components: { TreeComponent, Splitpanes, Pane },
props: {
// 支持传入默认选中的物料ID(单选传单个ID,多选传数组)
value: {
type: [Array, Number, String],
default: () => []
},
// 是否允许多选
multiple: {
type: Boolean,
default: true
},
// 默认选中的分类编码
defaultCategoryCodes: {
type: Array,
default: () => []
}
},
data() {
return {
// 分类树相关
categoryTreeData: [],
treeProps: { children: 'children', label: 'label', value: 'sid' },
nodeKey: 'sid',
loadingTree: false,
categoryMap: {}, // 分类编码->分类名称
categoryNameToCodeMap: {}, // 分类名称->分类编码
categoryCodeToSidMap: {}, // 分类编码->树节点sid
currentNodeId: null,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
sapNo: null,
materialName: null,
tsCode: null,
categoryCode: null,
categoryNameInput: null,
specification: null,
},
// 物料列表相关
materialsList: [],
total: 0,
loading: false,
selectedRows: [], // 选中的物料行数据
singleSelectedId: null, // 单选模式下的选中ID
isSelecting: false // 防止选择事件重复触发的锁
}
},
watch: {
// 监听外部传入的选中值变化
value: {
immediate: true,
deep: true,
handler(val) {
// 防止加载中或正在选择时触发,避免锁定
if (this.loading || this.isSelecting) return
if (!val || (Array.isArray(val) && !val.length)) {
this.clearSelection()
return
}
this.$nextTick(() => {
if (!this.$refs.materialTable || !this.materialsList.length) return
// 统一处理值格式:单选转单个ID,多选转数组
const targetIds = this.multiple
? Array.isArray(val) ? val.map(id => Number(id)) : [Number(val)]
: [Array.isArray(val) ? Number(val[0]) : Number(val)]
this.isSelecting = true // 加锁,防止重复触发
try {
// 清空原有选择
this.$refs.materialTable.clearSelection()
if (this.multiple) {
// 多选模式:选中所有匹配的行
this.materialsList.forEach(row => {
if (targetIds.includes(Number(row.id))) {
this.$refs.materialTable.toggleRowSelection(row, true)
}
})
} else {
// 单选模式:只选中第一个匹配的行
this.singleSelectedId = targetIds[0] || null
const targetRow = this.materialsList.find(row => Number(row.id) === this.singleSelectedId)
if (targetRow) {
this.$refs.materialTable.toggleRowSelection(targetRow, true)
}
}
} finally {
this.isSelecting = false // 解锁
}
})
}
},
// 监听多选状态切换:彻底重置选择状态,避免锁定
multiple: {
immediate: true,
handler(val) {
if (this.$refs.materialTable) {
this.isSelecting = true
try {
// 清空所有选择状态
this.$refs.materialTable.clearSelection()
this.selectedRows = []
this.singleSelectedId = null
// 重新初始化选中状态
this.$nextTick(() => {
this.$watchers.find(w => w.expression === 'value').handler(this.value)
})
} finally {
this.isSelecting = false
}
}
}
},
// 监听默认分类编码变化
defaultCategoryCodes: {
immediate: true,
handler(val) {
if (val && val.length && this.categoryTreeData.length) {
this.$nextTick(() => {
this.selectCategoryNodes(val)
})
}
}
}
},
async created() {
// 并行加载分类数据和分类树
await Promise.all([
this.getCategoryList(),
this.getCategoryTreeData()
])
// 加载物料列表
this.getList()
},
methods: {
/**
* 获取分类列表,构建编码-名称映射
*/
async getCategoryList() {
try {
const response = await listMaterials_category({ pageNum: 1, pageSize: 1000 })
if (response.rows && response.rows.length > 0) {
this.categoryMap = {}
this.categoryNameToCodeMap = {}
response.rows.forEach(item => {
// 只处理启用的分类
if (item.isUsed !== 0 && item.isUsed !== '0') {
const code = item.categoryCode
this.categoryMap[code] = item.categoryName
// 构建分类名称到编码的映射(处理同名分类)
if (!this.categoryNameToCodeMap[item.categoryName]) {
this.categoryNameToCodeMap[item.categoryName] = code
} else if (!Array.isArray(this.categoryNameToCodeMap[item.categoryName])) {
this.categoryNameToCodeMap[item.categoryName] = [this.categoryNameToCodeMap[item.categoryName], code]
} else {
this.categoryNameToCodeMap[item.categoryName].push(code)
}
}
})
}
} catch (error) {
console.error('获取分类列表失败:', error)
}
},
/**
* 获取分类树数据
*/
async getCategoryTreeData() {
this.loadingTree = true
try {
const response = await listMaterials_category({ pageNum: 1, pageSize: 1000 })
if (response.rows && response.rows.length > 0) {
// 过滤启用的分类
const activeCategories = response.rows.filter(item => item.isUsed !== 0 && item.isUsed !== '0')
// 构建树形结构
this.categoryTreeData = this.buildTreeData(activeCategories)
// 构建分类编码到树节点sid的映射
this.buildCategoryCodeToSidMap(this.categoryTreeData)
}
} catch (error) {
console.error('获取分类树数据失败:', error)
} finally {
this.loadingTree = false
}
},
/**
* 构建分类树形结构
*/
buildTreeData(list, parentId = null) {
return list
.filter(item => parentId === null
? (!item.parentId || item.parentId === 0 || item.parentId === '0')
: Number(item.parentId) === Number(parentId)
)
.map(item => ({
...item,
sid: String(item.id),
label: item.categoryName,
children: this.buildTreeData(list, item.id).length
? this.buildTreeData(list, item.id)
: undefined
}))
},
/**
* 构建分类编码到树节点sid的映射
*/
buildCategoryCodeToSidMap(treeData) {
treeData.forEach(node => {
if (node.categoryCode) {
this.categoryCodeToSidMap[node.categoryCode] = node.sid
// 兼容格式化的编码(如带横线的)
const rawCode = node.categoryCode.replace(/-/g, '')
if (rawCode !== node.categoryCode) {
this.categoryCodeToSidMap[rawCode] = node.sid
}
}
if (node.children && node.children.length) {
this.buildCategoryCodeToSidMap(node.children)
}
})
},
/**
* 根据分类编码选中树节点
*/
selectCategoryNodes(categoryCodes) {
if (!this.$refs.treeComponent || !this.$refs.treeComponent.$refs.tree) return
const tree = this.$refs.treeComponent.$refs.tree
categoryCodes.forEach(code => {
const rawCode = code.replace(/-/g, '')
const sid = this.categoryCodeToSidMap[rawCode] || this.categoryCodeToSidMap[code]
if (sid) {
tree.setCurrentKey(sid)
this.currentNodeId = sid
// 展开节点
const node = tree.getNode(sid)
if (node) {
tree.expandNode(node)
}
}
})
},
/**
* 分类树节点点击事件
*/
handleTreeClick(data) {
this.currentNodeId = data.sid
this.queryParams.categoryCode = data.categoryCode
this.queryParams.categoryNameInput = null
this.queryParams.pageNum = 1
this.getList()
},
/**
* 获取物料列表数据
*/
getList() {
this.loading = true
listMaterials(this.queryParams).then(response => {
// 过滤启用的物料并处理分类名称显示
this.materialsList = (response.rows || []).filter(item => item.isUsed !== 0 && item.isUsed !== '0').map(item => ({
...item,
displayCategory: this.categoryMap[item.categoryCode] || `${item.categoryCode}(未匹配分类)`
}))
this.total = response.total || 0
// 列表加载完成后重新同步选中状态(延迟执行,避免DOM未更新)
setTimeout(() => {
this.$watchers.find(w => w.expression === 'value').handler(this.value)
}, 100)
}).catch(error => {
console.error('获取物料列表失败:', error)
this.materialsList = []
this.total = 0
}).finally(() => {
this.loading = false
})
},
/**
* 搜索按钮点击事件
*/
handleQuery() {
// 根据分类名称匹配分类编码
const inputName = this.queryParams.categoryNameInput
if (inputName) {
const matchedCode = this.categoryNameToCodeMap[inputName]
if (matchedCode) {
this.queryParams.categoryCode = Array.isArray(matchedCode) ? matchedCode[0] : matchedCode
} else {
// 模糊匹配分类名称
const matchedCodes = Object.entries(this.categoryMap)
.filter(([code, name]) => name.includes(inputName))
.map(([code]) => code)
if (matchedCodes.length > 0) {
this.queryParams.categoryCode = matchedCodes[0]
}
}
}
this.queryParams.pageNum = 1
this.getList()
},
/**
* 重置查询条件
*/
resetQuery() {
this.queryParams = {
pageNum: 1,
pageSize: 10,
sapNo: null,
materialName: null,
tsCode: null,
categoryCode: null,
categoryNameInput: null,
specification: null,
}
this.currentNodeId = null
// 清空树节点选中状态
if (this.$refs.treeComponent && this.$refs.treeComponent.$refs.tree) {
this.$refs.treeComponent.$refs.tree.setCurrentKey(null)
}
this.getList()
},
/**
* 表格选择变化事件(批量选择)
*/
handleSelectionChange(selection) {
if (this.isSelecting || !this.$refs.materialTable) return
this.isSelecting = true
try {
// 单选模式处理:确保只有一个选中项
if (!this.multiple) {
if (selection.length > 1) {
// 移除多余选中项,只保留最后一个
const lastRow = selection.pop()
this.$refs.materialTable.clearSelection()
this.$refs.materialTable.toggleRowSelection(lastRow, true)
this.selectedRows = [lastRow]
this.singleSelectedId = Number(lastRow.id)
} else {
this.selectedRows = selection
this.singleSelectedId = selection.length > 0 ? Number(selection[0].id) : null
}
} else {
// 多选模式
this.selectedRows = selection
}
// 组装选中数据并触发事件
const selectedIds = this.selectedRows.map(row => Number(row.id))
const selectedData = this.selectedRows.map(item => ({
id: Number(item.id),
sapNo: item.sapNo,
materialName: item.materialName,
categoryCode: item.categoryCode,
specification: item.specification,
materialUnit: item.materialUnit,
isBatchManaged: item.isBatchManaged
}))
// 触发事件:input用于v-model绑定,change返回详细数据
if (this.multiple) {
this.$emit('input', selectedIds)
this.$emit('change', selectedData)
} else {
const singleId = selectedIds.length > 0 ? selectedIds[0] : ''
const singleData = selectedData.length > 0 ? selectedData[0] : null
this.$emit('input', singleId)
this.$emit('change', singleData)
}
} finally {
this.isSelecting = false
}
},
/**
* 表格单个选择事件(点击选择框)
*/
handleTableSelect(selection, row) {
if (this.isSelecting || this.multiple) return
// 单选模式:点击选择框时,清空其他选中项
this.isSelecting = true
try {
const isSelected = selection.includes(row)
this.$refs.materialTable.clearSelection()
if (isSelected) {
this.$refs.materialTable.toggleRowSelection(row, true)
this.singleSelectedId = Number(row.id)
this.selectedRows = [row]
this.$emit('input', Number(row.id))
this.$emit('change', row)
} else {
this.singleSelectedId = null
this.selectedRows = []
this.$emit('input', '')
this.$emit('change', null)
}
} finally {
this.isSelecting = false
}
},
/**
* 表格行点击事件
*/
handleRowClick(row) {
if (this.isSelecting || !this.$refs.materialTable) return
this.isSelecting = true
try {
if (!this.multiple) {
// 单选模式:点击行切换选中状态
const isCurrentlySelected = Number(this.singleSelectedId) === Number(row.id)
this.$refs.materialTable.clearSelection()
if (!isCurrentlySelected) {
this.$refs.materialTable.toggleRowSelection(row, true)
this.singleSelectedId = Number(row.id)
this.selectedRows = [row]
this.$emit('input', Number(row.id))
this.$emit('change', row)
} else {
this.singleSelectedId = null
this.selectedRows = []
this.$emit('input', '')
this.$emit('change', null)
}
} else {
// 多选模式:点击行切换选中状态
this.$refs.materialTable.toggleRowSelection(row)
}
} finally {
this.isSelecting = false
}
},
/**
* 清空选中状态(外部调用)
*/
clearSelection() {
if (this.isSelecting || !this.$refs.materialTable) return
this.isSelecting = true
try {
this.$refs.materialTable.clearSelection()
this.selectedRows = []
this.singleSelectedId = null
this.$emit('input', this.multiple ? [] : '')
this.$emit('change', this.multiple ? [] : null)
} finally {
this.isSelecting = false
}
},
/**
* 获取选中的物料详情(外部调用)
*/
getSelectedMaterials() {
return this.multiple ? [...this.selectedRows] : (this.selectedRows[0] || null)
},
/**
* 设置单选选中项(外部调用)
*/
setSingleSelection(materialId) {
if (this.isSelecting || this.multiple) return
this.isSelecting = true
try {
const targetId = Number(materialId)
this.singleSelectedId = targetId
this.$nextTick(() => {
this.$refs.materialTable.clearSelection()
const targetRow = this.materialsList.find(row => Number(row.id) === targetId)
if (targetRow) {
this.$refs.materialTable.toggleRowSelection(targetRow, true)
this.selectedRows = [targetRow]
this.$emit('input', targetId)
this.$emit('change', targetRow)
}
})
} finally {
this.isSelecting = false
}
}
}
}
</script>
<style scoped>
.material-selector-container {
height: 100%;
min-height: 500px;
}
.custom-tree-node {
font-size: 14px;
}
/* 优化表格选择框样式,避免点击区域冲突 */
/deep/ .el-table .el-table__header .cell {
text-align: center;
}
/deep/ .el-table--enable-row-hover .el-table__body tr:hover>td {
background-color: #f5f7fa;
}
/* 确保选择框可点击,无遮挡 */
/deep/ .el-table__fixed-right,
/deep/ .el-table__fixed-left {
pointer-events: auto !important;
}
</style>
\ No newline at end of file
...@@ -74,7 +74,6 @@ ...@@ -74,7 +74,6 @@
align="center" align="center"
/> />
<el-table-column type="index" label="序号" align="center"/> <el-table-column type="index" label="序号" align="center"/>
<el-table-column label="物料ID" align="center" prop="id" />
<el-table-column label="SAP物料号" align="center" prop="sapNo" /> <el-table-column label="SAP物料号" align="center" prop="sapNo" />
<el-table-column label="物料名称" align="center" prop="materialName" width="150"/> <el-table-column label="物料名称" align="center" prop="materialName" width="150"/>
<el-table-column label="TS Code" align="center" prop="tsCode" /> <el-table-column label="TS Code" align="center" prop="tsCode" />
......
...@@ -113,7 +113,6 @@ ...@@ -113,7 +113,6 @@
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
<!-- 新增查询字段 -->
<el-form-item label="库位使用" prop="locationUsage"> <el-form-item label="库位使用" prop="locationUsage">
<el-select <el-select
v-model="queryParams.locationUsage" v-model="queryParams.locationUsage"
...@@ -188,7 +187,6 @@ ...@@ -188,7 +187,6 @@
<div><strong>层:</strong>{{ scope.row.layerCode || '-' }}</div> <div><strong>层:</strong>{{ scope.row.layerCode || '-' }}</div>
</el-col> </el-col>
</el-row> </el-row>
<!-- 新增展开字段 -->
<el-row :gutter="20" style="margin: 10px 0;"> <el-row :gutter="20" style="margin: 10px 0;">
<el-col :span="6"> <el-col :span="6">
<div><strong>上架顺序:</strong>{{ scope.row.putawayOrder || '-' }}</div> <div><strong>上架顺序:</strong>{{ scope.row.putawayOrder || '-' }}</div>
...@@ -241,7 +239,6 @@ ...@@ -241,7 +239,6 @@
<dict-tag :options="dict.type.location_type" :value="scope.row.locationType"/> <dict-tag :options="dict.type.location_type" :value="scope.row.locationType"/>
</template> </template>
</el-table-column> </el-table-column>
<!-- 新增表格列 -->
<el-table-column label="库位使用" align="center" prop="locationUsage" width="100"> <el-table-column label="库位使用" align="center" prop="locationUsage" width="100">
<template slot-scope="scope"> <template slot-scope="scope">
<dict-tag :options="dict.type.location_usage" :value="scope.row.locationUsage"/> <dict-tag :options="dict.type.location_usage" :value="scope.row.locationUsage"/>
...@@ -271,7 +268,7 @@ ...@@ -271,7 +268,7 @@
> >
<div class="category-tags"> <div class="category-tags">
<el-tag <el-tag
v-for="(name, index) in (scope.row.allowedCategoryNames ? scope.row.allowedCategoryNames.split(',') : [])" v-for="(name, index) in (scope.row.allowedCategoryNames ? scope.row.allowedCategoryNames.split(',').filter(n => n.trim()) : [])"
:key="name" :key="name"
type="info" type="info"
size="small" size="small"
...@@ -281,12 +278,12 @@ ...@@ -281,12 +278,12 @@
{{ name }} {{ name }}
</el-tag> </el-tag>
<el-tag <el-tag
v-if="(scope.row.allowedCategoryNames ? scope.row.allowedCategoryNames.split(',').length : 0) > 3" v-if="(scope.row.allowedCategoryNames ? scope.row.allowedCategoryNames.split(',').filter(n => n.trim()).length : 0) > 3"
type="info" type="info"
size="small" size="small"
style="margin-right: 5px; margin-bottom: 5px; background: #f0f9eb; border-color: #c2e7b0;" style="margin-right: 5px; margin-bottom: 5px; background: #f0f9eb; border-color: #c2e7b0;"
> >
+{{ (scope.row.allowedCategoryNames ? scope.row.allowedCategoryNames.split(',').length : 0) - 3 }} +{{ (scope.row.allowedCategoryNames ? scope.row.allowedCategoryNames.split(',').filter(n => n.trim()).length : 0) - 3 }}
</el-tag> </el-tag>
</div> </div>
</el-tooltip> </el-tooltip>
...@@ -595,7 +592,7 @@ ...@@ -595,7 +592,7 @@
</div> </div>
</el-dialog> </el-dialog>
<!-- 导入组件 - 集成货主页面的导入功能 --> <!-- 导入组件 -->
<import-excel <import-excel
ref="import" ref="import"
title="库位导入" title="库位导入"
...@@ -624,7 +621,6 @@ import { listMaterials } from "@/api/inventory/materials" ...@@ -624,7 +621,6 @@ import { listMaterials } from "@/api/inventory/materials"
export default { export default {
name: "Locations", name: "Locations",
components: { materialsSeletor, WarehouseSelector, ImportExcel }, components: { materialsSeletor, WarehouseSelector, ImportExcel },
// 新增字典类型
dicts: ['sys_normal_disable', 'location_type', 'location_usage', 'yorn'], dicts: ['sys_normal_disable', 'location_type', 'location_usage', 'yorn'],
data() { data() {
return { return {
...@@ -638,48 +634,28 @@ export default { ...@@ -638,48 +634,28 @@ export default {
title: "", title: "",
open: false, open: false,
dict: { // 查询参数
type: {
location_type: [
{ label: "货架", value: "1" },
{ label: "地面", value: "2" },
{ label: "货位", value: "3" },
{ label: "专区", value: "4" }
],
sys_normal_disable: [
{ label: "启用", value: "1" },
{ label: "禁用", value: "0" }
],
// 新增字典默认值(实际会从后端加载)
location_usage: [],
yorn: [
{ label: "是", value: "Y" },
{ label: "否", value: "N" }
]
}
},
queryParams: { queryParams: {
pageNum: 1, pageNum: 1,
pageSize: 10, pageSize: 10,
locationCode: null, locationCode: null,
locationName: null, locationName: null,
warehouseId: null, // 前端保持warehouseId,内部映射后端的warehousesId warehouseId: null,
locationType: null, locationType: null,
layerCode: null, layerCode: null,
// 新增查询参数
locationUsage: null, locationUsage: null,
allowMixedProducts: null, allowMixedProducts: null,
zoneCode: null, zoneCode: null,
pickingArea: null pickingArea: null
}, },
// 表单数据
form: { form: {
id: null, id: null,
locationCode: null, locationCode: null,
locationName: null, locationName: null,
warehouseId: null, // 前端保持warehouseId,内部映射后端的warehousesId warehouseId: null,
warehouseName: null, // 新增仓库名称字段 warehouseName: null,
locationType: null, locationType: null,
zoneCode: null, zoneCode: null,
rowCode: null, rowCode: null,
...@@ -696,7 +672,6 @@ export default { ...@@ -696,7 +672,6 @@ export default {
isEnabled: 1, isEnabled: 1,
isUsed: 1, isUsed: 1,
sortNo: 0, sortNo: 0,
// 新增表单字段
putawayOrder: null, putawayOrder: null,
pickingOrder: null, pickingOrder: null,
locationUsage: null, locationUsage: null,
...@@ -707,6 +682,7 @@ export default { ...@@ -707,6 +682,7 @@ export default {
allowMixedBatches: null allowMixedBatches: null
}, },
// 表单验证规则
rules: { rules: {
locationCode: [ locationCode: [
{ required: true, message: '库位编码不能为空', trigger: 'blur' }, { required: true, message: '库位编码不能为空', trigger: 'blur' },
...@@ -716,28 +692,32 @@ export default { ...@@ -716,28 +692,32 @@ export default {
{ required: true, message: '库位名称不能为空', trigger: 'blur' }, { required: true, message: '库位名称不能为空', trigger: 'blur' },
{ min: 1, max: 100, message: '库位名称长度不能超过100个字符', trigger: 'blur' } { min: 1, max: 100, message: '库位名称长度不能超过100个字符', trigger: 'blur' }
], ],
warehouseId: [ // 验证规则保持warehouseId warehouseId: [
{ required: true, message: '仓库不能为空', trigger: 'change' } { required: true, message: '仓库不能为空', trigger: 'change' }
], ],
locationType: [ locationType: [
{ required: true, message: '库位类型不能为空', trigger: 'change' } { required: true, message: '库位类型不能为空', trigger: 'change' }
], ],
// 新增表单验证规则
locationUsage: [ locationUsage: [
{ required: true, message: '库位使用不能为空', trigger: 'change' } { required: true, message: '库位使用不能为空', trigger: 'change' }
], ],
allowMixedProducts: [ allowMixedProducts: [
{ required: true, message: '允许混放产品不能为空', trigger: 'change' } { required: true, message: '允许混放产品不能为空', trigger: 'change' }
], ],
allowMixedBatches: [
{ required: true, message: '允许混放批次不能为空', trigger: 'change' }
],
isEnabled: [ isEnabled: [
{ required: true, message: '应用状态不能为空', trigger: 'change' } { required: true, message: '应用状态不能为空', trigger: 'change' }
] ]
}, },
warehouseList: [], // 仓库列表(包含id和名称) // 仓库相关
warehouseList: [],
loadingWarehouse: false, loadingWarehouse: false,
queryWarehouseName: '', // 查询用仓库名称 queryWarehouseName: '',
// 物料选择相关
showMaterialSelect: false, showMaterialSelect: false,
tempSelectedMaterials: { tempSelectedMaterials: {
materialCodes: [], materialCodes: [],
...@@ -746,12 +726,15 @@ export default { ...@@ -746,12 +726,15 @@ export default {
}, },
materialCodeToNameMap: {}, materialCodeToNameMap: {},
materialMapLoaded: false, materialMapLoaded: false,
// 仓库选择器相关
warehouseSelectorVisible: false, warehouseSelectorVisible: false,
warehouseSelectTarget: '', // 仓库选择目标(query/form) warehouseSelectTarget: '',
currentDetailItem: null // 当前编辑的明细项 currentDetailItem: null
} }
}, },
created() { created() {
console.log('【Locations组件】开始初始化')
this.getList() this.getList()
this.getWarehouseList() this.getWarehouseList()
this.initMaterialCodeToNameMap() this.initMaterialCodeToNameMap()
...@@ -759,6 +742,7 @@ export default { ...@@ -759,6 +742,7 @@ export default {
methods: { methods: {
// 清空查询仓库 // 清空查询仓库
clearQueryWarehouse() { clearQueryWarehouse() {
console.log('【清空查询仓库】执行清空操作')
this.queryWarehouseName = '' this.queryWarehouseName = ''
this.queryParams.warehouseId = null this.queryParams.warehouseId = null
this.handleQuery() this.handleQuery()
...@@ -766,14 +750,15 @@ export default { ...@@ -766,14 +750,15 @@ export default {
// 清空表单仓库 // 清空表单仓库
clearFormWarehouse() { clearFormWarehouse() {
console.log('【清空表单仓库】执行清空操作')
this.form.warehouseName = '' this.form.warehouseName = ''
this.form.warehouseId = null this.form.warehouseId = null
}, },
// 仓库选择回调 - 适配后端返回的warehousesId // 仓库选择回调
handleWarehouseSelected(warehouse) { handleWarehouseSelected(warehouse) {
console.log('【仓库选择回调】选中的仓库数据:', warehouse)
if (!warehouse) return if (!warehouse) return
// 统一处理:优先取warehousesId,兼容warehouseId/id
const warehouseId = warehouse.warehousesId || warehouse.warehouseId || warehouse.id const warehouseId = warehouse.warehousesId || warehouse.warehouseId || warehouse.id
const warehouseName = warehouse.warehousesName || warehouse.name || warehouse.warehouseName const warehouseName = warehouse.warehousesName || warehouse.name || warehouse.warehouseName
...@@ -785,7 +770,6 @@ export default { ...@@ -785,7 +770,6 @@ export default {
this.form.warehouseId = warehouseId this.form.warehouseId = warehouseId
this.form.warehouseName = warehouseName this.form.warehouseName = warehouseName
// 更新明细中的默认仓库
if (this.currentDetailItem) { if (this.currentDetailItem) {
this.currentDetailItem.warehouseId = warehouseId this.currentDetailItem.warehouseId = warehouseId
this.currentDetailItem.warehouseName = warehouseName this.currentDetailItem.warehouseName = warehouseName
...@@ -796,35 +780,41 @@ export default { ...@@ -796,35 +780,41 @@ export default {
// 打开仓库选择器 // 打开仓库选择器
openWarehouseSelector(target = 'form') { openWarehouseSelector(target = 'form') {
console.log('【打开仓库选择器】目标:', target)
this.warehouseSelectTarget = target this.warehouseSelectTarget = target
this.warehouseSelectorVisible = true this.warehouseSelectorVisible = true
}, },
// 获取仓库列表(包含id) // 获取仓库列表
getWarehouseList() { getWarehouseList() {
console.log('【获取仓库列表】开始请求仓库数据')
this.loadingWarehouse = true this.loadingWarehouse = true
listWarehouses({ pageNum: 1, pageSize: 1000, isUsed: 1 }).then(response => { listWarehouses({ pageNum: 1, pageSize: 1000, isUsed: 1 }).then(response => {
console.log('【获取仓库列表】请求成功,返回数据:', response)
this.warehouseList = response.rows || [] this.warehouseList = response.rows || []
this.loadingWarehouse = false this.loadingWarehouse = false
}).catch(error => { }).catch(error => {
console.error('获取仓库列表失败:', error) console.error('【获取仓库列表】请求失败:', error)
this.warehouseList = [] this.warehouseList = []
this.loadingWarehouse = false this.loadingWarehouse = false
}) })
}, },
// 根据仓库ID获取仓库名称 - 适配后端的warehousesId // 根据仓库ID获取仓库名称
getWarehouseNameById(warehouseId) { getWarehouseNameById(warehouseId) {
console.log('【根据仓库ID获取名称】仓库ID:', warehouseId)
if (!warehouseId) return '-' if (!warehouseId) return '-'
// 兼容匹配:同时匹配warehousesId/warehouseId/id
const warehouse = this.warehouseList.find(item => const warehouse = this.warehouseList.find(item =>
item.warehousesId === warehouseId || item.warehouseId === warehouseId || item.id === warehouseId item.warehousesId === warehouseId || item.warehouseId === warehouseId || item.id === warehouseId
) )
return warehouse ? (warehouse.warehousesName || warehouse.name || warehouse.warehouseName || '-') : '-' const warehouseName = warehouse ? (warehouse.warehousesName || warehouse.name || warehouse.warehouseName || '-') : '-'
console.log('【根据仓库ID获取名称】匹配到的仓库名称:', warehouseName)
return warehouseName
}, },
// 初始化物料编码-名称映射表 // 初始化物料编码-名称映射表
async initMaterialCodeToNameMap() { async initMaterialCodeToNameMap() {
console.log('【初始化物料映射表】开始加载物料数据')
try { try {
this.materialMapLoaded = true this.materialMapLoaded = true
let pageNum = 1 let pageNum = 1
...@@ -833,6 +823,7 @@ export default { ...@@ -833,6 +823,7 @@ export default {
this.materialCodeToNameMap = {} this.materialCodeToNameMap = {}
while (hasMore) { while (hasMore) {
console.log(`【初始化物料映射表】请求第${pageNum}页物料数据,每页${pageSize}条`)
const response = await listMaterials({ const response = await listMaterials({
pageNum, pageNum,
pageSize, pageSize,
...@@ -842,6 +833,7 @@ export default { ...@@ -842,6 +833,7 @@ export default {
}) })
if (response.rows && response.rows.length) { if (response.rows && response.rows.length) {
console.log(`【初始化物料映射表】第${pageNum}页返回${response.rows.length}条物料数据`)
response.rows.forEach(item => { response.rows.forEach(item => {
if (item.materialCode && item.materialName) { if (item.materialCode && item.materialName) {
const code = item.materialCode.trim().toUpperCase() const code = item.materialCode.trim().toUpperCase()
...@@ -854,37 +846,40 @@ export default { ...@@ -854,37 +846,40 @@ export default {
hasMore = false hasMore = false
} }
} }
console.log('物料映射表初始化完成:', this.materialCodeToNameMap) console.log('【初始化物料映射表】完成,映射表长度:', Object.keys(this.materialCodeToNameMap).length)
} catch (error) { } catch (error) {
console.error('初始化物料编码-名称映射表失败:', error) console.error('【初始化物料映射表】失败:', error)
this.materialMapLoaded = false this.materialMapLoaded = false
this.$modal.msgError('物料数据加载失败,请刷新页面重试!') this.$modal.msgError('物料数据加载失败,请刷新页面重试!')
} }
}, },
// 行点击事件(展开/收起) // 行点击事件
handleRowClick(row, event, column) { handleRowClick(row, event, column) {
console.log('【行点击事件】点击的行数据:', row, '列类型:', column.type)
if (column.type !== 'selection') { if (column.type !== 'selection') {
this.$refs.locationsTable?.toggleRowExpansion(row) this.$refs.locationsTable?.toggleRowExpansion(row)
} }
}, },
// 获取库位列表 - 适配后端的warehousesId参数 // 获取库位列表
getList() { getList() {
console.log('【获取库位列表】查询参数:', this.queryParams)
this.loading = true this.loading = true
// 转换参数:将前端的warehouseId映射为后端需要的warehousesId
const params = { const params = {
...this.queryParams, ...this.queryParams,
isUsed: 1, isUsed: 1,
warehousesId: this.queryParams.warehouseId, // 新增:传递warehousesId给后端 warehousesId: this.queryParams.warehouseId,
warehouseId: undefined // 移除:避免重复传参 warehouseId: undefined
} }
console.log('【获取库位列表】最终请求参数:', params)
listLocations(params).then(response => { listLocations(params).then(response => {
console.log('【获取库位列表】请求成功,返回数据:', response)
this.locationsList = response.rows || [] this.locationsList = response.rows || []
this.total = response.total || 0 this.total = response.total || 0
this.loading = false this.loading = false
}).catch(error => { }).catch(error => {
console.error('获取库位列表失败:', error) console.error('【获取库位列表】请求失败:', error)
this.locationsList = [] this.locationsList = []
this.total = 0 this.total = 0
this.loading = false this.loading = false
...@@ -893,12 +888,14 @@ export default { ...@@ -893,12 +888,14 @@ export default {
// 查询事件 // 查询事件
handleQuery() { handleQuery() {
console.log('【查询事件】执行查询操作')
this.queryParams.pageNum = 1 this.queryParams.pageNum = 1
this.getList() this.getList()
}, },
// 重置查询条件 // 重置查询条件
resetQuery() { resetQuery() {
console.log('【重置查询条件】执行重置操作')
this.queryParams = { this.queryParams = {
pageNum: 1, pageNum: 1,
pageSize: 10, pageSize: 10,
...@@ -907,7 +904,6 @@ export default { ...@@ -907,7 +904,6 @@ export default {
warehouseId: null, warehouseId: null,
locationType: null, locationType: null,
layerCode: null, layerCode: null,
// 重置新增的查询参数
locationUsage: null, locationUsage: null,
allowMixedProducts: null, allowMixedProducts: null,
zoneCode: null, zoneCode: null,
...@@ -919,20 +915,24 @@ export default { ...@@ -919,20 +915,24 @@ export default {
// 表格选择事件 // 表格选择事件
handleSelectionChange(selection) { handleSelectionChange(selection) {
console.log('【表格选择事件】选中的行:', 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
console.log('【表格选择事件】处理后 - ids:', this.ids, 'single:', this.single, 'multiple:', this.multiple)
}, },
// 新增库位 // 新增库位
handleAdd() { handleAdd() {
console.log('【新增库位】执行新增操作')
this.reset() this.reset()
this.open = true this.open = true
this.title = "添加库位" this.title = "添加库位"
}, },
// 修改库位 - 适配后端返回的warehousesId字段 // 修改库位 - 核心优化:适配数组格式的物料/分类数据
async handleUpdate(row) { async handleUpdate(row) {
console.log('【修改库位】触发修改操作,传入的行数据:', row)
this.reset() this.reset()
const id = row?.id || this.ids?.[0] const id = row?.id || this.ids?.[0]
if (!id) { if (!id) {
...@@ -941,14 +941,16 @@ export default { ...@@ -941,14 +941,16 @@ export default {
} }
try { try {
console.log('【修改库位】请求库位详情,ID:', id)
const response = await getLocations(id) const response = await getLocations(id)
console.log('后端返回库位详情:', response.data) console.log('【修改库位】后端返回库位详情:', response)
const rowData = response.data const rowData = response.data
// 映射后端的warehousesId到前端的warehouseId
// 映射后端字段到前端
const formData = { const formData = {
...rowData, ...rowData,
warehouseId: rowData.warehousesId || rowData.warehouseId || rowData.id, // 优先级:warehousesId > warehouseId > id warehouseId: rowData.warehousesId || rowData.warehouseId || rowData.id,
warehousesId: undefined // 移除:前端只维护warehouseId warehousesId: undefined
} }
this.form = JSON.parse(JSON.stringify(formData)) this.form = JSON.parse(JSON.stringify(formData))
...@@ -959,154 +961,284 @@ export default { ...@@ -959,154 +961,284 @@ export default {
await this.initMaterialCodeToNameMap() await this.initMaterialCodeToNameMap()
// 从allowedCategoryIds读取物料编码(替代缺失的materialCodes) // ========== 核心修改:处理数组格式的物料/分类数据 ==========
const rawMaterialCodes = this.form.allowedCategoryIds || row.allowedCategoryIds || '' console.log('【修改库位】开始处理物料数据,原始数据:', {
console.log('原始物料编码(从allowedCategoryIds读取):', rawMaterialCodes) materialIds: rowData.materialIds,
materialCodes: rowData.materialCodes,
names: rowData.names,
materialNames: rowData.materialNames,
categoryIds: rowData.categoryIds,
allowedCategoryIds: rowData.allowedCategoryIds
})
// 处理物料编码和名称(支持数组或字符串格式)
let materialCodes = []
let materialNames = []
if (rawMaterialCodes) { // 优先从materialIds数组读取
const materialCodes = rawMaterialCodes.split(',') if (Array.isArray(rowData.materialIds) && rowData.materialIds.length) {
materialCodes = rowData.materialIds
.filter(code => code && code.trim()) // 过滤null/空值
.map(code => code.trim().toUpperCase()) .map(code => code.trim().toUpperCase())
.filter(code => code) .filter((code, index, self) => self.indexOf(code) === index) // 去重
console.log('【修改库位】从materialIds数组读取物料编码:', materialCodes)
console.log('处理后物料编码:', materialCodes) }
console.log('映射表匹配:', materialCodes.map(code => ({ // 兼容字符串格式
code, else if (rowData.materialCodes) {
name: this.materialCodeToNameMap[code] materialCodes = rowData.materialCodes.split(',')
}))) .filter(code => code && code.trim())
.map(code => code.trim().toUpperCase())
.filter((code, index, self) => self.indexOf(code) === index)
console.log('【修改库位】从materialCodes字符串读取物料编码:', materialCodes)
}
this.form.materialNames = materialCodes.map(code => { // 处理物料名称(支持数组或字符串格式)
if (Array.isArray(rowData.names) && rowData.names.length) {
materialNames = rowData.names
.filter(name => name && name.trim())
.filter((name, index, self) => self.indexOf(name) === index)
console.log('【修改库位】从names数组读取物料名称:', materialNames)
}
else if (rowData.materialNames) {
materialNames = rowData.materialNames.split(',')
.filter(name => name && name.trim())
.filter((name, index, self) => self.indexOf(name) === index)
console.log('【修改库位】从materialNames字符串读取物料名称:', materialNames)
}
// 兜底:通过物料编码映射名称
else if (materialCodes.length) {
materialNames = materialCodes.map(code => {
return this.materialCodeToNameMap[code] || `【未匹配】${code}` return this.materialCodeToNameMap[code] || `【未匹配】${code}`
}).join(',') })
console.log('【修改库位】通过物料编码映射名称:', materialNames)
}
// 同步赋值materialCodes(确保选择器能接收到) // 处理分类ID(支持数组或字符串格式)
this.form.materialCodes = rawMaterialCodes let categoryIds = []
if (Array.isArray(rowData.categoryIds) && rowData.categoryIds.length) {
categoryIds = rowData.categoryIds
.filter(id => id && id.trim())
.filter((id, index, self) => self.indexOf(id) === index)
console.log('【修改库位】从categoryIds数组读取分类ID:', categoryIds)
}
else if (rowData.allowedCategoryIds) {
categoryIds = rowData.allowedCategoryIds.split(',')
.filter(id => id && id.trim())
.filter((id, index, self) => self.indexOf(id) === index)
console.log('【修改库位】从allowedCategoryIds字符串读取分类ID:', categoryIds)
}
// 更新表单数据
this.form.materialCodes = materialCodes.join(',')
this.form.materialNames = materialNames.join(',')
this.form.allowedCategoryIds = categoryIds.join(',')
// 处理分类名称
if (categoryIds.length && this.$refs.materialsSeletor) {
const categoryNames = categoryIds.map(code => {
const rawCode = code.replace(/-/g, '')
return this.$refs.materialsSeletor.categoryMap?.[rawCode] || code
})
this.form.allowedCategoryNames = categoryNames.join(',')
console.log('【修改库位】处理后的分类名称:', categoryNames)
} else if (rowData.allowedCategoryNames) {
this.form.allowedCategoryNames = rowData.allowedCategoryNames
console.log('【修改库位】使用原始分类名称:', rowData.allowedCategoryNames)
}
// 更新临时选择数据
this.tempSelectedMaterials = { this.tempSelectedMaterials = {
materialCodes: materialCodes, materialCodes: materialCodes,
names: this.form.materialNames.split(',').filter(name => name.trim()), names: materialNames,
categoryIds: this.form.allowedCategoryIds ? this.form.allowedCategoryIds.split(',').filter(c => c.trim()) : [] categoryIds: categoryIds
}
} }
console.log('【修改库位】处理后的物料数据:', {
materialCodes: this.form.materialCodes,
materialNames: this.form.materialNames,
categoryIds: this.form.allowedCategoryIds
})
this.open = true this.open = true
this.title = "修改库位" this.title = "修改库位"
} catch (error) { } catch (error) {
console.error('获取库位详情失败:', error) console.error('【修改库位】获取库位详情失败:', error)
this.$modal.msgError('获取数据失败,请重试!') this.$modal.msgError('获取数据失败,请重试!')
} }
}, },
// 提交表单 - 适配后端的warehousesId参数 // 提交表单
submitForm() { submitForm() {
console.log('【提交表单】开始验证表单,当前表单数据:', this.form)
this.$refs["form"].validate(valid => { this.$refs["form"].validate(valid => {
if (valid) { if (valid) {
// 处理物料编码和名称 console.log('【提交表单】表单验证通过,开始格式化数据')
if (this.form.materialCodes) { // 格式化物料相关字段(去重、过滤空值)
this.form.materialCodes = this.form.materialCodes.split(',').filter(code => code.trim()).join(',') const formatField = (value) => {
} if (!value) return ''
if (this.form.materialNames) { const result = value.split(',')
this.form.materialNames = this.form.materialNames.split(',').filter(name => name.trim()).join(',') .filter(item => item && item.trim())
.filter((item, index, self) => self.indexOf(item) === index)
.join(',')
console.log(`【提交表单】格式化字段值 "${value}" 结果: "${result}"`)
return result
} }
// 转换表单数据:将前端的warehouseId映射为后端需要的warehousesId this.form.materialCodes = formatField(this.form.materialCodes)
this.form.materialNames = formatField(this.form.materialNames)
this.form.allowedCategoryIds = formatField(this.form.allowedCategoryIds)
this.form.allowedCategoryNames = formatField(this.form.allowedCategoryNames)
// 转换表单数据
const submitData = { const submitData = {
...this.form, ...this.form,
warehousesId: this.form.warehouseId, // 新增:传递warehousesId给后端 warehousesId: this.form.warehouseId,
warehouseId: undefined, // 移除:避免重复传参 warehouseId: undefined,
warehouseName: undefined // 移除:只传ID给后端 warehouseName: undefined
} }
console.log('【提交表单】最终提交数据:', submitData)
const request = this.form.id != null ? updateLocations(submitData) : addLocations(submitData) const request = this.form.id != null ? updateLocations(submitData) : addLocations(submitData)
request.then(response => { request.then(response => {
console.log('【提交表单】请求成功:', response)
this.$modal.msgSuccess(this.form.id != null ? "修改成功" : "新增成功") this.$modal.msgSuccess(this.form.id != null ? "修改成功" : "新增成功")
this.open = false this.open = false
this.getList() this.getList()
}).catch(error => { }).catch(error => {
console.error('提交库位数据失败:', error) console.error('【提交表单】请求失败:', error)
this.$modal.msgError(this.form.id != null ? "修改失败" : "新增失败") this.$modal.msgError(this.form.id != null ? "修改失败" : "新增失败")
}) })
} else {
console.log('【提交表单】表单验证失败')
} }
}) })
}, },
// 删除库位 // 删除库位
handleDelete(row) { handleDelete(row) {
console.log('【删除库位】触发删除操作,行数据:', row)
const ids = row?.id ? [row.id] : this.ids const ids = row?.id ? [row.id] : this.ids
if (!ids || ids.length === 0) { if (!ids || ids.length === 0) {
this.$modal.msgWarning('请选择要删除的库位!') this.$modal.msgWarning('请选择要删除的库位!')
return return
} }
console.log('【删除库位】待删除ID:', ids)
this.$modal.confirm( this.$modal.confirm(
row?.id ? `是否确认删除库位编号为"${row.locationCode}"的数据项?` : `是否确认删除选中的${ids.length}条库位数据项?` row?.id ? `是否确认删除库位编号为"${row.locationCode}"的数据项?` : `是否确认删除选中的${ids.length}条库位数据项?`
).then(() => { ).then(() => {
console.log('【删除库位】用户确认删除,执行删除请求')
return delLocations(ids) return delLocations(ids)
}).then(() => { }).then(() => {
console.log('【删除库位】删除成功')
this.getList() this.getList()
this.$modal.msgSuccess("删除成功") this.$modal.msgSuccess("删除成功")
}).catch(() => {}) }).catch(() => {
console.log('【删除库位】用户取消删除或请求失败')
})
}, },
// 导出库位 - 适配后端的warehousesId参数 // 导出库位
handleExport() { handleExport() {
// 转换导出参数:将前端的warehouseId映射为后端需要的warehousesId console.log('【导出库位】执行导出操作,查询参数:', this.queryParams)
const exportParams = { const exportParams = {
...this.queryParams, ...this.queryParams,
warehousesId: this.queryParams.warehouseId, warehousesId: this.queryParams.warehouseId,
warehouseId: undefined warehouseId: undefined
} }
console.log('【导出库位】最终导出参数:', exportParams)
this.download('inventory/locations/export', exportParams, `locations_${new Date().getTime()}.xlsx`) this.download('inventory/locations/export', exportParams, `locations_${new Date().getTime()}.xlsx`)
}, },
// 物料选择变化 // 物料选择变化 - 优化数据处理
handleMaterialSelectionChange(selectedData) { handleMaterialSelectionChange(selectedData) {
console.log('【物料选择变化】接收到的选择数据:', selectedData)
// 修复:从selectedData中取materialIds(而非materialCodes)
const materialCodes = (selectedData.materialIds || [])
.filter(code => code && code.trim())
.map(code => code.trim().toUpperCase())
.filter((code, index, self) => self.indexOf(code) === index)
// 物料名称取selectedData.names
const names = (selectedData.names || [])
.filter(name => name && name.trim())
.filter((name, index, self) => self.indexOf(name) === index)
// 分类ID取selectedData.categoryIds
const categoryIds = (selectedData.categoryIds || [])
.filter(id => id && id.trim())
.filter((id, index, self) => self.indexOf(id) === index)
this.tempSelectedMaterials = { this.tempSelectedMaterials = {
materialCodes: selectedData.materialCodes || [], materialCodes, // 保持变量名不变(后续逻辑依赖)
names: selectedData.names || [], names,
categoryIds: selectedData.formattedCategoryIds || [] categoryIds
} }
console.log('【物料选择变化】处理后的临时选择数据:', this.tempSelectedMaterials)
}, },
// 取消物料选择 // 取消物料选择
handleMaterialSelectionCancel() { handleMaterialSelectionCancel() {
console.log('【取消物料选择】执行取消操作,恢复原有选择状态')
this.showMaterialSelect = false this.showMaterialSelect = false
// 恢复原有选择状态
this.tempSelectedMaterials = { this.tempSelectedMaterials = {
materialCodes: this.form.materialCodes ? this.form.materialCodes.split(',').filter(u => u.trim()) : [], materialCodes: this.form.materialCodes ? this.form.materialCodes.split(',').filter(u => u.trim()) : [],
names: this.form.materialNames ? this.form.materialNames.split(',').filter(n => n.trim()) : [], names: this.form.materialNames ? this.form.materialNames.split(',').filter(n => n.trim()) : [],
categoryIds: this.form.allowedCategoryIds ? this.form.allowedCategoryIds.split(',').filter(c => c.trim()) : [] categoryIds: this.form.allowedCategoryIds ? this.form.allowedCategoryIds.split(',').filter(c => c.trim()) : []
} }
console.log('【取消物料选择】恢复后的临时选择数据:', this.tempSelectedMaterials)
}, },
// 确认物料选择 // 确认物料选择 - 优化数据格式化
confirmMaterialSelection() { confirmMaterialSelection() {
console.log('【确认物料选择】当前临时选择数据:', this.tempSelectedMaterials)
// 修复:判断tempSelectedMaterials.materialCodes是否有值
if (!this.tempSelectedMaterials.materialCodes.length) { if (!this.tempSelectedMaterials.materialCodes.length) {
console.warn('【确认物料选择】未选择任何物料,提示用户')
this.$modal.msgWarning('请至少选择一个物料!') this.$modal.msgWarning('请至少选择一个物料!')
return return
} }
// 更新表单数据(确保去重和过滤)
this.form.materialCodes = this.tempSelectedMaterials.materialCodes.join(',') this.form.materialCodes = this.tempSelectedMaterials.materialCodes.join(',')
this.form.materialNames = this.tempSelectedMaterials.names.join(',') this.form.materialNames = this.tempSelectedMaterials.names.join(',')
this.form.allowedCategoryIds = this.tempSelectedMaterials.categoryIds.join(',') this.form.allowedCategoryIds = this.tempSelectedMaterials.categoryIds.join(',')
if (this.$refs.materialsSeletor) { // 生成分类名称
if (this.$refs.materialsSeletor && this.tempSelectedMaterials.categoryIds.length) {
const categoryNames = this.tempSelectedMaterials.categoryIds.map(code => { const categoryNames = this.tempSelectedMaterials.categoryIds.map(code => {
const rawCode = code.replace(/-/g, '') const rawCode = code.replace(/-/g, '')
return this.$refs.materialsSeletor.categoryMap[rawCode] || code return this.$refs.materialsSeletor.categoryMap?.[rawCode] || code
}) }).filter(name => name && name.trim())
this.form.allowedCategoryNames = categoryNames.join(',') this.form.allowedCategoryNames = categoryNames.join(',')
console.log('【确认物料选择】生成的分类名称:', categoryNames)
} }
console.log('【确认物料选择】更新后的表单物料数据:', {
materialCodes: this.form.materialCodes,
materialNames: this.form.materialNames,
allowedCategoryIds: this.form.allowedCategoryIds,
allowedCategoryNames: this.form.allowedCategoryNames
})
this.showMaterialSelect = false this.showMaterialSelect = false
this.$modal.msgSuccess(`成功选择 ${this.tempSelectedMaterials.names.length} 个物料`) this.$modal.msgSuccess(`成功选择 ${this.tempSelectedMaterials.names.length} 个物料`)
}, },
// 导入库位 - 集成货主页面的导入逻辑 // 导入库位
handleImport() { handleImport() {
console.log('【导入库位】打开导入组件')
this.$refs.import.show() this.$refs.import.show()
}, },
// 重置表单 // 重置表单
reset() { reset() {
console.log('【重置表单】执行表单重置')
this.form = { this.form = {
id: null, id: null,
locationCode: null, locationCode: null,
...@@ -1129,7 +1261,6 @@ export default { ...@@ -1129,7 +1261,6 @@ export default {
isEnabled: 1, isEnabled: 1,
isUsed: 1, isUsed: 1,
sortNo: 0, sortNo: 0,
// 重置新增的表单字段
putawayOrder: null, putawayOrder: null,
pickingOrder: null, pickingOrder: null,
locationUsage: null, locationUsage: null,
...@@ -1147,10 +1278,12 @@ export default { ...@@ -1147,10 +1278,12 @@ export default {
if (this.$refs.form) { if (this.$refs.form) {
this.$refs.form.resetFields() this.$refs.form.resetFields()
} }
console.log('【重置表单】重置完成,表单数据:', this.form)
}, },
// 取消操作 // 取消操作
cancel() { cancel() {
console.log('【取消操作】关闭弹窗并重置表单')
this.open = false this.open = false
this.reset() this.reset()
} }
......
...@@ -83,7 +83,6 @@ ...@@ -83,7 +83,6 @@
<el-table-column prop="outboundOrderId" label="出库单号" width="150" /> <el-table-column prop="outboundOrderId" label="出库单号" width="150" />
<el-table-column prop="warehousesName" label="仓库名称" width="120" /> <el-table-column prop="warehousesName" label="仓库名称" width="120" />
<el-table-column prop="locationName" label="库位名称" width="120" /> <el-table-column prop="locationName" label="库位名称" width="120" />
<el-table-column prop="locationId" label="库位ID" width="140" />
<el-table-column <el-table-column
prop="inventoryType" prop="inventoryType"
label="库存类型" label="库存类型"
...@@ -146,7 +145,7 @@ ...@@ -146,7 +145,7 @@
v-for="color in dict.type.label_color" v-for="color in dict.type.label_color"
:key="color.value" :key="color.value"
:label="color.label" :label="color.label"
:value="color.value" :value="Number(color.value)"
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
...@@ -230,7 +229,6 @@ ...@@ -230,7 +229,6 @@
<el-table-column prop="batchId" label="批次ID" width="150" /> <el-table-column prop="batchId" label="批次ID" width="150" />
<el-table-column prop="warehousesName" label="仓库名称" width="120" /> <el-table-column prop="warehousesName" label="仓库名称" width="120" />
<el-table-column prop="locationName" label="库位名称" width="120" /> <el-table-column prop="locationName" label="库位名称" width="120" />
<el-table-column prop="locationId" label="库位ID" width="140" />
<el-table-column prop="plannedQuantity" label="计划数量" width="100" /> <el-table-column prop="plannedQuantity" label="计划数量" width="100" />
<el-table-column prop="actualQuantity" label="实际数量" width="100" /> <el-table-column prop="actualQuantity" label="实际数量" width="100" />
<el-table-column prop="unitPrice" label="单价" width="100" /> <el-table-column prop="unitPrice" label="单价" width="100" />
......
...@@ -74,10 +74,10 @@ ...@@ -74,10 +74,10 @@
@keyup.enter.native="handleQuery" @keyup.enter.native="handleQuery"
/> />
</el-form-item> </el-form-item>
<el-form-item label="库类型" prop="orderTypeId"> <el-form-item label="库类型" prop="orderTypeId">
<el-input <el-input
v-model="queryParams.orderTypeId" v-model="queryParams.orderTypeId"
placeholder="请输入库类型" placeholder="请输入库类型"
clearable clearable
@keyup.enter.native="handleQuery" @keyup.enter.native="handleQuery"
/> />
...@@ -192,7 +192,7 @@ ...@@ -192,7 +192,7 @@
<el-table-column type="selection" width="55" align="center" fixed /> <el-table-column type="selection" width="55" align="center" fixed />
<el-table-column label="出库单号" align="center" prop="orderId" width="150" fixed/> <el-table-column label="出库单号" align="center" prop="orderId" width="150" fixed/>
<el-table-column label="系统编号" align="center" prop="systemNo" width="150" /> <el-table-column label="系统编号" align="center" prop="systemNo" width="150" />
<el-table-column label="库类型" align="center" prop="orderTypeId" width="120"> <el-table-column label="库类型" align="center" prop="orderTypeId" width="120">
<template slot-scope="scope"> <template slot-scope="scope">
<dict-tag v-if="dict.type.outbound_order_type" :options="dict.type.outbound_order_type" :value="scope.row.orderTypeId"/> <dict-tag v-if="dict.type.outbound_order_type" :options="dict.type.outbound_order_type" :value="scope.row.orderTypeId"/>
<span v-else>-</span> <span v-else>-</span>
...@@ -201,7 +201,7 @@ ...@@ -201,7 +201,7 @@
<!-- 新增:订单类型列 --> <!-- 新增:订单类型列 -->
<el-table-column label="订单类型" align="center" prop="orderType" width="120"> <el-table-column label="订单类型" align="center" prop="orderType" width="120">
<template slot-scope="scope"> <template slot-scope="scope">
<dict-tag v-if="dict.type.outbound_order_type" :options="dict.type.outbound_order_type" :value="scope.row.orderType"/> <dict-tag v-if="dict.type.order_type" :options="dict.type.order_type" :value="scope.row.orderType"/>
<span v-else>-</span> <span v-else>-</span>
</template> </template>
</el-table-column> </el-table-column>
...@@ -299,7 +299,7 @@ ...@@ -299,7 +299,7 @@
<el-form-item label="入库类型" prop="orderTypeId"> <el-form-item label="入库类型" prop="orderTypeId">
<el-select v-model="form.orderTypeId" placeholder="请选择入库类型" :disabled="isViewDetail || formDisabled.orderTypeId" style="width: 100%"> <el-select v-model="form.orderTypeId" placeholder="请选择入库类型" :disabled="isViewDetail || formDisabled.orderTypeId" style="width: 100%">
<el-option <el-option
v-for="item in dict.type.inbound_order_type" v-for="item in dict.type.outbound_order_type"
:key="item.value" :key="item.value"
:label="item.label" :label="item.label"
:value="item.value" :value="item.value"
...@@ -314,7 +314,7 @@ ...@@ -314,7 +314,7 @@
<el-form-item label="订单类型" prop="orderType"> <el-form-item label="订单类型" prop="orderType">
<el-select v-model="form.orderType" placeholder="请选择订单类型" :disabled="isViewDetail || formDisabled.orderType" style="width: 100%"> <el-select v-model="form.orderType" placeholder="请选择订单类型" :disabled="isViewDetail || formDisabled.orderType" style="width: 100%">
<el-option <el-option
v-for="item in dict.type.outbound_order_type" v-for="item in dict.type.order_type"
:key="item.value" :key="item.value"
:label="item.label" :label="item.label"
:value="item.value" :value="item.value"
...@@ -518,9 +518,12 @@ ...@@ -518,9 +518,12 @@
ref="import" ref="import"
title="导入" title="导入"
import-url="/inventory/orders/import" import-url="/inventory/orders/import"
template-url="inventory/orders/importTemplate" template-url="/inventory/orders/importTemplate"
template-name="owners_importTemplate" template-name="入库单导入模板"
@success="getList" @success="getList"
:show-trdc-checkbox="true"
@orderTypeChange="handleOrderTypeChange"
:orderTypeRequired="true"
/> />
</div> </div>
</template> </template>
...@@ -534,10 +537,11 @@ import WarehouseSelector from "@/views/compononents/WarehouseSelector.vue" ...@@ -534,10 +537,11 @@ import WarehouseSelector from "@/views/compononents/WarehouseSelector.vue"
import LocationSelector from "@/views/compononents/LocationSelector.vue" import LocationSelector from "@/views/compononents/LocationSelector.vue"
import OwnerSelector from "@/views/compononents/OwnerSelector.vue" import OwnerSelector from "@/views/compononents/OwnerSelector.vue"
import PageTitle from "@/components/PageTitle" import PageTitle from "@/components/PageTitle"
import ImportExcel from "@/components/ImportExcel/index" import ImportExcel from "@/components/ImportExcel/index"
export default { export default {
name: "Orders", name: "Orders",
dicts: ['outbound_order_type', 'inbound_order_type', 'inbound_order_status', 'label_color'], dicts: ['outbound_order_type', 'inbound_order_type', 'inbound_order_status', 'label_color','order_type'],
components: { components: {
OutboundOrderFormWithItems, OutboundOrderFormWithItems,
WarehouseSelector, WarehouseSelector,
...@@ -677,6 +681,9 @@ export default { ...@@ -677,6 +681,9 @@ export default {
}, },
methods: { methods: {
handleOrderTypeChange(selection) {
this.form.orderTypeId = selection
},
/** 打开导入弹窗 */ /** 打开导入弹窗 */
handleImport() { handleImport() {
this.$refs.import.show() this.$refs.import.show()
...@@ -934,8 +941,7 @@ handleOwnerSelected(owner) { ...@@ -934,8 +941,7 @@ handleOwnerSelected(owner) {
this.detailDialogOpen = true this.detailDialogOpen = true
}) })
}, },
// 修复:接收子组件提交的明细数据 handleDetailSubmit(details) {
handleDetailSubmit(details) {
// 确保是数组格式 // 确保是数组格式
const detailList = Array.isArray(details) ? details : [details]; const detailList = Array.isArray(details) ? details : [details];
if (detailList.length === 0) { if (detailList.length === 0) {
...@@ -983,7 +989,8 @@ handleOwnerSelected(owner) { ...@@ -983,7 +989,8 @@ handleOwnerSelected(owner) {
sortNo: 0, sortNo: 0,
remark: item.remark || '', remark: item.remark || '',
warehouseName: item.warehouseName || this.form.warehouseName || '', warehouseName: item.warehouseName || this.form.warehouseName || '',
locationName: item.locationName || '' locationName: item.locationName || '',
batchCode: item.batchId || '' // 新增:将子组件的batchId赋值给batchCode
}; };
}); });
...@@ -1019,7 +1026,8 @@ handleOwnerSelected(owner) { ...@@ -1019,7 +1026,8 @@ handleOwnerSelected(owner) {
sortNo: 0, sortNo: 0,
remark: item.remark || '', remark: item.remark || '',
warehouseName: item.warehouseName || this.form.warehouseName || '', warehouseName: item.warehouseName || this.form.warehouseName || '',
locationName: item.locationName || '' locationName: item.locationName || '',
batchCode: item.batchId || '' // 新增:将子组件的batchId赋值给batchCode
}; };
}); });
...@@ -1042,7 +1050,7 @@ handleOwnerSelected(owner) { ...@@ -1042,7 +1050,7 @@ handleOwnerSelected(owner) {
this.detailDialogOpen = false; this.detailDialogOpen = false;
// 强制更新视图 // 强制更新视图
this.$forceUpdate(); this.$forceUpdate();
}, },
// 计算主表总数量和总金额 // 计算主表总数量和总金额
calcTotalQuantity() { calcTotalQuantity() {
let totalPlanned = 0 let totalPlanned = 0
......
...@@ -158,12 +158,12 @@ public class OutboundOrdersController extends BaseController ...@@ -158,12 +158,12 @@ public class OutboundOrdersController extends BaseController
@PreAuthorize("@ss.hasPermi('inventory:inbound:import')") @PreAuthorize("@ss.hasPermi('inventory:inbound:import')")
@Log(title = "入库信息导入", businessType = BusinessType.IMPORT) @Log(title = "入库信息导入", businessType = BusinessType.IMPORT)
@PostMapping("/import") @PostMapping("/import")
public AjaxResult importTemplate(MultipartFile file , boolean updateSupport) throws Exception public AjaxResult importTemplate(MultipartFile file , boolean updateSupport,Integer orderType) throws Exception
{ {
ExcelUtil<OutboundTemplateVO> util = new ExcelUtil<OutboundTemplateVO>(OutboundTemplateVO.class); ExcelUtil<OutboundTemplateVO> util = new ExcelUtil<OutboundTemplateVO>(OutboundTemplateVO.class);
List<OutboundTemplateVO> inboundOrders = util.importExcel(file.getInputStream()); List<OutboundTemplateVO> inboundOrders = util.importExcel(file.getInputStream());
String operName = getUsername(); String operName = getUsername();
String message = outboundOrdersService.importOutboundOrders(inboundOrders, updateSupport, operName); String message = outboundOrdersService.importOutboundOrders(inboundOrders, updateSupport, operName,orderType);
return success(message); return success(message);
} }
} }
...@@ -125,7 +125,13 @@ public class Inventory extends BaseEntity ...@@ -125,7 +125,13 @@ public class Inventory extends BaseEntity
/** 预警类型 */ /** 预警类型 */
private String alertType; private String alertType;
public String getWarehousesId() {
return warehousesId;
}
public void setWarehousesId(String warehousesId) {
this.warehousesId = warehousesId;
}
/** 最低库存 */ /** 最低库存 */
private Long minStockLevel; private Long minStockLevel;
......
...@@ -68,7 +68,6 @@ public class InboundOutboundStatisticsVO extends BaseEntity { ...@@ -68,7 +68,6 @@ public class InboundOutboundStatisticsVO extends BaseEntity {
/** 库位ID */ /** 库位ID */
private String locationId; private String locationId;
/** 物料编码/ID查询 */ /** 物料编码/ID查询 */
private String materialCode; private String materialCode;
......
...@@ -3,6 +3,7 @@ package com.ruoyi.inventory.domain.vo; ...@@ -3,6 +3,7 @@ package com.ruoyi.inventory.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel; import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity; import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.commons.lang3.builder.ToStringStyle;
...@@ -15,6 +16,7 @@ import java.util.Date; ...@@ -15,6 +16,7 @@ import java.util.Date;
* @author ruoyi * @author ruoyi
* @date 2025-12-10 * @date 2025-12-10
*/ */
@Data
public class OutboundOrdersSummaryVO extends BaseEntity public class OutboundOrdersSummaryVO extends BaseEntity
{ {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
...@@ -56,6 +58,9 @@ public class OutboundOrdersSummaryVO extends BaseEntity ...@@ -56,6 +58,9 @@ public class OutboundOrdersSummaryVO extends BaseEntity
@Excel(name = "包装重量") @Excel(name = "包装重量")
private BigDecimal packageWeight; private BigDecimal packageWeight;
private String itemStatus;
private String unitPrice;
/** 总重量 */ /** 总重量 */
@Excel(name = "总重量") @Excel(name = "总重量")
private BigDecimal totalWeight; private BigDecimal totalWeight;
...@@ -124,265 +129,10 @@ public class OutboundOrdersSummaryVO extends BaseEntity ...@@ -124,265 +129,10 @@ public class OutboundOrdersSummaryVO extends BaseEntity
@JsonFormat(pattern = "yyyy-MM-dd") @JsonFormat(pattern = "yyyy-MM-dd")
private Date endDate; private Date endDate;
/** 订单状态(检索条件) */
@Excel(name = "订单状态 字典,检索条件")
private Long orderStatus;
/** 库位ID(检索条件) */ /** 库位ID(检索条件) */
@Excel(name = "库位ID 检索条件") @Excel(name = "库位ID 检索条件")
private String locationId; private String locationId;
// ========== Getter & Setter 方法 ========== private String locationName;
public String getMaterialId() {
return materialId;
}
public void setMaterialId(String materialId) {
this.materialId = materialId;
}
public String getMaterialName() {
return materialName;
}
public void setMaterialName(String materialName) {
this.materialName = materialName;
}
public String getSapNo() {
return sapNo;
}
public void setSapNo(String sapNo) {
this.sapNo = sapNo;
}
public String getTsCode() {
return tsCode;
}
public void setTsCode(String tsCode) {
this.tsCode = tsCode;
}
public String getHazardId() {
return hazardId;
}
public void setHazardId(String hazardId) {
this.hazardId = hazardId;
}
public String getSpecification() {
return specification;
}
public void setSpecification(String specification) {
this.specification = specification;
}
public String getMaterialUnit() {
return materialUnit;
}
public void setMaterialUnit(String materialUnit) {
this.materialUnit = materialUnit;
}
public BigDecimal getUnitWeight() {
return unitWeight;
}
public void setUnitWeight(BigDecimal unitWeight) {
this.unitWeight = unitWeight;
}
public BigDecimal getPackageWeight() {
return packageWeight;
}
public void setPackageWeight(BigDecimal packageWeight) {
this.packageWeight = packageWeight;
}
public BigDecimal getTotalWeight() {
return totalWeight;
}
public void setTotalWeight(BigDecimal totalWeight) {
this.totalWeight = totalWeight;
}
public BigDecimal getVolume() {
return volume;
}
public void setVolume(BigDecimal volume) {
this.volume = volume;
}
public Long getShelfLifeDays() {
return shelfLifeDays;
}
public void setShelfLifeDays(Long shelfLifeDays) {
this.shelfLifeDays = shelfLifeDays;
}
public String getStorageTemperature() {
return storageTemperature;
}
public void setStorageTemperature(String storageTemperature) {
this.storageTemperature = storageTemperature;
}
public String getSpecialRequirements() {
return specialRequirements;
}
public void setSpecialRequirements(String specialRequirements) {
this.specialRequirements = specialRequirements;
}
public Long getSortNo() {
return sortNo;
}
public void setSortNo(Long sortNo) {
this.sortNo = sortNo;
}
public BigDecimal getPlannedQuantity() {
return plannedQuantity;
}
public void setPlannedQuantity(BigDecimal plannedQuantity) {
this.plannedQuantity = plannedQuantity;
}
public BigDecimal getActualQuantity() {
return actualQuantity;
}
public void setActualQuantity(BigDecimal actualQuantity) {
this.actualQuantity = actualQuantity;
}
public BigDecimal getTotalAmount() {
return totalAmount;
}
public void setTotalAmount(BigDecimal totalAmount) {
this.totalAmount = totalAmount;
}
public String getWarehouseId() {
return warehouseId;
}
public void setWarehouseId(String warehouseId) {
this.warehouseId = warehouseId;
}
public String getWarehouseName() {
return warehouseName;
}
public void setWarehouseName(String warehouseName) {
this.warehouseName = warehouseName;
}
public String getBatchCode() {
return batchCode;
}
public void setBatchCode(String batchCode) {
this.batchCode = batchCode;
}
public String getOrderId() {
return orderId;
}
public void setOrderId(String orderId) {
this.orderId = orderId;
}
public String getMainOrderId() {
return mainOrderId;
}
public void setMainOrderId(String mainOrderId) {
this.mainOrderId = mainOrderId;
}
public Date getStartDate() {
return startDate;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
public Date getEndDate() {
return endDate;
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
public Long getOrderStatus() {
return orderStatus;
}
public void setOrderStatus(Long orderStatus) {
this.orderStatus = orderStatus;
}
public String getLocationId() {
return locationId;
}
public void setLocationId(String locationId) {
this.locationId = locationId;
}
// ========== ToString 方法 ==========
@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
.append("materialId", getMaterialId())
.append("materialName", getMaterialName())
.append("sapNo", getSapNo())
.append("tsCode", getTsCode())
.append("hazardId", getHazardId())
.append("specification", getSpecification())
.append("materialUnit", getMaterialUnit())
.append("unitWeight", getUnitWeight())
.append("packageWeight", getPackageWeight())
.append("totalWeight", getTotalWeight())
.append("volume", getVolume())
.append("shelfLifeDays", getShelfLifeDays())
.append("storageTemperature", getStorageTemperature())
.append("specialRequirements", getSpecialRequirements())
.append("sortNo", getSortNo())
.append("plannedQuantity", getPlannedQuantity())
.append("actualQuantity", getActualQuantity())
.append("totalAmount", getTotalAmount())
.append("warehouseId", getWarehouseId())
.append("warehouseName", getWarehouseName())
.append("batchCode", getBatchCode())
.append("orderId", getOrderId())
.append("mainOrderId", getMainOrderId())
.append("startDate", getStartDate())
.append("endDate", getEndDate())
.append("orderStatus", getOrderStatus())
.append("locationId", getLocationId())
.append("remark", getRemark())
.append("createTime", getCreateTime())
.append("updateTime", getUpdateTime())
.toString();
}
} }
\ No newline at end of file
...@@ -46,6 +46,6 @@ public class StorageLocationsLocationTemplateVO { ...@@ -46,6 +46,6 @@ public class StorageLocationsLocationTemplateVO {
@Excel(name = "允许混放产品",dictType="yorn") @Excel(name = "允许混放产品",dictType="yorn")
private String allowMixedProducts; private String allowMixedProducts;
@Excel(name = "允许混放批次") @Excel(name = "允许混放批次",dictType="yorn")
private String allowMixedBatches; private String allowMixedBatches;
} }
\ No newline at end of file
...@@ -78,5 +78,5 @@ public interface IOutboundOrdersService ...@@ -78,5 +78,5 @@ public interface IOutboundOrdersService
public String outboundOrdersCount(); public String outboundOrdersCount();
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
String importOutboundOrders(List<OutboundTemplateVO> inboundOrdersList, Boolean isUpdateSupport, String operName); String importOutboundOrders(List<OutboundTemplateVO> inboundOrdersList, Boolean isUpdateSupport, String operName,Integer orderType);
} }
...@@ -252,7 +252,7 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService ...@@ -252,7 +252,7 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
@Override @Override
public String importOutboundOrders(List<OutboundTemplateVO> inboundOrdersList, Boolean isUpdateSupport, String operName) { public String importOutboundOrders(List<OutboundTemplateVO> inboundOrdersList, Boolean isUpdateSupport, String operName,Integer orderType) {
// 1. 基础空值校验(完全保留你的代码) // 1. 基础空值校验(完全保留你的代码)
if (CollectionUtils.isEmpty(inboundOrdersList)) { if (CollectionUtils.isEmpty(inboundOrdersList)) {
throw new ServiceException("导入数据不能为空!"); throw new ServiceException("导入数据不能为空!");
...@@ -348,6 +348,7 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService ...@@ -348,6 +348,7 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
mainDO.setOrderStatus(3L); mainDO.setOrderStatus(3L);
mainDO.setCreateBy(operId); mainDO.setCreateBy(operId);
mainDO.setCreateTime(now); mainDO.setCreateTime(now);
mainDO.setOrderType(Long.valueOf(orderType));
mainDO.setCreateUserCode(operId); mainDO.setCreateUserCode(operId);
mainDO.setUpdateBy(operId); mainDO.setUpdateBy(operId);
mainDO.setUpdateTime(now); mainDO.setUpdateTime(now);
......
...@@ -270,6 +270,7 @@ public class StorageLocationsServiceImpl implements IStorageLocationsService ...@@ -270,6 +270,7 @@ public class StorageLocationsServiceImpl implements IStorageLocationsService
storageLocations.setCreateBy(operId); storageLocations.setCreateBy(operId);
storageLocations.setCreateTime(now); storageLocations.setCreateTime(now);
storageLocations.setCreateUserCode(operId); storageLocations.setCreateUserCode(operId);
storageLocations.setWarehousesId("572ba484-199c-45d9-9735-610928ed5c70");
// 设置默认值 // 设置默认值
if (storageLocations.getIsUsed() == null) { if (storageLocations.getIsUsed() == null) {
......
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper <!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.inventory.mapper.InventoryMapper"> <mapper namespace="com.ruoyi.inventory.mapper.InventoryMapper">
<resultMap type="Inventory" id="InventoryResult"> <resultMap type="Inventory" id="InventoryResult">
...@@ -44,7 +44,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" ...@@ -44,7 +44,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="unitWeight" column="unit_weight" /> <result property="unitWeight" column="unit_weight" />
<result property="packageWeight" column="package_weight" /> <result property="packageWeight" column="package_weight" />
<result property="totalWeight" column="total_weight" /> <result property="totalWeight" column="total_weight" />
<result property="volume" column="volume" />
<result property="shelfLifeDays" column="shelf_life_days" /> <result property="shelfLifeDays" column="shelf_life_days" />
<result property="storageTemperature" column="storage_temperature" /> <result property="storageTemperature" column="storage_temperature" />
<result property="specialRequirements" column="special_requirements" /> <result property="specialRequirements" column="special_requirements" />
...@@ -89,6 +88,52 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" ...@@ -89,6 +88,52 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="unitPrice" column="unit_price" /> <result property="unitPrice" column="unit_price" />
</resultMap> </resultMap>
<resultMap type="com.ruoyi.inventory.domain.vo.InventoryVo" id="InventoryVoResult">
<result property="id" column="id" />
<result property="inventoryType" column="inventory_type" />
<result property="orderId" column="order_id" />
<result property="materialId" column="material_id" />
<result property="batchId" column="batch_id" />
<result property="warehousesCode" column="warehouses_code" />
<result property="locationId" column="location_id" />
<result property="ownerId" column="owner_id" />
<result property="quantity" column="quantity" />
<result property="lockedQuantity" column="locked_quantity" />
<result property="unitWeight" column="unit_weight" />
<result property="totalWeight" column="total_weight" />
<result property="totalVolume" column="total_volume" />
<result property="productionDate" column="production_date" />
<result property="expirationDate" column="expiration_date" />
<result property="inventoryStatus" column="inventory_status" />
<result property="lastInboundTime" column="last_inbound_time" />
<result property="lastOutboundTime" column="last_outbound_time" />
<result property="isUsed" column="is_used" />
<result property="sortNo" column="sort_no" />
<result property="createTime" column="create_time" />
<result property="createUserCode" column="create_user_code" />
<result property="updateTime" column="update_time" />
<result property="updateUserCode" column="update_user_code" />
<result property="warehousesId" column="warehouses_id" />
<result property="materialName" column="material_name" />
<result property="minStockLevel" column="min_stock_level" jdbcType="BIGINT"/>
<result property="maxStockLevel" column="max_stock_level" jdbcType="BIGINT"/>
<result property="sapNo" column="sap_no" />
<result property="tsCode" column="ts_code" />
<result property="hazardId" column="hazard_id" />
<result property="specification" column="specification" />
<result property="materialUnit" column="material_unit" />
<result property="unitWeight" column="unit_weight" />
<result property="packageWeight" column="package_weight" />
<result property="totalWeight" column="total_weight" />
<result property="shelfLifeDays" column="shelf_life_days" />
<result property="storageTemperature" column="storage_temperature" />
<result property="specialRequirements" column="special_requirements" />
<result property="alterType" column="alterType" />
<result property="warehousesName" column="warehouses_name" />
<result property="locationName" column="location_name" />
<result property="ownerName" column="owner_name" />
</resultMap>
<resultMap type="com.ruoyi.inventory.domain.vo.InventorySummaryVO" id="InventorySummaryResult"> <resultMap type="com.ruoyi.inventory.domain.vo.InventorySummaryVO" id="InventorySummaryResult">
<result property="materialId" column="material_id" /> <result property="materialId" column="material_id" />
<result property="materialName" column="material_name" /> <result property="materialName" column="material_name" />
...@@ -102,7 +147,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" ...@@ -102,7 +147,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="unitWeight" column="unit_weight" /> <result property="unitWeight" column="unit_weight" />
<result property="packageWeight" column="package_weight" /> <result property="packageWeight" column="package_weight" />
<result property="totalWeight" column="total_weight" /> <result property="totalWeight" column="total_weight" />
<result property="volume" column="volume" />
<result property="shelfLifeDays" column="shelf_life_days" /> <result property="shelfLifeDays" column="shelf_life_days" />
<result property="storageTemperature" column="storage_temperature" /> <result property="storageTemperature" column="storage_temperature" />
<result property="specialRequirements" column="special_requirements" /> <result property="specialRequirements" column="special_requirements" />
...@@ -157,7 +201,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" ...@@ -157,7 +201,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
m.unit_weight, m.unit_weight,
m.package_weight, m.package_weight,
m.total_weight, m.total_weight,
m.volume,
m.shelf_life_days, m.shelf_life_days,
m.storage_temperature, m.storage_temperature,
m.special_requirements, m.special_requirements,
...@@ -193,7 +236,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" ...@@ -193,7 +236,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
m.unit_weight, m.unit_weight,
m.package_weight, m.package_weight,
m.total_weight, m.total_weight,
m.volume,
m.shelf_life_days, m.shelf_life_days,
m.storage_temperature, m.storage_temperature,
m.special_requirements ) tab m.special_requirements ) tab
...@@ -218,7 +260,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" ...@@ -218,7 +260,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="inventoryStatus != null "> and i.inventory_status = #{inventoryStatus}</if> <if test="inventoryStatus != null "> and i.inventory_status = #{inventoryStatus}</if>
<if test="isUsed != null "> and i.is_used = #{isUsed}</if> <if test="isUsed != null "> and i.is_used = #{isUsed}</if>
</where> </where>
i.material_id, m.material_name, m.sap_no, group by i.material_id, m.material_name, m.sap_no,
m.ts_code, m.ts_code,
m.hazard_id, m.hazard_id,
m.specification, m.specification,
...@@ -226,7 +268,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" ...@@ -226,7 +268,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
m.unit_weight, m.unit_weight,
m.package_weight, m.package_weight,
m.total_weight, m.total_weight,
m.volume,
m.shelf_life_days, m.shelf_life_days,
m.storage_temperature, m.storage_temperature,
m.special_requirements) tab m.special_requirements) tab
...@@ -268,7 +309,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" ...@@ -268,7 +309,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
m.unit_weight, m.unit_weight,
m.package_weight, m.package_weight,
m.total_weight, m.total_weight,
m.volume,
m.shelf_life_days, m.shelf_life_days,
m.storage_temperature, m.storage_temperature,
m.special_requirements, m.special_requirements,
...@@ -535,7 +575,7 @@ and inventory_status = '1' ...@@ -535,7 +575,7 @@ and inventory_status = '1'
#{id} #{id}
</foreach> </foreach>
</delete> </delete>
<!-- 库存物料超出预警值统计--> <!-- 库存物料超出预警值统计-->
<resultMap id="InventoryExceedWarnResultMap" type="com.ruoyi.inventory.domain.vo.InventoryExceedWarnVO"> <resultMap id="InventoryExceedWarnResultMap" type="com.ruoyi.inventory.domain.vo.InventoryExceedWarnVO">
<result column="material_name" property="materialName" jdbcType="VARCHAR"/> <result column="material_name" property="materialName" jdbcType="VARCHAR"/>
<result column="category_name" property="categoryName" jdbcType="VARCHAR"/> <result column="category_name" property="categoryName" jdbcType="VARCHAR"/>
......
...@@ -42,6 +42,12 @@ ...@@ -42,6 +42,12 @@
<result property="materialName" column="material_name" /> <result property="materialName" column="material_name" />
<result property="sapNo" column="sap_no" /> <result property="sapNo" column="sap_no" />
<result property="tsCode" column="ts_code" /> <result property="tsCode" column="ts_code" />
<result property="locationId" column="location_id" />
<result property="locationName" column="location_name" />
<result property="itemStatus" column="item_status" />
<result property="unitPrice" column="unit_price" />
<result property="hazardId" column="hazard_id" /> <result property="hazardId" column="hazard_id" />
<result property="specification" column="specification" /> <result property="specification" column="specification" />
<result property="materialUnit" column="material_unit" /> <result property="materialUnit" column="material_unit" />
...@@ -244,6 +250,8 @@ ...@@ -244,6 +250,8 @@
m.total_weight, m.total_weight,
m.volume, m.volume,
m.shelf_life_days, m.shelf_life_days,
oi.location_id,
sl.location_name as location_name,
m.storage_temperature, m.storage_temperature,
m.special_requirements, m.special_requirements,
m.sort_no, m.sort_no,
...@@ -254,7 +262,10 @@ ...@@ -254,7 +262,10 @@
w.warehouses_name as warehouse_name, w.warehouses_name as warehouse_name,
oi.batch_code, oi.batch_code,
oi.order_id, oi.order_id,
o.order_id as main_order_id oi.remark,
oi.unit_price,
o.order_id as main_order_id,
oi.item_status
from outbound_order_items oi from outbound_order_items oi
left join outbound_orders o on oi.outbound_order_id = o.id left join outbound_orders o on oi.outbound_order_id = o.id
left join materials m on oi.material_id = m.id left join materials m on oi.material_id = m.id
...@@ -269,7 +280,7 @@ ...@@ -269,7 +280,7 @@
<if test="endDate != null and endDate != ''"> and date_format(COALESCE(oi.shipped_at, o.inbound_date),'%Y-%m-%d') &lt;= #{endDate}</if> <if test="endDate != null and endDate != ''"> and date_format(COALESCE(oi.shipped_at, o.inbound_date),'%Y-%m-%d') &lt;= #{endDate}</if>
<if test="warehouseId != null and warehouseId != ''"> and oi.warehouse_id = #{warehouseId}</if> <if test="warehouseId != null and warehouseId != ''"> and oi.warehouse_id = #{warehouseId}</if>
<if test="locationId != null and locationId != ''"> and oi.location_id = #{locationId}</if> <if test="locationId != null and locationId != ''"> and oi.location_id = #{locationId}</if>
<if test="orderStatus != null "> and o.order_status = #{orderStatus}</if> <if test="itemStatus != null "> and oi.item_status = #{itemStatus}</if>
</where> </where>
group by oi.material_id, m.material_name, m.sap_no, group by oi.material_id, m.material_name, m.sap_no,
m.ts_code, m.ts_code,
......
...@@ -108,6 +108,8 @@ ...@@ -108,6 +108,8 @@
<if test="pickingArea != null and pickingArea != ''"> and sl.picking_area = #{pickingArea}</if> <if test="pickingArea != null and pickingArea != ''"> and sl.picking_area = #{pickingArea}</if>
<if test="allowMixedProducts != null "> and sl.allow_mixed_products = #{allowMixedProducts}</if> <if test="allowMixedProducts != null "> and sl.allow_mixed_products = #{allowMixedProducts}</if>
<if test="allowMixedBatches != null "> and sl.allow_mixed_batches = #{allowMixedBatches}</if> <if test="allowMixedBatches != null "> and sl.allow_mixed_batches = #{allowMixedBatches}</if>
<!-- 按sort_no降序排序 -->
order by sl.sort_no desc
</select> </select>
<!-- 关联仓库表的列表查询(简化) --> <!-- 关联仓库表的列表查询(简化) -->
...@@ -129,6 +131,8 @@ ...@@ -129,6 +131,8 @@
<if test="pickingArea != null and pickingArea != ''"> and sl.picking_area = #{pickingArea}</if> <if test="pickingArea != null and pickingArea != ''"> and sl.picking_area = #{pickingArea}</if>
<if test="allowMixedProducts != null "> and sl.allow_mixed_products = #{allowMixedProducts}</if> <if test="allowMixedProducts != null "> and sl.allow_mixed_products = #{allowMixedProducts}</if>
<if test="allowMixedBatches != null "> and sl.allow_mixed_batches = #{allowMixedBatches}</if> <if test="allowMixedBatches != null "> and sl.allow_mixed_batches = #{allowMixedBatches}</if>
<!-- 按sort_no降序排序 -->
order by sl.sort_no desc
</select> </select>
<!-- 根据ID查询(调整:保留where,单独条件) --> <!-- 根据ID查询(调整:保留where,单独条件) -->
...@@ -180,12 +184,16 @@ ...@@ -180,12 +184,16 @@
<select id="selectStorageLocationsByWarehousesCode" parameterType="String" resultMap="StorageLocationsResult"> <select id="selectStorageLocationsByWarehousesCode" parameterType="String" resultMap="StorageLocationsResult">
<include refid="selectStorageLocationsVo"/> <include refid="selectStorageLocationsVo"/>
and sl.warehouses_code = #{warehousesCode} and sl.warehouses_code = #{warehousesCode}
<!-- 按sort_no降序排序 -->
order by sl.sort_no desc
</select> </select>
<!-- 关联仓库表的仓库编码查询(简化) --> <!-- 关联仓库表的仓库编码查询(简化) -->
<select id="selectStorageLocationsByWarehousesCodeWithWarehouses" parameterType="String" resultMap="StorageLocationsWithWarehousesResult"> <select id="selectStorageLocationsByWarehousesCodeWithWarehouses" parameterType="String" resultMap="StorageLocationsWithWarehousesResult">
<include refid="selectStorageLocationsWithWarehousesVo"/> <include refid="selectStorageLocationsWithWarehousesVo"/>
and sl.warehouses_code = #{warehousesCode} and sl.warehouses_code = #{warehousesCode}
<!-- 按sort_no降序排序 -->
order by sl.sort_no desc
</select> </select>
<!-- 根据仓库编码列表查询(简化) --> <!-- 根据仓库编码列表查询(简化) -->
...@@ -195,6 +203,8 @@ ...@@ -195,6 +203,8 @@
<foreach item="id" collection="list" open="(" separator="," close=")"> <foreach item="id" collection="list" open="(" separator="," close=")">
#{id} #{id}
</foreach> </foreach>
<!-- 按sort_no降序排序 -->
order by sl.sort_no desc
</select> </select>
<!-- 关联仓库表的编码列表查询(简化) --> <!-- 关联仓库表的编码列表查询(简化) -->
...@@ -204,12 +214,16 @@ ...@@ -204,12 +214,16 @@
<foreach item="id" collection="list" open="(" separator="," close=")"> <foreach item="id" collection="list" open="(" separator="," close=")">
#{id} #{id}
</foreach> </foreach>
<!-- 按sort_no降序排序 -->
order by sl.sort_no desc
</select> </select>
<!-- 获取库位表 的 location_code 编码 location_name 做成字典--> <!-- 获取库位表 的 location_code 编码 location_name 做成字典-->
<select id="getMapList" parameterType="StorageLocations" resultType="java.util.Map"> <select id="getMapList" parameterType="StorageLocations" resultType="java.util.Map">
select id, IFNULL(location_name, '') as location_name from storage_locations where is_used = 1 select id, IFNULL(location_name, '') as location_name from storage_locations where is_used = 1
<if test="warehousesCode != null and warehousesCode != ''"> and warehouses_id = #{warehousesCode}</if> <if test="warehousesCode != null and warehousesCode != ''"> and warehouses_id = #{warehousesCode}</if>
<!-- 按sort_no降序排序 -->
order by sort_no desc
</select> </select>
<!-- 关联仓库的字典查询 --> <!-- 关联仓库的字典查询 -->
...@@ -219,6 +233,8 @@ ...@@ -219,6 +233,8 @@
left join warehouses w on sl.warehouses_code = w.warehouses_code left join warehouses w on sl.warehouses_code = w.warehouses_code
where sl.is_used = 1 where sl.is_used = 1
<if test="warehousesCode != null and warehousesCode != ''"> and sl.warehouses_code = #{warehousesCode}</if> <if test="warehousesCode != null and warehousesCode != ''"> and sl.warehouses_code = #{warehousesCode}</if>
<!-- 按sort_no降序排序 -->
order by sl.sort_no desc
</select> </select>
<!-- 原有新增/更新/删除方法(仅添加新字段) --> <!-- 原有新增/更新/删除方法(仅添加新字段) -->
...@@ -393,6 +409,8 @@ ...@@ -393,6 +409,8 @@
<if test="pickingArea != null and pickingArea != ''"> and sl.picking_area = #{pickingArea}</if> <if test="pickingArea != null and pickingArea != ''"> and sl.picking_area = #{pickingArea}</if>
<if test="allowMixedProducts != null "> and sl.allow_mixed_products = #{allowMixedProducts}</if> <if test="allowMixedProducts != null "> and sl.allow_mixed_products = #{allowMixedProducts}</if>
<if test="allowMixedBatches != null "> and sl.allow_mixed_batches = #{allowMixedBatches}</if> <if test="allowMixedBatches != null "> and sl.allow_mixed_batches = #{allowMixedBatches}</if>
<!-- 按sort_no降序排序 -->
order by sl.sort_no desc
</select> </select>
<!-- 关联仓库的getStorageLocationsList --> <!-- 关联仓库的getStorageLocationsList -->
...@@ -414,6 +432,8 @@ ...@@ -414,6 +432,8 @@
<if test="pickingArea != null and pickingArea != ''"> and sl.picking_area = #{pickingArea}</if> <if test="pickingArea != null and pickingArea != ''"> and sl.picking_area = #{pickingArea}</if>
<if test="allowMixedProducts != null "> and sl.allow_mixed_products = #{allowMixedProducts}</if> <if test="allowMixedProducts != null "> and sl.allow_mixed_products = #{allowMixedProducts}</if>
<if test="allowMixedBatches != null "> and sl.allow_mixed_batches = #{allowMixedBatches}</if> <if test="allowMixedBatches != null "> and sl.allow_mixed_batches = #{allowMixedBatches}</if>
<!-- 按sort_no降序排序 -->
order by sl.sort_no desc
</select> </select>
</mapper> </mapper>
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论