Commit 4551012a by yubin

出库

parent 70157266
......@@ -52,3 +52,10 @@ export function listLocationsForSelector(query) {
params: query
})
}
export function getlocationsdicts() {
return request({
url: '/inventory/owners/getMapList',
method: 'get'
})
}
\ No newline at end of file
......@@ -42,3 +42,10 @@ export function delMaterials(id) {
method: 'delete'
})
}
export function getMaterialsdicts() {
return request({
url: '/inventory/materials/getMapList',
method: 'get'
})
}
......@@ -42,3 +42,9 @@ export function delOwners(id) {
method: 'delete'
})
}
export function getOwnerdicts() {
return request({
url: '/inventory/owners/getMapList',
method: 'get'
})
}
......@@ -51,3 +51,9 @@ export function listWarehousesForSelector(query) {
params: query
})
}
export function getMapList() {
return request({
url: '/inventory/warehouses/getMapList',
method: 'get'
})
}
<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
......@@ -56,19 +56,18 @@
</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-key="row => row.sapNo"
@row-click="handleRowClick"
:select-on-indeterminate="false"
@select="handleTableSelect"
>
<!-- 修复单选/多选列:单选模式下不限制selectable,通过事件控制唯一选中 -->
<el-table-column
type="selection"
width="55"
......@@ -119,35 +118,34 @@ export default {
name: "MaterialSelector",
components: { TreeComponent, Splitpanes, Pane },
props: {
// 支持传入默认选中的物料ID(单选传单个ID,多选传数组)
value: {
type: [Array, Number, String],
type: [Array, String],
default: () => []
},
// 是否允许多选
multiple: {
type: Boolean,
default: true
},
// 默认选中的分类编码
defaultCategoryCodes: {
type: Array,
default: () => []
},
// 新增:父页面传递的反显参数(兼容原逻辑)
selectedMaterialCodes: {
type: Array,
default: () => []
}
},
data() {
return {
// 分类树相关
categoryTreeData: [],
treeProps: { children: 'children', label: 'label', value: 'sid' },
nodeKey: 'sid',
loadingTree: false,
categoryMap: {}, // 分类编码->分类名称
categoryNameToCodeMap: {}, // 分类名称->分类编码
categoryCodeToSidMap: {}, // 分类编码->树节点sid
categoryMap: {},
categoryNameToCodeMap: {},
categoryCodeToSidMap: {},
currentNodeId: null,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
......@@ -158,126 +156,102 @@ export default {
categoryNameInput: null,
specification: null,
},
// 物料列表相关
materialsList: [],
total: 0,
loading: false,
selectedRows: [], // 选中的物料行数据
singleSelectedId: null, // 单选模式下的选中ID
isSelecting: false // 防止选择事件重复触发的锁
selectedRows: [],
singleSelectedSapNo: null,
isSelecting: false
}
},
watch: {
// 监听外部传入的选中值变化
// 核心修复1:同时监听value和selectedMaterialCodes,兼容两种传参方式
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)
this.handleValueChange(val)
}
})
} 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 // 解锁
},
selectedMaterialCodes: {
immediate: true,
deep: true,
handler(val) {
// 优先使用selectedMaterialCodes,兼容父页面旧传参
if (val && val.length) {
this.handleValueChange(val)
}
})
}
},
// 监听多选状态切换:彻底重置选择状态,避免锁定
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)
})
this.singleSelectedSapNo = null
this.$nextTick(() => this.handleValueSync())
} finally {
this.isSelecting = false
}
}
}
},
// 监听默认分类编码变化
defaultCategoryCodes: {
immediate: true,
handler(val) {
if (val && val.length && this.categoryTreeData.length) {
this.$nextTick(() => {
this.selectCategoryNodes(val)
})
this.$nextTick(() => this.selectCategoryNodes(val))
}
}
}
},
async created() {
// 并行加载分类数据和分类树
await Promise.all([
this.getCategoryList(),
this.getCategoryTreeData()
])
// 加载物料列表
await Promise.all([this.getCategoryList(), this.getCategoryTreeData()])
this.getList()
},
methods: {
/**
* 获取分类列表,构建编码-名称映射
*/
// 新增:统一处理值变更
handleValueChange(val) {
if (this.isSelecting) return
// 空值直接清空选中
if (!val || (Array.isArray(val) && !val.length)) {
this.clearSelection()
return
}
// 有值时:先清空筛选,保证列表全量
if (this.currentNodeId || this.queryParams.categoryCode) {
this.currentNodeId = null
this.queryParams.categoryCode = null
this.getList()
return
}
// 列表未加载完成则等待,已加载则直接反显
if (this.loading || !this.materialsList.length) {
// 延长等待时间,确保列表加载完成
const timer = setTimeout(() => {
this.handleValueSync()
clearTimeout(timer)
}, 500)
} else {
this.handleValueSync()
}
},
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])) {
......@@ -292,20 +266,13 @@ export default {
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) {
......@@ -314,10 +281,6 @@ export default {
this.loadingTree = false
}
},
/**
* 构建分类树形结构
*/
buildTreeData(list, parentId = null) {
return list
.filter(item => parentId === null
......@@ -333,15 +296,10 @@ export default {
: 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
......@@ -352,13 +310,8 @@ export default {
}
})
},
/**
* 根据分类编码选中树节点
*/
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, '')
......@@ -366,18 +319,11 @@ export default {
if (sid) {
tree.setCurrentKey(sid)
this.currentNodeId = sid
// 展开节点
const node = tree.getNode(sid)
if (node) {
tree.expandNode(node)
}
if (node) tree.expandNode(node)
}
})
},
/**
* 分类树节点点击事件
*/
handleTreeClick(data) {
this.currentNodeId = data.sid
this.queryParams.categoryCode = data.categoryCode
......@@ -385,24 +331,20 @@ export default {
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}(未匹配分类)`
displayCategory: this.categoryMap[item.categoryCode] || `${item.categoryCode}(未匹配分类)`,
// 核心修复2:存储SAP号的大写和原始值,用于反显匹配
sapNoUpper: item.sapNo ? item.sapNo.trim().toUpperCase() : ''
}))
this.total = response.total || 0
// 列表加载完成后重新同步选中状态(延迟执行,避免DOM未更新)
setTimeout(() => {
this.$watchers.find(w => w.expression === 'value').handler(this.value)
}, 100)
// 确保列表渲染完成后再反显
this.$nextTick(() => {
setTimeout(() => this.handleValueSync(), 300)
})
}).catch(error => {
console.error('获取物料列表失败:', error)
this.materialsList = []
......@@ -411,19 +353,13 @@ export default {
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)
......@@ -435,10 +371,7 @@ export default {
this.queryParams.pageNum = 1
this.getList()
},
/**
* 重置查询条件
*/
// 核心修复:重置所有状态(对外暴露)
resetQuery() {
this.queryParams = {
pageNum: 1,
......@@ -451,131 +384,132 @@ export default {
specification: null,
}
this.currentNodeId = null
// 清空树节点选中状态
if (this.$refs.treeComponent && this.$refs.treeComponent.$refs.tree) {
this.$refs.treeComponent.$refs.tree.setCurrentKey(null)
}
this.clearSelection()
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)
this.singleSelectedSapNo = lastRow.sapNo
} else {
this.selectedRows = selection
this.singleSelectedId = selection.length > 0 ? Number(selection[0].id) : null
this.singleSelectedSapNo = selection.length > 0 ? selection[0].sapNo : null
}
} else {
// 多选模式
this.selectedRows = selection
}
// 组装选中数据并触发事件
const selectedIds = this.selectedRows.map(row => Number(row.id))
const selectedSapNos = this.selectedRows.map(row => row.sapNo)
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
categoryId: item.categoryCode || ''
}))
// 触发事件:input用于v-model绑定,change返回详细数据
// 核心修复3:新增selection-change事件,兼容父页面旧逻辑
this.$emit('selection-change', {
materialCodes: selectedSapNos,
names: selectedData.map(item => item.materialName),
categoryIds: selectedData.map(item => item.categoryId)
})
if (this.multiple) {
this.$emit('input', selectedIds)
this.$emit('input', selectedSapNos)
this.$emit('change', selectedData)
} else {
const singleId = selectedIds.length > 0 ? selectedIds[0] : ''
const singleSapNo = selectedSapNos.length > 0 ? selectedSapNos[0] : ''
const singleData = selectedData.length > 0 ? selectedData[0] : null
this.$emit('input', singleId)
this.$emit('input', singleSapNo)
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.singleSelectedSapNo = row.sapNo
this.selectedRows = [row]
this.$emit('input', Number(row.id))
this.$emit('change', row)
this.$emit('input', row.sapNo)
this.$emit('change', { sapNo: row.sapNo, materialName: row.materialName })
// 兼容selection-change事件
this.$emit('selection-change', {
materialCodes: [row.sapNo],
names: [row.materialName],
categoryIds: [row.categoryCode || '']
})
} else {
this.singleSelectedId = null
this.singleSelectedSapNo = null
this.selectedRows = []
this.$emit('input', '')
this.$emit('change', null)
this.$emit('selection-change', {
materialCodes: [],
names: [],
categoryIds: []
})
}
} 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)
const isCurrentlySelected = this.singleSelectedSapNo === row.sapNo
this.$refs.materialTable.clearSelection()
if (!isCurrentlySelected) {
this.$refs.materialTable.toggleRowSelection(row, true)
this.singleSelectedId = Number(row.id)
this.singleSelectedSapNo = row.sapNo
this.selectedRows = [row]
this.$emit('input', Number(row.id))
this.$emit('change', row)
this.$emit('input', row.sapNo)
this.$emit('change', { sapNo: row.sapNo, materialName: row.materialName })
this.$emit('selection-change', {
materialCodes: [row.sapNo],
names: [row.materialName],
categoryIds: [row.categoryCode || '']
})
} else {
this.singleSelectedId = null
this.singleSelectedSapNo = null
this.selectedRows = []
this.$emit('input', '')
this.$emit('change', null)
this.$emit('selection-change', {
materialCodes: [],
names: [],
categoryIds: []
})
}
} else {
// 多选模式:点击行切换选中状态
this.$refs.materialTable.toggleRowSelection(row)
}
} finally {
this.isSelecting = false
}
},
/**
* 清空选中状态(外部调用)
*/
// 核心修复:彻底清空选中状态并同步父页面(对外暴露)
clearSelection() {
if (this.isSelecting || !this.$refs.materialTable) return
......@@ -583,39 +517,109 @@ export default {
try {
this.$refs.materialTable.clearSelection()
this.selectedRows = []
this.singleSelectedId = null
this.singleSelectedSapNo = null
this.$emit('input', this.multiple ? [] : '')
this.$emit('change', this.multiple ? [] : null)
this.$emit('selection-change', {
materialCodes: [],
names: [],
categoryIds: []
})
} finally {
this.isSelecting = false
}
},
// 核心修复4:增强反显同步逻辑,兼容大小写和多页数据
handleValueSync() {
if (this.loading || this.isSelecting || !this.$refs.materialTable) return
/**
* 获取选中的物料详情(外部调用)
*/
getSelectedMaterials() {
return this.multiple ? [...this.selectedRows] : (this.selectedRows[0] || null)
// 优先使用selectedMaterialCodes,兼容父页面传参
const val = this.selectedMaterialCodes.length ? this.selectedMaterialCodes : this.value
if (!val || (Array.isArray(val) && !val.length)) {
this.clearSelection()
return
}
// 统一处理值格式:转数组 + 去空 + 转大写(用于匹配)
const targetSapNos = this.multiple
? Array.isArray(val) ? val : [val]
: [Array.isArray(val) ? val[0] : val]
const targetSapNosUpper = targetSapNos.map(code => code ? code.trim().toUpperCase() : '')
.filter(code => code)
this.isSelecting = true
try {
this.$refs.materialTable.clearSelection()
// 遍历列表匹配(兼容原始值和大写值)
this.materialsList.forEach(row => {
const rowSapUpper = row.sapNoUpper || row.sapNo.trim().toUpperCase()
if (targetSapNos.includes(row.sapNo) || targetSapNosUpper.includes(rowSapUpper)) {
this.$refs.materialTable.toggleRowSelection(row, true)
}
})
// 更新选中行数据
this.selectedRows = this.materialsList.filter(row => {
const rowSapUpper = row.sapNoUpper || row.sapNo.trim().toUpperCase()
return targetSapNos.includes(row.sapNo) || targetSapNosUpper.includes(rowSapUpper)
})
this.singleSelectedSapNo = this.multiple ? null : (this.selectedRows[0]?.sapNo || null)
} finally {
this.isSelecting = false
}
},
// 核心修复5:对外暴露反显方法,供父页面主动调用
setSelectedCodes(codes) {
if (this.isSelecting) return
/**
* 设置单选选中项(外部调用)
*/
setSingleSelection(materialId) {
this.isSelecting = true
try {
// 先清空筛选,保证列表全量
this.currentNodeId = null
this.queryParams.categoryCode = null
// 重新加载列表后再反显
this.getList().then(() => {
this.$nextTick(() => {
// 赋值给selectedMaterialCodes触发反显
this.$props.selectedMaterialCodes = codes
this.handleValueSync()
})
})
} finally {
this.isSelecting = false
}
},
getSelectedMaterials() {
if (this.multiple) {
return this.selectedRows.map(row => ({ sapNo: row.sapNo, materialName: row.materialName }))
} else {
return this.selectedRows[0] ? { sapNo: this.selectedRows[0].sapNo, materialName: this.selectedRows[0].materialName } : null
}
},
setSingleSelection(sapNo) {
if (this.isSelecting || this.multiple) return
this.isSelecting = true
try {
const targetId = Number(materialId)
this.singleSelectedId = targetId
this.singleSelectedSapNo = sapNo
this.$nextTick(() => {
this.$refs.materialTable.clearSelection()
const targetRow = this.materialsList.find(row => Number(row.id) === targetId)
const targetRow = this.materialsList.find(row => {
const rowSapUpper = row.sapNoUpper || row.sapNo.trim().toUpperCase()
return row.sapNo === sapNo || rowSapUpper === sapNo.trim().toUpperCase()
})
if (targetRow) {
this.$refs.materialTable.toggleRowSelection(targetRow, true)
this.selectedRows = [targetRow]
this.$emit('input', targetId)
this.$emit('change', targetRow)
this.$emit('input', sapNo)
this.$emit('change', { sapNo: targetRow.sapNo, materialName: targetRow.materialName })
this.$emit('selection-change', {
materialCodes: [targetRow.sapNo],
names: [targetRow.materialName],
categoryIds: [targetRow.categoryCode || '']
})
}
})
} finally {
......@@ -634,15 +638,12 @@ export default {
.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;
......
......@@ -192,15 +192,6 @@
</el-tooltip>
</template>
</el-table-column>
<el-table-column label="允许存放物料编码" align="center" prop="materialCodes" width="200">
<template slot-scope="scope">
<el-tooltip :content="scope.row.materialCodes" placement="top">
<div class="material-names">
{{ scope.row.materialCodes ? (scope.row.materialCodes.length > 20 ? scope.row.materialCodes.substring(0, 20) + '...' : scope.row.materialCodes) : '-' }}
</div>
</el-tooltip>
</template>
</el-table-column>
<el-table-column label="温区" align="center" prop="temperatureZone" width="100" />
<el-table-column label="应用状态" align="center" prop="isEnabled" width="100">
<template slot-scope="scope">
......@@ -351,7 +342,7 @@
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="允许存放物料" prop="materialCodes">
<el-form-item label="允许存放物料" prop="allowedCategoryIds">
<div style="display: flex; align-items: center; flex-direction: column; gap: 8px;">
<el-input
v-model="form.materialNames"
......@@ -362,10 +353,13 @@
<el-button
type="primary"
size="small"
@click.stop="showMaterialSelect = true"
@click.stop="openMaterialSelector"
style="align-self: flex-end;"
>选择物料</el-button>
</div>
<div style="margin-top: 8px; font-size: 12px; color: #666;">
已选SAP号:{{ form.allowedCategoryIds || '无' }}
</div>
</el-form-item>
</el-col>
</el-row>
......@@ -412,13 +406,16 @@
append-to-body
:close-on-click-modal="false"
:close-on-press-escape="false"
@open="initMaterialSelector"
>
<!-- 关键修复:v-if确保弹窗打开时才初始化组件 -->
<materialsSeletor
v-if="showMaterialSelect"
ref="materialsSeletor"
@selection-change="handleMaterialSelectionChange"
:selected-material-codes="form.materialCodes ? form.materialCodes.split(',').filter(u => u.trim()) : []"
:selected-material-codes="selectedSapCodes"
:multiple="true"
:default-category-codes="form.allowedCategoryIds ? form.allowedCategoryIds.split(',').filter(c => c.trim()) : []"
:default-category-codes="[]"
/>
<div slot="footer" class="dialog-footer">
......@@ -442,14 +439,14 @@
<script>
import { listLocations, getLocations, delLocations, addLocations, updateLocations } from "@/api/inventory/locations"
import { listWarehouses } from "@/api/inventory/warehouses"
import materialsSeletor from "../../../components/materialsSeletor.vue"
import materialsSeletor from "@/components/materialsSeletor.vue"
import ImportExcel from "@/components/ImportExcel/index"
import { listMaterials } from "@/api/inventory/materials"
export default {
name: "Locations",
components: { materialsSeletor, ImportExcel },
dicts: ['sys_normal_disable'],
dicts: ['sys_normal_disable', 'location_type'],
data() {
return {
loading: true,
......@@ -500,10 +497,9 @@ export default {
capacity: null,
volumeCapacity: null,
allowedHazardLevels: null,
materialCodes: null,
materialNames: null,
allowedCategoryIds: null,
allowedCategoryNames: null,
allowedCategoryIds: null, // 核心字段:存储逗号分隔的SAP号
materialNames: null, // 存储物料名称(逗号分隔,用于显示)
allowedCategoryNames: null, // 存储物料分类名称(逗号分隔)
temperatureZone: null,
isEnabled: 1,
isUsed: 0,
......@@ -527,6 +523,9 @@ export default {
],
isEnabled: [
{ required: true, message: '应用状态不能为空', trigger: 'change' }
],
allowedCategoryIds: [
{ required: true, message: '请选择允许存放的物料', trigger: 'blur' }
]
},
......@@ -534,24 +533,36 @@ export default {
loadingWarehouse: false,
showMaterialSelect: false,
tempSelectedMaterials: {
materialCodes: [],
names: [],
categoryIds: []
tempSelectedMaterials: { // 临时存储选择的物料数据
materialCodes: [], // SAP号数组
names: [], // 物料名称数组
categoryIds: [] // 分类ID数组
},
materialCodeToNameMap: {},
materialMapLoaded: false
materialCodeToNameMap: {}, // SAP号→物料名称映射表
materialMapLoaded: false // 映射表加载状态
}
},
computed: {
// 计算属性:统一处理SAP号大小写,确保反显参数正确
selectedSapCodes() {
if (!this.form.allowedCategoryIds) return []
// 核心修复:转大写 + 去空 + 去重
return this.form.allowedCategoryIds.split(',')
.map(code => code.trim().toUpperCase())
.filter(code => code)
.filter((code, index, self) => self.indexOf(code) === index)
}
},
created() {
this.getList()
this.getWarehouseOptions()
this.initMaterialCodeToNameMap()
this.initMaterialCodeToNameMap() // 初始化SAP号-名称映射
},
methods: {
/** 初始化SAP号→物料名称映射表(用于反显) */
async initMaterialCodeToNameMap() {
try {
this.materialMapLoaded = true
this.materialMapLoaded = false
let pageNum = 1
const pageSize = 1000
let hasMore = true
......@@ -561,16 +572,14 @@ export default {
const response = await listMaterials({
pageNum,
pageSize,
isUsed: 1,
materialCode: null,
materialName: null
isUsed: 1 // 只查询启用的物料
})
if (response.rows && response.rows.length) {
response.rows.forEach(item => {
if (item.materialCode && item.materialName) {
const code = item.materialCode.trim().toUpperCase()
this.materialCodeToNameMap[code] = item.materialName
if (item.sapNo && item.materialName) {
const sapCode = item.sapNo.trim().toUpperCase() // SAP号统一大写存储
this.materialCodeToNameMap[sapCode] = item.materialName
}
})
hasMore = pageNum * pageSize < response.total
......@@ -579,25 +588,28 @@ export default {
hasMore = false
}
}
console.log('物料映射表初始化完成:', this.materialCodeToNameMap)
this.materialMapLoaded = true
console.log('SAP号-物料名称映射表初始化完成:', this.materialCodeToNameMap)
} catch (error) {
console.error('初始化物料编码-名称映射表失败:', error)
console.error('初始化SAP号-物料名称映射表失败:', error)
this.materialMapLoaded = false
this.$modal.msgError('物料数据加载失败,请刷新页面重试!')
}
},
/** 表格行点击展开详情 */
handleRowClick(row, event, column) {
if (column.type !== 'selection') {
this.$refs.locationsTable.toggleRowExpansion(row)
}
},
/** 获取库位列表 */
getList() {
this.loading = true
const params = {
...this.queryParams,
isUsed: 0
isUsed: 0 // 只查询未删除的库位
}
listLocations(params).then(response => {
this.locationsList = response.rows
......@@ -606,6 +618,7 @@ export default {
})
},
/** 获取仓库下拉选项 */
getWarehouseOptions() {
this.loadingWarehouse = true
listWarehouses({ pageNum: 1, pageSize: 100 }).then(response => {
......@@ -622,17 +635,20 @@ export default {
})
},
/** 根据仓库编码获取仓库名称 */
getWarehouseName(warehouseCode) {
if (!warehouseCode) return ''
const warehouse = this.warehouseOptions.find(item => item.value === warehouseCode)
return warehouse ? warehouse.label : warehouseCode
},
/** 取消操作,关闭弹窗并重置 */
cancel() {
this.open = false
this.reset()
this.reset() // 重置表单状态,避免数据残留
},
/** 重置表单(关键:清空所有状态,避免数据残留) */
reset() {
this.form = {
id: null,
......@@ -647,83 +663,101 @@ export default {
capacity: null,
volumeCapacity: null,
allowedHazardLevels: null,
materialCodes: null,
materialNames: null,
allowedCategoryIds: null,
allowedCategoryNames: null,
allowedCategoryIds: null, // 清空SAP号
materialNames: null, // 清空物料名称
allowedCategoryNames: null, // 清空分类名称
temperatureZone: null,
isEnabled: 1,
isUsed: 0,
sortNo: 0
}
// 清空临时选择的物料数据
this.tempSelectedMaterials = {
materialCodes: [],
names: [],
categoryIds: []
}
this.resetForm("form")
// 重置物料选择器(关键:避免切换时残留选中状态)
if (this.$refs.materialsSeletor) {
// 调用选择器内部的清空方法(需组件支持)
if (typeof this.$refs.materialsSeletor.clearSelection === 'function') {
this.$refs.materialsSeletor.clearSelection()
}
if (typeof this.$refs.materialsSeletor.resetQuery === 'function') {
this.$refs.materialsSeletor.resetQuery()
}
}
// 重置表单校验
if (this.$refs.form) {
this.$refs.form.resetFields()
}
this.showMaterialSelect = false
},
/** 查询库位列表 */
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
/** 重置查询条件 */
resetQuery() {
this.resetForm("queryForm")
if (this.$refs.queryForm) {
this.$refs.queryForm.resetFields()
}
this.handleQuery()
},
/** 表格选择事件 */
handleSelectionChange(selection) {
this.ids = selection.map(item => item.id)
this.single = selection.length!==1
this.single = selection.length !== 1
this.multiple = !selection.length
},
/** 新增库位 */
handleAdd() {
this.reset()
this.reset() // 新增前先重置,避免残留修改的数据
this.open = true
this.title = "添加库位"
},
/** 修改库位(反显数据,基于allowedCategoryIds存储的SAP号) */
async handleUpdate(row) {
this.reset()
this.reset() // 修改前先重置,避免数据残留
const id = row.id || this.ids
try {
const response = await getLocations(id)
console.log('后端返回库位详情:', response.data)
this.form = JSON.parse(JSON.stringify(response.data))
const data = response.data || {}
this.form = { ...this.form, ...data } // 赋值基础字段
// 等待映射表加载完成,再处理SAP号反显
if (!this.materialMapLoaded) {
await this.initMaterialCodeToNameMap()
}
// 从allowedCategoryIds读取物料编码(替代缺失的materialCodes)
const rawMaterialCodes = this.form.allowedCategoryIds || row.allowedCategoryIds || ''
console.log('原始物料编码(从allowedCategoryIds读取):', rawMaterialCodes)
// 核心修复:统一转大写,确保匹配映射表
const sapCodes = this.form.allowedCategoryIds
? this.form.allowedCategoryIds.split(',').map(code => code.trim().toUpperCase()).filter(code => code)
: []
if (rawMaterialCodes) {
const materialCodes = rawMaterialCodes.split(',')
.map(code => code.trim().toUpperCase())
.filter(code => code)
console.log('处理后物料编码:', materialCodes)
console.log('映射表匹配:', materialCodes.map(code => ({
console.log('反显的SAP号(转大写后):', sapCodes)
console.log('映射表匹配结果:', sapCodes.map(code => ({
code,
name: this.materialCodeToNameMap[code]
})))
this.form.materialNames = materialCodes.map(code => {
// 匹配物料名称
this.form.materialNames = sapCodes.map(code => {
return this.materialCodeToNameMap[code] || `【未匹配】${code}`
}).join(',')
// 同步赋值materialCodes(确保选择器能接收到)
this.form.materialCodes = rawMaterialCodes
// 临时存储选中的物料数据(用于物料选择器回显)
this.tempSelectedMaterials = {
materialCodes: materialCodes,
materialCodes: sapCodes,
names: this.form.materialNames.split(',').filter(name => name.trim()),
categoryIds: this.form.allowedCategoryIds ? this.form.allowedCategoryIds.split(',').filter(c => c.trim()) : []
}
categoryIds: [] // 分类ID按需从后端获取,此处暂空
}
this.open = true
......@@ -734,16 +768,26 @@ export default {
}
},
/** 提交表单(新增/修改) */
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.materialCodes) {
this.form.materialCodes = this.form.materialCodes.split(',').filter(code => code.trim()).join(',')
}
if (this.form.materialNames) {
this.form.materialNames = this.form.materialNames.split(',').filter(name => name.trim()).join(',')
}
// 处理SAP号:去重、去空、统一大写,用逗号分隔
const sapCodes = this.form.allowedCategoryIds
? this.form.allowedCategoryIds.split(',')
.map(code => code.trim().toUpperCase())
.filter(code => code)
.filter((code, index, self) => self.indexOf(code) === index) // 去重
: []
this.form.allowedCategoryIds = sapCodes.join(',') // 重新赋值SAP号
// 物料名称与SAP号保持一致
this.form.materialNames = sapCodes.map(code => {
return this.materialCodeToNameMap[code] || `【未匹配】${code}`
}).join(',')
// 提交到后端
if (this.form.id != null) {
updateLocations(this.form).then(response => {
this.$modal.msgSuccess("修改成功")
......@@ -761,6 +805,7 @@ export default {
})
},
/** 删除库位 */
handleDelete(row) {
const ids = row.id || this.ids
this.$modal.confirm(row.id ? `是否确认删除库位编号为"${row.locationCode}"的数据项?` : `是否确认删除选中的${ids.length}条库位数据项?`).then(function() {
......@@ -771,52 +816,78 @@ export default {
}).catch(() => {})
},
/** 导出库位数据 */
handleExport() {
this.download('inventory/locations/export', {
...this.queryParams
}, `locations_${new Date().getTime()}.xlsx`)
},
/** 打开物料选择器(封装逻辑,确保数据加载完成) */
openMaterialSelector() {
// 确保映射表加载完成
if (!this.materialMapLoaded) {
this.$modal.msgWarning('物料数据正在加载,请稍候!')
this.initMaterialCodeToNameMap().then(() => {
this.showMaterialSelect = true
})
return
}
this.showMaterialSelect = true
},
/** 初始化物料选择器(弹窗打开时触发) */
initMaterialSelector() {
// 主动触发选择器反显(需组件支持setSelectedCodes方法)
if (this.$refs.materialsSeletor && typeof this.$refs.materialsSeletor.setSelectedCodes === 'function') {
this.$refs.materialsSeletor.setSelectedCodes(this.selectedSapCodes)
}
console.log('物料选择器反显参数:', this.selectedSapCodes)
},
/** 物料选择器选择事件(接收选中的物料数据) */
handleMaterialSelectionChange(selectedData) {
this.tempSelectedMaterials = {
materialCodes: selectedData.materialCodes || [],
names: selectedData.names || [],
categoryIds: selectedData.formattedCategoryIds || []
materialCodes: selectedData.materialCodes || [], // SAP号数组
names: selectedData.names || [], // 物料名称数组
categoryIds: selectedData.categoryIds || [] // 分类ID数组
}
},
/** 取消物料选择 */
handleMaterialSelectionCancel() {
this.showMaterialSelect = false
// 恢复之前选择的物料数据(避免取消后丢失已选数据)
this.tempSelectedMaterials = {
materialCodes: this.form.materialCodes ? this.form.materialCodes.split(',').filter(u => u.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()) : []
materialCodes: this.form.allowedCategoryIds ? this.form.allowedCategoryIds.split(',').filter(code => code.trim()).map(code => code.toUpperCase()) : [],
names: this.form.materialNames ? this.form.materialNames.split(',').filter(name => name.trim()) : [],
categoryIds: []
}
},
/** 确认选择物料(将选中的SAP号赋值给allowedCategoryIds) */
confirmMaterialSelection() {
if (!this.tempSelectedMaterials.materialCodes.length) {
const { materialCodes, names, categoryIds } = this.tempSelectedMaterials
if (!materialCodes.length) {
this.$modal.msgWarning('请至少选择一个物料!')
return
}
this.form.materialCodes = this.tempSelectedMaterials.materialCodes.join(',')
this.form.materialNames = this.tempSelectedMaterials.names.join(',')
this.form.allowedCategoryIds = this.tempSelectedMaterials.categoryIds.join(',')
if (this.$refs.materialsSeletor) {
const categoryNames = this.tempSelectedMaterials.categoryIds.map(code => {
const rawCode = code.replace(/-/g, '')
return this.$refs.materialsSeletor.categoryMap[rawCode] || code
})
this.form.allowedCategoryNames = categoryNames.join(',')
}
// 核心:将选中的SAP号用逗号分隔存储到allowedCategoryIds
this.form.allowedCategoryIds = materialCodes.join(',')
// 存储物料名称(用于显示)
this.form.materialNames = names.join(',')
// 存储分类名称(按需处理)
this.form.allowedCategoryNames = categoryIds.map(id => {
return this.$refs.materialsSeletor?.categoryMap[id] || id
}).join(',')
this.showMaterialSelect = false
this.$modal.msgSuccess(`成功选择 ${this.tempSelectedMaterials.names.length} 个物料`)
this.$modal.msgSuccess(`成功选择 ${materialCodes.length} 个物料(SAP号:${this.form.allowedCategoryIds}`)
},
/** 导入组件 */
/** 导入库位数据 */
handleImport() {
this.$refs.import.show()
}
......@@ -867,4 +938,17 @@ export default {
max-width: 300px;
white-space: normal;
}
/* 优化SAP号显示样式 */
/deep/ .el-form-item__content .el-input {
margin-bottom: 4px;
}
.el-form-item__content .el-button {
margin-top: 4px;
}
.el-form-item__content div[style*="font-size: 12px"] {
color: #888;
}
</style>
\ No newline at end of file
......@@ -12,7 +12,6 @@
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="货物ID" prop="materialId">
<!-- 核心:编辑状态禁用输入框和选择按钮 -->
<el-input
v-model="form.materialId"
placeholder="请选择或输入货物ID"
......@@ -30,7 +29,6 @@
></el-button>
</template>
</el-input>
<!-- 编辑状态隐藏物料选择器弹窗 -->
<el-dialog
v-if="!isMaterialLocked"
title="选择物料"
......@@ -59,7 +57,6 @@
</el-col>
</el-row>
<!-- 库存信息列表 - 添加库存ID列和单价列 -->
<el-row v-if="form.materialId && form.materialId.trim()" style="margin: 10px 0;">
<el-col :span="24">
<div style="margin-bottom: 8px; font-weight: 600; color: #1989fa;">
......@@ -75,13 +72,13 @@
stripe
empty-text="暂无库存数据"
@row-click="handleRowClick"
:row-key="item => item.id"
:row-key="item => item.inventoryId"
>
<el-table-column prop="materialId" label="货物ID" width="120" />
<el-table-column prop="batchId" label="批次ID" width="120" />
<el-table-column prop="outboundOrderId" label="出库单号" width="120" />
<el-table-column prop="warehouseId" label="仓库ID" width="120" />
<el-table-column prop="locationId" label="库位ID" width="110" />
<el-table-column prop="materialId" label="货物ID" width="150" />
<el-table-column prop="batchId" label="批次ID" width="150" />
<el-table-column prop="outboundOrderId" label="出库单号" width="150" />
<!-- <el-table-column prop="warehouseId" label="仓库ID" width="120" /> -->
<el-table-column prop="locationId" label="库位ID" width="140" />
<el-table-column
prop="inventoryType"
label="库存类型"
......@@ -98,7 +95,6 @@
{{ (scope.row.quantity || 0) - (scope.row.lockedQuantity || 0) }}
</template>
</el-table-column>
<!-- 实际数量:填写即视为选中(原选择数量) -->
<el-table-column label="实际数量" width="120">
<template slot-scope="scope">
<el-input
......@@ -114,7 +110,6 @@
</el-table-column>
</el-table>
<!-- 选中行的扩展字段填写区域 -->
<div
v-if="currentSelectedRow"
style="margin-top: 10px; padding: 10px; border: 1px solid #e6e6e6; border-radius: 4px;"
......@@ -122,7 +117,6 @@
<div style="margin-bottom: 8px; font-weight: 600; color: #1989fa;">
库存明细信息
</div>
<!-- 扩展字段区域 -->
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="约数" prop="divisor">
......@@ -197,7 +191,18 @@
</el-col>
</el-row>
<el-row :gutter="20" style="margin-top: 10px;">
<el-col :span="24">
<el-col :span="8">
<el-form-item label="发货时间" prop="shippedAt">
<el-date-picker
v-model="currentSelectedRow.shippedAt"
type="date"
placeholder="选择发货时间"
style="width: 100%;"
@input="syncDetails(false)"
/>
</el-form-item>
</el-col>
<el-col :span="16">
<el-form-item label="备注" prop="remark">
<el-input
v-model="currentSelectedRow.remark"
......@@ -213,7 +218,6 @@
</el-col>
</el-row>
<!-- 已生成的明细预览 - 添加库存ID列和单价列 -->
<el-row v-if="details.length > 0" style="margin: 10px 0;">
<el-col :span="24">
<div style="margin-bottom: 8px; font-weight: 600; color: #1989fa;">
......@@ -241,6 +245,7 @@
</el-table-column>
<el-table-column prop="voucherNumber" label="凭证号" />
<el-table-column prop="shippedBy" label="发货方" />
<el-table-column prop="shippedAt" label="发货时间" />
<el-table-column prop="remark" label="备注" />
<el-table-column label="操作" width="80">
<template slot-scope="scope">
......@@ -264,7 +269,7 @@
<script>
import { listInventoryByMaterialId } from "@/api/inventory/inventory";
import MaterialSelector from '../../../components/materialsSeletor.vue';
import MaterialSelector from '@/components/materialsSeletor.vue';
function debounce(fn, delay = 500) {
let timer = null;
......@@ -278,7 +283,7 @@ function debounce(fn, delay = 500) {
export default {
name: 'OutboundOrderFormWithItems',
dicts: ['inbound_order_status', 'inbound_order_type', 'inbound_order_item_status','label_color'],
dicts: ['inbound_order_status', 'inbound_order_type', 'inbound_order_item_status', 'label_color'],
components: {
MaterialSelector
},
......@@ -335,9 +340,8 @@ export default {
},
computed: {
currentSelectedRow() {
return this.inventoryList.find(row => row.id === this.currentSelectedRowId) || null;
return this.inventoryList.find(row => row.inventoryId === this.currentSelectedRowId) || null;
},
// 核心计算属性:判断是否为编辑状态(有初始数据则锁死物料)
isMaterialLocked() {
return this.initDetails.length > 0 || !!this.initForm.materialId;
}
......@@ -356,9 +360,18 @@ export default {
this.selectedMaterialInfo = null;
this.currentSelectedRowId = null;
this.details = this.initDetails.length > 0 ? JSON.parse(JSON.stringify(this.initDetails)) : [];
// 强制等待DOM更新后再查库存,避免数据未初始化
this.$nextTick(async () => {
if (this.form.materialId && this.form.materialId.trim()) {
this.handleMaterialIdChange();
await this.handleMaterialIdChange();
// 二次确认:库存加载完成后手动触发回显
if (this.inventoryList.length > 0 && !this.isInitEcho) {
this.initEchoDetails();
this.isInitEcho = true;
this.currentSelectedRowId = this.inventoryList[0].inventoryId;
}
}
});
} else {
this.$nextTick(() => {
this.closeLoading();
......@@ -381,10 +394,18 @@ export default {
const oldMaterialId = this.selectedMaterialId;
this.selectedMaterialId = this.form.materialId || '';
this.currentSelectedRowId = null;
// 强制等待DOM更新后再查库存
this.$nextTick(async () => {
if (this.form.materialId && this.form.materialId.trim() && this.form.materialId !== oldMaterialId) {
this.handleMaterialIdChange();
await this.handleMaterialIdChange();
if (this.inventoryList.length > 0 && !this.isInitEcho) {
this.initEchoDetails();
this.isInitEcho = true;
this.currentSelectedRowId = this.inventoryList[0].inventoryId;
}
}
});
}
},
immediate: true,
deep: true
......@@ -394,9 +415,7 @@ export default {
if (this.open && newVal.length > 0 && !this.isInitEcho) {
this.initEchoDetails();
this.isInitEcho = true;
if (!this.currentSelectedRowId) {
this.currentSelectedRowId = newVal[0].id;
}
this.currentSelectedRowId = newVal[0].inventoryId;
}
},
immediate: true,
......@@ -441,12 +460,18 @@ export default {
materialId: materialId,
outboundOrderId: this.form.outboundOrderId
};
console.log('【查询库存参数】', params);
const res = await listInventoryByMaterialId(params);
console.log('【库存接口返回】', res);
console.log('【库存接口原始行数据】', res.rows); // 打印原始行数据
if (res.code === 200) {
this.inventoryList = [];
(res.rows || []).forEach(item => {
console.log('【单条库存数据】', item); // 打印单条库存数据
const newRow = {
id: item.id,
// 核心修复:优先取item.inventoryId(匹配回显字段),兼容item.id
inventoryId: item.inventoryId || item.id,
id: item.id, // 保留原id字段
materialId: item.materialId || materialId,
batchId: item.batchId || '',
outboundOrderId: item.outboundOrderId || this.form.outboundOrderId,
......@@ -468,6 +493,8 @@ export default {
};
this.inventoryList.push(newRow);
});
console.log('【组装后的库存列表】', this.inventoryList);
console.log('【待回显的initDetails】', this.initDetails);
if (this.inventoryList.length === 0) {
this.$message.warning('未查询到该物料的库存信息');
......@@ -485,11 +512,11 @@ export default {
});
}
},
// 修复:初始化回显逻辑 - 确保所有明细都正确赋值
initEchoDetails() {
if (this.initDetails.length === 0) return;
console.log('【开始回显】inventoryList=', this.inventoryList, 'initDetails=', this.initDetails);
if (this.initDetails.length === 0 || this.inventoryList.length === 0) return;
// 清空原有数据,避免残留
// 清空原有数据
this.inventoryList.forEach(row => {
this.$set(row, 'actualQuantity', null);
this.$set(row, 'plannedQuantity', null);
......@@ -502,27 +529,53 @@ export default {
this.$set(row, 'remark', '');
});
// 重新赋值所有明细
this.initDetails.forEach(detail => {
const targetRow = this.inventoryList.find(row => row.id === detail.inventoryId);
// 方案1:优先用inventoryId匹配
let targetRow = null;
const firstDetail = this.initDetails[0];
targetRow = this.inventoryList.find(row => row.inventoryId === firstDetail.inventoryId);
// 方案2:兜底用batchId+warehouseId+locationId匹配
if (!targetRow) {
console.log('【兜底匹配】使用batchId+warehouseId+locationId匹配,明细=', firstDetail);
targetRow = this.inventoryList.find(row =>
row.batchId === firstDetail.batchId &&
row.warehouseId === firstDetail.warehouseId &&
row.locationId === firstDetail.locationId
);
}
// 方案3:终极兜底(强制赋值到第一行)
if (!targetRow) {
console.log('【强制回显】无匹配字段,直接赋值到第一条库存行');
targetRow = this.inventoryList[0];
}
console.log('【匹配明细】detail.inventoryId=', firstDetail.inventoryId, '匹配到的行=', targetRow);
if (targetRow) {
this.$set(targetRow, 'actualQuantity', detail.actualQuantity ?? null);
this.$set(targetRow, 'plannedQuantity', detail.plannedQuantity ?? null);
this.$set(targetRow, 'divisor', detail.divisor ?? null);
this.$set(targetRow, 'labelColor', detail.labelColor ?? '');
this.$set(targetRow, 'unitPrice', detail.unitPrice ?? null);
this.$set(targetRow, 'shippedBy', detail.shippedBy ?? '');
this.$set(targetRow, 'shippedAt', detail.shippedAt ?? '');
this.$set(targetRow, 'voucherNumber', detail.voucherNumber ?? '');
this.$set(targetRow, 'remark', detail.remark ?? '');
// 回显赋值(所有字段)
this.$set(targetRow, 'actualQuantity', firstDetail.actualQuantity ?? null);
this.$set(targetRow, 'plannedQuantity', firstDetail.plannedQuantity ?? null);
this.$set(targetRow, 'divisor', firstDetail.divisor ?? null);
this.$set(targetRow, 'labelColor', firstDetail.labelColor ?? '');
this.$set(targetRow, 'unitPrice', firstDetail.unitPrice ?? null);
this.$set(targetRow, 'shippedBy', firstDetail.shippedBy ?? '');
this.$set(targetRow, 'shippedAt', firstDetail.shippedAt ?? '');
this.$set(targetRow, 'voucherNumber', firstDetail.voucherNumber ?? '');
this.$set(targetRow, 'remark', firstDetail.remark ?? '');
// 强制选中该行
this.currentSelectedRowId = targetRow.inventoryId;
} else {
console.warn('【匹配失败】无可用库存行进行回显');
}
});
// 同步明细数据
this.syncDetails(false);
console.log('【回显完成】inventoryList=', this.inventoryList);
},
handleRowClick(row) {
if (!row) return;
this.currentSelectedRowId = row.id;
this.currentSelectedRowId = row.inventoryId;
},
handleRowActualQtyInput(row) {
if (isNaN(row.actualQuantity) || row.actualQuantity === '') {
......@@ -552,7 +605,6 @@ export default {
this.$set(row, 'plannedQuantity', 1);
}
},
// 修复:同步明细数据逻辑 - 确保严格模式下正确收集所有有效数据
syncDetails(strict = true) {
this.details = [];
......@@ -560,7 +612,6 @@ export default {
if (strict) {
validRows = this.inventoryList.filter(row => {
const availableQty = (row.quantity || 0) - (row.lockedQuantity || 0);
// 修复:允许0值(但需大于0),同时确保必填字段不为空
return row.actualQuantity !== null &&
row.actualQuantity !== undefined &&
row.actualQuantity >= 1 &&
......@@ -585,10 +636,9 @@ export default {
});
}
// 修复:确保每条明细都有唯一标识
validRows.forEach(row => {
const newDetail = {
inventoryId: row.id,
inventoryId: row.inventoryId,
materialId: row.materialId || this.form.materialId,
batchId: row.batchId || row.batchCode || '',
warehouseId: row.warehouseId || '',
......@@ -609,7 +659,7 @@ export default {
},
removeDetail(row) {
this.details = this.details.filter(d => d.inventoryId !== row.inventoryId);
const inventoryRow = this.inventoryList.find(item => item.id === row.inventoryId);
const inventoryRow = this.inventoryList.find(item => item.inventoryId === row.inventoryId);
if (inventoryRow) {
this.$set(inventoryRow, 'actualQuantity', null);
this.$set(inventoryRow, 'plannedQuantity', null);
......@@ -621,12 +671,11 @@ export default {
this.$set(inventoryRow, 'voucherNumber', '');
this.$set(inventoryRow, 'remark', '');
if (this.currentSelectedRowId === row.inventoryId) {
this.currentSelectedRowId = this.inventoryList.length > 0 ? this.inventoryList[0].id : null;
this.currentSelectedRowId = this.inventoryList.length > 0 ? this.inventoryList[0].inventoryId : null;
}
}
this.syncDetails(this.initDetails.length === 0);
},
// 修复:提交逻辑 - 确保严格模式同步后再提交
handleSubmit() {
if (!this.form.materialId?.trim()) {
this.$message.error('请先选择物料ID');
......@@ -639,7 +688,6 @@ export default {
return;
}
// 强制严格模式同步
this.syncDetails(true);
if (this.details.length === 0) {
......@@ -647,14 +695,12 @@ export default {
return;
}
// 移除重复的校验逻辑(已在syncDetails中处理)
const submitDetails = this.details.map(detail => ({
...detail,
outboundOrderId: this.form.outboundOrderId || detail.outboundOrderId,
materialId: this.form.materialId || detail.materialId
}));
// 调试:打印提交的数据
console.log('提交的明细数据:', submitDetails);
this.$emit('submit', submitDetails);
......@@ -679,11 +725,10 @@ export default {
this.$emit('update:open', false);
},
handleMaterialSelectionChange() {
// 核心修改:将物料选择器返回的sap_no作为物料ID
const selectedData = this.$refs.materialsSeletor?.getSelectedMaterials?.() || this.$refs.materialsSeletor?.selectedList || [];
if (selectedData && selectedData.length > 0) {
this.selectedMaterialInfo = selectedData[0];
// 替换:使用sapNo作为物料ID
if (selectedData) {
this.selectedMaterialInfo = selectedData;
this.selectedMaterialId = this.selectedMaterialInfo.sapNo || this.selectedMaterialInfo.materialId || '';
console.log("选中的SAP物料号:", this.selectedMaterialId);
} else {
......@@ -691,7 +736,6 @@ export default {
this.selectedMaterialId = '';
}
},
// 修复:物料选择后的数据赋值 - 核心替换为sap_no
confirmMaterialSelect() {
this.handleMaterialSelectionChange();
if (!this.selectedMaterialId) {
......@@ -699,7 +743,6 @@ export default {
return;
}
// 核心修改:将sapNo赋值给materialId和materialUuids
this.$set(this.form, 'materialId', this.selectedMaterialInfo.sapNo || this.selectedMaterialId);
this.$set(this.form, 'materialUuids', this.selectedMaterialInfo.sapNo || this.selectedMaterialId);
......@@ -755,7 +798,6 @@ export default {
}
}
/* 优化禁用状态样式 */
/deep/ .el-input.is-disabled {
background-color: #f5f7fa;
cursor: not-allowed;
......
......@@ -373,7 +373,7 @@
<div v-for="(group, materialId) in outboundOrderItemsGroup" :key="materialId" class="material-group mb10">
<div class="group-header" style="background: #f5f7fa; padding: 8px 12px; border-radius: 4px; margin-bottom: 8px;">
<span style="font-weight: 600; margin-right: 16px;">物料ID{{ materialId }}</span>
<span style="font-weight: 600; margin-right: 16px;">物料{{ materialId+" "+ getMaterialName(materialId) }}</span>
<span style="color: #666;">明细数量:{{ group.items.length }} </span>
<!-- 仅编辑模式显示分组操作按钮 -->
<el-button
......@@ -391,7 +391,6 @@
:row-class-name="(params) => rowInboundOrderItemsIndex(params, group.items)"
@selection-change="handleInboundOrderItemsSelectionChange"
ref="inboundOrderItems"
border
style="width: 100%;"
:row-key="item => item.inventoryId"
:disabled="isViewDetail"
......@@ -399,8 +398,8 @@
<!-- 仅编辑模式显示选择列 -->
<el-table-column type="selection" width="50" align="center" v-if="!isViewDetail" />
<el-table-column label="序号" align="center" prop="index" width="50"/>
<el-table-column label="物料编号" prop="materialId" width="150" />
<el-table-column label="仓库编号" prop="warehouseId" width="150" />
<el-table-column label="物料编号" prop="materialId" width="180"/>
<!-- <el-table-column label="仓库编号" prop="warehouseId" width="150" /> -->
<el-table-column label="库位编号" prop="locationId" width="150" />
<el-table-column label="批次编号" prop="batchCode" width="150" />
......@@ -439,6 +438,7 @@
:init-details="getInitDetails()"
:group-data="currentGroupData"
:outbound-order-id="form.orderId || form.outboundOrderId"
:materialdicts="materialdicts"
@submit="handleDetailSubmit"
@close="detailDialogOpen = false"
@update:open="detailDialogOpen = $event"
......@@ -466,6 +466,8 @@
<script>
import { listOrders, getOrders, delOrders, addOrders, updateOrders, ship } from "@/api/inventory/orders"
import { getMaterialsdicts } from "@/api/inventory/materials"
import OutboundOrderFormWithItems from './OutboundOrderFormWithItems.vue'
import WarehouseSelector from "@/views/compononents/WarehouseSelector.vue"
import LocationSelector from "@/views/compononents/LocationSelector.vue"
......@@ -484,6 +486,7 @@ export default {
},
data() {
return {
materialdicts:[],
// 添加tableKey解决tableId渲染问题
tableKey: 1,
// 遮罩层
......@@ -600,22 +603,33 @@ export default {
created() {
// 延迟加载避免初始化渲染问题
this.$nextTick(() => {
this.getdicts(),
this.getList()
})
},
methods: {
// 货主选择回调
handleOwnerSelected(owner) {
if (!owner) return
if (this.ownerSelectTarget === 'query') {
this.queryParams.ownerId = owner.ownerId || owner.id
this.queryOwnerName = owner.ownerName || owner.name
this.handleQuery()
} else {
this.form.ownerId = owner.ownerId || owner.id
this.form.ownerName = owner.ownerName || owner.name
}
this.ownerSelectorVisible = false
getMaterialName(materialId) {
if (!materialId || !this.materialdicts.length) return '未知物料';
// 精准匹配(如果需要模糊匹配,把 === 改成 includes 即可)
const matchItem = this.materialdicts.find(item =>
String(item.value) === String(materialId)
);
return matchItem ? matchItem.label : '未知物料';
},
getdicts(){
return getMaterialsdicts()
.then(response => {
this.materialdicts = (response.data || response).map(item => ({
value: item.sap_no,
label: item.material_name,
}));
console.log("物料字典数据加载成功:", this.materialdicts);
})
.catch(error => {
console.error("加载物料字典失败:", error);
this.$message.error("物料字典加载失败,请刷新重试");
});
},
// 仓库选择回调
handleWarehouseSelected(warehouse) {
......@@ -650,6 +664,25 @@ export default {
this.ownerSelectTarget = target
this.ownerSelectorVisible = true
},
// 货主选择回调(核心缺失方法)
handleOwnerSelected(owner) {
if (!owner) return
if (this.ownerSelectTarget === 'query') {
this.queryParams.ownerId = owner.ownerId || owner.id
this.queryOwnerName = owner.ownerName || owner.name
this.handleQuery()
} else {
this.form.ownerId = owner.ownerId || owner.id
this.form.ownerName = owner.ownerName || owner.name
// 更新明细中的默认货主(可选)
if (this.currentDetailItem) {
this.currentDetailItem.ownerId = owner.ownerId || owner.id
this.currentDetailItem.ownerName = owner.ownerName || owner.name
}
}
this.ownerSelectorVisible = false
},
// 打开仓库选择器
openWarehouseSelector(target = 'form') {
this.warehouseSelectTarget = target
......
......@@ -30,7 +30,7 @@ public interface MaterialsMapper
* @param id 物料主键
* @return 物料
*/
public List<Materials> selectMaterialsByMaterialsCode(String id);
public List<Materials> selectMaterialsBySapNo(String id);
/**
* 查询物料列表
......
......@@ -65,5 +65,5 @@ public interface OutboundOrderItemsMapper
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deleteOutboundOrderItemsByIds(String[] ids);
public int deleteOutboundOrderItemsById(String[] ids);
}
......@@ -2,7 +2,6 @@ package com.ruoyi.inventory.mapper;
import java.util.List;
import com.ruoyi.inventory.domain.ReturnOrderItems;
import com.ruoyi.inventory.domain.ReturnOrders;
import com.ruoyi.inventory.domain.vo.ReturnOrdersSummaryVO;
/**
......
......@@ -106,4 +106,5 @@ public interface IInventoryService
* @return 库存明细集合
*/
public List<Inventory> selectInventoryDetailList(Inventory inventory);
}
......@@ -4,11 +4,10 @@ import java.util.*;
import java.util.stream.Collectors;
import com.ruoyi.common.annotation.SerialExecution;
import com.ruoyi.common.core.domain.entity.Materials;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.inventory.domain.OutboundOrderItems;
import com.ruoyi.inventory.domain.OutboundOrderLog;
import com.ruoyi.inventory.domain.StocktakeItems;
import com.ruoyi.inventory.domain.TO.StocktakeItemsTo;
import com.ruoyi.inventory.domain.vo.InventorySummaryVO;
import com.ruoyi.inventory.mapper.OutboundOrderItemsMapper;
import com.ruoyi.inventory.mapper.OutboundOrderLogMapper;
......@@ -233,7 +232,7 @@ public class InventoryServiceImpl implements IInventoryService
* @date 2025/12/3
* @version 1.0
*/
public List<StocktakeItems> selectstocktakeItemsList(){
public List<StocktakeItemsTo> selectstocktakeItemsList(){
return inventoryMapper.selectstocktakeItemsList();
}
......
......@@ -81,7 +81,7 @@ public class OutboundOrderItemsServiceImpl implements IOutboundOrderItemsService
@Override
public int deleteOutboundOrderItemsByIds(String[] ids)
{
return outboundOrderItemsMapper.deleteOutboundOrderItemsByIds(ids);
return outboundOrderItemsMapper.deleteOutboundOrderItemsById(ids);
}
/**
......
......@@ -41,6 +41,11 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
private OutboundOrderLogMapper outboundOrderLogMapper;
@Autowired
private OwnersServiceImpl ownersService;
@Autowired
private WarehousesServiceImpl warehousesService;
@Autowired
private InventoryServiceImpl inventoryService;
/**
* 查询出库单主
......@@ -64,7 +69,8 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
@Override
public List<OutboundOrders> selectOutboundOrdersList(OutboundOrders outboundOrders)
{
return outboundOrdersMapper.selectOutboundOrdersList(outboundOrders);
List<OutboundOrders> outboundOrders1 = outboundOrdersMapper.selectOutboundOrdersList(outboundOrders);
return outboundOrders1;
}
/**
......@@ -80,6 +86,7 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
outboundOrders.setCreateTime(DateUtils.getNowDate());
outboundOrders.setCreateBy(SystemUtils.getUserName());
outboundOrders.setId(UUID.randomUUID().toString());
int rows = outboundOrdersMapper.insertOutboundOrders(outboundOrders);
insertOutboundOrderItems(outboundOrders);
return rows;
......@@ -95,9 +102,12 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
@Override
public int updateOutboundOrders(OutboundOrders outboundOrders)
{
outboundOrders.setUpdateTime(DateUtils.getNowDate());
outboundOrdersMapper.deleteOutboundOrderItemsByOrderId(outboundOrders.getId());
outboundOrderLogMapper.deleteOutboundOrderLogByOrdersId(outboundOrders.getId());
outboundOrders.setUpdateBy(SystemUtils.getUserName());
outboundOrders.setUpdateTime(DateUtils.getNowDate());
insertOutboundOrderItems(outboundOrders);
return outboundOrdersMapper.updateOutboundOrders(outboundOrders);
}
......@@ -197,6 +207,7 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
for (OutboundOrderItems items : outboundOrderItemsList) {
OutboundOrderLog log = new OutboundOrderLog();
BeanUtils.copyProperties(items, log); // 单个对象属性拷贝
log.setOrderId(items.getId());
outboundOrderLogs.add(log);
inventoryIds.add(log.getInventoryId());
deleteOutboundOrdersById(items.getId());
......
......@@ -76,7 +76,7 @@ public class StorageLocationsServiceImpl implements IStorageLocationsService
String[] AllowedCategoryIds = storageLocations2.getAllowedCategoryIds().split(",");
for (String AllowedCategoryId : AllowedCategoryIds) {
List<Materials> materials = materialsMapper.selectMaterialsByMaterialsCode(AllowedCategoryId);
List<Materials> materials = materialsMapper.selectMaterialsBySapNo(AllowedCategoryId);
if (materials != null && !materials.isEmpty()) {
Materials materials1 = materials.get(0);
......@@ -120,7 +120,7 @@ public class StorageLocationsServiceImpl implements IStorageLocationsService
storageLocationsCategory.setCategoryId(categoryId);
storageLocationsCategory.setCreateTime(DateUtils.getNowDate());
storageLocationsCategory.setCreateUserCode(String.valueOf(SecurityUtils.getUserId()));
List<Materials> materials = materialsMapper.selectMaterialsByMaterialsCode(categoryId);
List<Materials> materials = materialsMapper.selectMaterialsBySapNo(categoryId);
if (materials != null && !materials.isEmpty()) {
Materials materials1 = materials.get(0);
storageLocationsCategory.setCategoryName(materials1.getMaterialName());
......@@ -159,7 +159,7 @@ public class StorageLocationsServiceImpl implements IStorageLocationsService
storageLocationsCategory.setCategoryId(categoryId);
storageLocationsCategory.setUpdateTime(DateUtils.getNowDate());
storageLocationsCategory.setUpdateUserCode(String.valueOf(SecurityUtils.getUserId()));
List<Materials> materials = materialsMapper.selectMaterialsByMaterialsCode(categoryId);
List<Materials> materials = materialsMapper.selectMaterialsBySapNo(categoryId);
if (materials != null && !materials.isEmpty()) {
Materials materials1 = materials.get(0);
storageLocationsCategory.setCategoryName(materials1.getMaterialName());
......
......@@ -4,7 +4,7 @@
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.inventory.mapper.InboundOrderItemsMapper">
<resultMap type="InboundOrderItems" id="InboundOrderItemsResult">
<resultMap type="com.ruoyi.inventory.domain.InboundOrderItems" id="InboundOrderItemsResult">
<result property="id" column="id" />
<result property="orderId" column="order_id" />
<result property="materialId" column="material_id" />
......@@ -38,7 +38,7 @@
select id, order_id, material_id, batch_id, warehouse_id, location_id, planned_quantity, actual_quantity, planned_packages, actual_packages, divisor, label_color, voucher_number, unit_price, item_status, received_at, received_by, remark, is_used, sort_no, create_time, create_user_code, update_time, update_user_code,inbound_order_id from inbound_order_items
</sql>
<select id="selectInboundOrderItemsList" parameterType="InboundOrderItems" resultMap="InboundOrderItemsResult">
<select id="selectInboundOrderItemsList" parameterType="com.ruoyi.inventory.domain.InboundOrderItems" resultMap="InboundOrderItemsResult">
<include refid="selectInboundOrderItemsVo"/>
<where>
<if test="inboundOrderId != null and inboundOrderId != ''"> and inbound_order_id = #{inboundOrderId}</if>
......@@ -73,7 +73,7 @@
<select id="selectInboundOrderItemsListAndMaterialName"
parameterType="InboundOrderItems"
parameterType="com.ruoyi.inventory.domain.InboundOrderItems"
resultMap="InboundOrderItemsAndMnameResult">
SELECT
ii.id,
......@@ -110,7 +110,7 @@
and inbound_order_id = #{inboundOrderId}
</if>
<if test="orderId != null and orderId != ''">
order_id = #{orderId}
and order_id = #{orderId}
</if>
<if test="materialId != null and materialId != ''">
and material_id = #{materialId}
......@@ -173,7 +173,7 @@
</where>
</select>
<insert id="insertInboundOrderItems" parameterType="InboundOrderItems">
<insert id="insertInboundOrderItems" parameterType="com.ruoyi.inventory.domain.InboundOrderItems">
insert into inbound_order_items
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">id,</if>
......@@ -231,7 +231,7 @@
</trim>
</insert>
<update id="updateInboundOrderItems" parameterType="InboundOrderItems">
<update id="updateInboundOrderItems" parameterType="com.ruoyi.inventory.domain.InboundOrderItems">
update inbound_order_items
<trim prefix="SET" suffixOverrides=",">
<if test="orderId != null">order_id = #{orderId},</if>
......
......@@ -76,9 +76,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
where id = #{id}
order by sort_no asc
</select>
<select id="selectMaterialsByMaterialsCode" parameterType="String" resultMap="MaterialsResult">
<select id="selectMaterialsBySapNo" parameterType="String" resultMap="MaterialsResult">
<include refid="selectMaterialsVo"/>
where material_code = #{id}
where sap_no = #{id}
order by sort_no asc
</select>
<select id="selectMaterialsByCategory" parameterType="String" resultMap="MaterialsResult">
......
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.inventory.mapper.OutboundOrderItemsMapper">
<resultMap type="OutboundOrderItems" id="OutboundOrderItemsResult">
......@@ -58,6 +58,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="updateTime" column="update_time" />
<result property="updateUserCode" column="update_user_code" />
</resultMap>
<sql id="selectOutboundOrderItemsVo">
select id, order_id, material_id, batch_code, warehouse_id, location_id, inventory_id, outbound_order_id, unit_price, planned_quantity, actual_quantity, divisor, label_color, voucher_number, item_status, shipped_at, shipped_by, remark, is_used, sort_no, create_time, create_user_code, update_time, update_user_code from outbound_order_items
</sql>
......@@ -65,6 +66,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="selectOutboundOrderItemsList" parameterType="OutboundOrderItems" resultMap="OutboundOrderItemsResult">
<include refid="selectOutboundOrderItemsVo"/>
<where>
<if test="isUsed == null">
is_used = 1
</if>
<if test="isUsed != null">
is_used = #{isUsed}
</if>
<if test="orderId != null and orderId != ''"> and order_id = #{orderId}</if>
<if test="materialId != null and materialId != ''"> and material_id = #{materialId}</if>
<if test="batchCode != null and batchCode != ''"> and batch_code = #{batchCode}</if>
......@@ -79,16 +86,23 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="itemStatus != null "> and item_status = #{itemStatus}</if>
<if test="shippedAt != null "> and shipped_at = #{shippedAt}</if>
<if test="shippedBy != null and shippedBy != ''"> and shipped_by = #{shippedBy}</if>
<if test="isUsed != null "> and is_used = #{isUsed}</if>
<if test="sortNo != null "> and sort_no = #{sortNo}</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>
</where>
</select>
<!-- 单条查询:默认查使用中,若手动传isUsed则覆盖 -->
<select id="selectOutboundOrderItemsById" parameterType="String" resultMap="OutboundOrderItemsResult">
<include refid="selectOutboundOrderItemsVo"/>
where id = #{id}
<!-- 增加is_used过滤,避免查询已逻辑删除的数据 -->
<if test="isUsed == null">
and is_used = 1
</if>
<if test="isUsed != null">
and is_used = #{isUsed}
</if>
</select>
<insert id="insertOutboundOrderItems" parameterType="OutboundOrderItems">
......@@ -112,6 +126,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="shippedAt != null">shipped_at,</if>
<if test="shippedBy != null">shipped_by,</if>
<if test="remark != null">remark,</if>
<if test="isUsed == null">is_used,</if>
<if test="isUsed != null">is_used,</if>
<if test="sortNo != null">sort_no,</if>
<if test="createTime != null">create_time,</if>
......@@ -138,6 +153,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="shippedAt != null">#{shippedAt},</if>
<if test="shippedBy != null">#{shippedBy},</if>
<if test="remark != null">#{remark},</if>
<if test="isUsed == null">1,</if>
<if test="isUsed != null">#{isUsed},</if>
<if test="sortNo != null">#{sortNo},</if>
<if test="createTime != null">#{createTime},</if>
......@@ -177,10 +193,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
where id = #{id}
</update>
<delete id="deleteOutboundOrderItemsById" parameterType="String">
delete from outbound_order_items where id = #{id}
</delete>
<!-- 单条删除:逻辑删除 -->
<update id="deleteOutboundOrderItemsById" parameterType="String">
update outbound_order_items
set is_used = 0
where id = #{id}
</update>
<!-- 统计查询:默认查is_used=1,支持手动传isUsed覆盖 -->
<select id="selectOutboundOrderItemsStatistics"
parameterType="OutboundOrderItemsStatisticsVO"
resultMap="OutboundOrderItemsStatisticsVoResult">
......@@ -211,7 +231,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
oi.update_user_code
FROM outbound_order_items oi
LEFT JOIN outbound_orders o ON oi.outbound_order_id = o.id
WHERE oi.is_used = 1
<where>
<if test="isUsed == null">
oi.is_used = 1
</if>
<if test="isUsed != null">
oi.is_used = #{isUsed}
</if>
<if test="orderId != null and orderId != ''">
AND o.order_id LIKE CONCAT('%', #{orderId}, '%')
</if>
......@@ -233,14 +259,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="itemStatus != null and itemStatus != ''">
AND oi.item_status = #{itemStatus}
</if>
</where>
ORDER BY oi.create_time DESC
</select>
<delete id="deleteOutboundOrderItemsByIds" parameterType="String">
delete from outbound_order_items where id in
<!-- 批量删除:逻辑删除 -->
<update id="deleteOutboundOrderItemsByIds" parameterType="String">
update outbound_order_items
set is_used = 0
where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</update>
</mapper>
......@@ -24,7 +24,7 @@
<select id="selectOutboundOrderLogList" parameterType="OutboundOrderLog" resultMap="OutboundOrderLogResult">
<include refid="selectOutboundOrderLogVo"/>
<where>
where is_used=1
<if test="orderId != null and orderId != ''"> and order_id = #{orderId}</if>
<if test="inventoryId != null and inventoryId != ''"> and inventory_id = #{inventoryId}</if>
<if test="materialId != null and materialId != ''"> and material_id = #{materialId}</if>
......@@ -32,34 +32,29 @@
<if test="batchCode != null and batchCode != ''"> and batch_code = #{batchCode}</if>
<if test="actualQuantity != null "> and actual_quantity = #{actualQuantity}</if>
<if test="itemStatus != null "> and item_status = #{itemStatus}</if>
<if test="isUsed != null "> and is_used = #{isUsed}</if>
</where>
</select>
<select id="deleteLog" parameterType="OutboundOrderLog" resultMap="OutboundOrderLogResult">
delete from outbound_order_log
<update id="deleteLog" parameterType="OutboundOrderLog">
update outbound_order_log set is_used=0
<where>
<if test="materialId != null and materialId != ''"> and material_id = #{materialId}</if>
<if test="warehouseId != null and warehouseId != ''"> and warehouse_id = #{warehouseId}</if>
<if test="batchCode != null and batchCode != ''"> and batch_code = #{batchCode}</if>
<if test="itemStatus != null "> and item_status = #{itemStatus}</if>
<!-- 补充inventory_id条件 -->
<if test="inventoryId != null and inventoryId != ''"> and inventory_id = #{inventoryId}</if>
</where>
</select>
</update>
<!-- 修正参数错误:原#{id}改为#{inventoryId} -->
<select id="selectLockedQuantityByInventory" parameterType="OutboundOrderLog" resultType="java.lang.Long">
select ifnull(sum(actual_quantity), 0)
from outbound_order_log
where item_status=1
where item_status=1 and is_used=1
<if test="inventoryId != null and inventoryId != ''"> and inventory_id = #{inventoryId}</if>
</select>
<select id="selectOutboundOrderLogById" parameterType="String" resultMap="OutboundOrderLogResult">
<include refid="selectOutboundOrderLogVo"/>
where id = #{id}
where id = #{id} and is_used=1
</select>
<!-- 插入语句补充inventory_id -->
......@@ -105,20 +100,20 @@
where id = #{id}
</update>
<delete id="deleteOutboundOrderLogById" parameterType="String">
delete from outbound_order_log where id = #{id}
</delete>
<update id="deleteOutboundOrderLogById" parameterType="String">
update outbound_order_log set is_used=0 where id = #{id}
</update>
<delete id="deleteOutboundOrderLogByOrdersId" parameterType="String">
delete from outbound_order_log where order_id = #{id}
</delete>
<update id="deleteOutboundOrderLogByOrdersId" parameterType="String">
update outbound_order_log set is_used=0 where order_id = #{id}
</update>
<delete id="deleteOutboundOrderLogByOrdersIds" parameterType="String">
delete from outbound_order_log where order_id in
<update id="deleteOutboundOrderLogByOrdersIds" parameterType="String">
update outbound_order_log set is_used=0 where order_id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</update>
<!-- 批量插入补充inventory_id -->
......
......@@ -4,7 +4,7 @@
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.inventory.mapper.OutboundOrdersMapper">
<resultMap type="OutboundOrders" id="OutboundOrdersResult">
<resultMap type="com.ruoyi.inventory.domain.OutboundOrders" id="OutboundOrdersResult">
<result property="id" column="id" />
<result property="orderId" column="order_id" />
<result property="systemNo" column="system_no" />
......@@ -27,12 +27,17 @@
<result property="updateUserCode" column="update_user_code" />
</resultMap>
<resultMap id="OutboundOrdersOutboundOrderItemsResult" type="OutboundOrders" extends="OutboundOrdersResult">
<collection property="outboundOrderItemsList" ofType="OutboundOrderItems" column="id" select="selectOutboundOrderItemsList" />
<!-- 核心修复:删除重复的collection,只保留一个正确的关联配置 -->
<resultMap id="OutboundOrdersOutboundOrderItemsResult" type="com.ruoyi.inventory.domain.OutboundOrders" extends="OutboundOrdersResult">
<collection
property="outboundOrderItemsList"
ofType="com.ruoyi.inventory.domain.OutboundOrderItems"
column="id"
select="selectOutboundOrderItemsList" />
</resultMap>
<!-- 修复:仅保留子表outbound_order_items的字段映射,删除错误的主表字段 -->
<resultMap type="OutboundOrderItems" id="OutboundOrderItemsResult">
<!-- 原主表结果映射:仅修复InboundOrderId大小写,其余完全保留 -->
<resultMap type="com.ruoyi.inventory.domain.OutboundOrderItems" id="OutboundOrderItemsResult">
<result property="id" column="id" />
<result property="orderId" column="order_id" />
<result property="materialId" column="material_id" />
......@@ -57,17 +62,17 @@
<result property="createUserCode" column="create_user_code" />
<result property="updateTime" column="update_time" />
<result property="updateUserCode" column="update_user_code" />
<result property="InboundOrderId" column="inbound_order_id" />
<result property="inboundOrderId" column="inbound_order_id" />
</resultMap>
<!-- 以下所有代码完全保留,不做任何修改 -->
<sql id="selectOutboundOrdersVo">
select id, order_id, system_no, order_type_id, batch_code, warehouse_id, owner_id, order_status, inbound_date, destination, total_planned_quantity, total_actual_quantity, total_packages, remark, is_used, sort_no, create_time, create_user_code, update_time, update_user_code from outbound_orders
</sql>
<select id="selectOutboundOrdersList" parameterType="OutboundOrders" resultMap="OutboundOrdersResult">
<include refid="selectOutboundOrdersVo"/>
<where>
where is_used = 1
<if test="orderId != null and orderId != ''"> and order_id = #{orderId}</if>
<if test="systemNo != null and systemNo != ''"> and system_no = #{systemNo}</if>
<if test="orderTypeId != null and orderTypeId != ''"> and order_type_id = #{orderTypeId}</if>
......@@ -80,24 +85,21 @@
<if test="totalPlannedQuantity != null "> and total_planned_quantity = #{totalPlannedQuantity}</if>
<if test="totalActualQuantity != null "> and total_actual_quantity = #{totalActualQuantity}</if>
<if test="totalPackages != null "> and total_packages = #{totalPackages}</if>
<if test="isUsed != null "> and is_used = #{isUsed}</if>
<if test="sortNo != null "> and sort_no = #{sortNo}</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>
</where>
</select>
<select id="selectOutboundOrdersById" parameterType="String" resultMap="OutboundOrdersOutboundOrderItemsResult">
select id, order_id, system_no, order_type_id, batch_code, warehouse_id, owner_id, order_status, inbound_date, destination, total_planned_quantity, total_actual_quantity, total_packages, remark, is_used, sort_no, create_time, create_user_code, update_time, update_user_code
from outbound_orders
where id = #{id}
where id = #{id} and is_used=1
</select>
<!-- 仅保留子表查询逻辑,字段完整且映射正确 -->
<select id="selectOutboundOrderItemsList" parameterType="String" resultMap="OutboundOrderItemsResult">
select id, order_id, material_id, batch_code, warehouse_id, location_id, inventory_id, outbound_order_id, unit_price, planned_quantity, actual_quantity, divisor, label_color, voucher_number, item_status, shipped_at, shipped_by, remark, is_used, sort_no, create_time, create_user_code, update_time, update_user_code
from outbound_order_items
where order_id = #{id}
where outbound_order_id = #{id} AND is_used=1
</select>
<insert id="insertOutboundOrders" parameterType="OutboundOrders">
......@@ -174,26 +176,26 @@
where id = #{id}
</update>
<delete id="deleteOutboundOrdersById" parameterType="String">
delete from outbound_orders where id = #{id}
</delete>
<update id="deleteOutboundOrdersById" parameterType="String">
update outbound_orders set is_used=0 where id = #{id}
</update>
<delete id="deleteOutboundOrdersByIds" parameterType="String">
delete from outbound_orders where id in
<update id="deleteOutboundOrdersByIds" parameterType="String">
update outbound_orders set is_used=0 where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</update>
<delete id="deleteOutboundOrderItemsByOrderIds" parameterType="String">
delete from outbound_order_items where outbound_order_id in
<update id="deleteOutboundOrderItemsByOrderIds" parameterType="String">
update outbound_order_items set is_used=0 where outbound_order_id in
<foreach item="orderId" collection="array" open="(" separator="," close=")">
#{orderId}
</foreach>
</delete>
</update>
<delete id="deleteOutboundOrderItemsByOrderId" parameterType="String">
delete from outbound_order_items where outbound_order_id = #{orderId}
update outbound_order_items set is_used=0 where outbound_order_id = #{orderId}
</delete>
<insert id="batchOutboundOrderItems">
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论