Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
M
mini-wms
概览
Overview
Details
Activity
Cycle Analytics
版本库
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
问题
0
Issues
0
列表
Board
标记
里程碑
合并请求
0
Merge Requests
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
Snippets
成员
Members
Collapse sidebar
Close sidebar
活动
图像
聊天
创建新问题
作业
提交
Issue Boards
Open sidebar
周海峰
mini-wms
Commits
e76b86c2
Commit
e76b86c2
authored
Dec 02, 2025
by
yubin
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/master'
parents
9a9aa266
dec88768
显示空白字符变更
内嵌
并排
正在显示
16 个修改的文件
包含
1406 行增加
和
179 行删除
+1406
-179
ruoyi-admin-vue/src/api/inventory/materials_category.js
+9
-0
ruoyi-admin-vue/src/views/inventory/materials/index.vue
+296
-86
ruoyi-admin-vue/src/views/inventory/materials_category/index.vue
+498
-82
ruoyi-admin-vue/src/views/inventory/materials_category/treeComponent.vue
+377
-0
ruoyi-admin-vue/src/views/system/user/index.vue
+10
-1
ruoyi-admin/src/main/java/com/ruoyi/web/controller/inventory/MaterialsCategoryController.java
+12
-1
ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java
+1
-0
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java
+17
-1
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/MaterialsCategory.java
+49
-1
ruoyi-inventory/pom.xml
+2
-0
ruoyi-inventory/src/main/java/com/ruoyi/inventory/mapper/MaterialsCategoryMapper.java
+1
-2
ruoyi-inventory/src/main/java/com/ruoyi/inventory/mapper/MaterialsMapper.java
+6
-1
ruoyi-inventory/src/main/java/com/ruoyi/inventory/service/IMaterialsCategoryService.java
+27
-1
ruoyi-inventory/src/main/java/com/ruoyi/inventory/service/impl/MaterialsCategoryServiceImpl.java
+89
-1
ruoyi-inventory/src/main/resources/mapper/inventory/MaterialsCategoryMapper.xml
+11
-1
ruoyi-inventory/src/main/resources/mapper/inventory/MaterialsMapper.xml
+1
-1
没有找到文件。
ruoyi-admin-vue/src/api/inventory/materials_category.js
View file @
e76b86c2
...
...
@@ -42,3 +42,11 @@ export function delMaterials_category(id) {
method
:
'delete'
})
}
// 查询部门下拉树结构
export
function
categoryTreeSelect
()
{
return
request
({
url
:
'/inventory/materials_category/categoryTree'
,
method
:
'get'
})
}
\ No newline at end of file
ruoyi-admin-vue/src/views/inventory/materials/index.vue
View file @
e76b86c2
<
template
>
<div
class=
"app-container"
>
<div
class=
"app-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"
>
<span>
{{
node
.
label
}}
</span>
</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"
v-show=
"showSearch"
label-width=
"88px"
>
<el-form-item
label=
"物料编码"
prop=
"materialCode"
>
<el-input
...
...
@@ -33,9 +61,9 @@
@
keyup
.
enter
.
native=
"handleQuery"
/>
</el-form-item>
<el-form-item
label=
"物料分类"
prop=
"categoryCode
"
>
<el-form-item
label=
"物料分类"
prop=
"categoryNameInput
"
>
<el-input
v-model=
"queryParams.categoryCode
"
v-model=
"queryParams.categoryNameInput
"
placeholder=
"请输入物料分类"
clearable
@
keyup
.
enter
.
native=
"handleQuery"
...
...
@@ -108,19 +136,11 @@
v-hasPermi=
"['inventory:materials:export']"
>
导出
</el-button>
</el-col>
<el-col
:span=
"1.5"
>
<el-button
type=
"primary"
icon=
"el-icon-s-grid"
size=
"mini"
@
click=
"openMaterialsCategory"
v-hasPermi=
"['inventory:materials:category']"
>
物料分类管理
</el-button>
</el-col>
<right-toolbar
:showSearch
.
sync=
"showSearch"
@
queryTable=
"getList"
></right-toolbar>
</el-row>
<el-table
v-loading=
"loading"
:data=
"materialsList"
@
selection-change=
"handleSelectionChange"
:scroll-x=
"true"
>
<!-- 表格列保持不变 -->
<el-table-column
type=
"selection"
width=
"55"
align=
"center"
/>
<el-table-column
type=
"index"
label=
"序号"
align=
"center"
/>
<el-table-column
label=
"物料编码"
align=
"center"
prop=
"materialCode"
/>
...
...
@@ -129,7 +149,7 @@
<el-table-column
label=
"TS Code"
align=
"center"
prop=
"tsCode"
/>
<el-table-column
label=
"物料分类"
align=
"center"
prop=
"categoryCode"
>
<
template
slot-scope=
"scope"
>
{{
categoryMap
[
scope
.
row
.
categoryCode
]
||
scope
.
row
.
categoryCode
}}
{{
scope
.
row
.
displayCategory
||
categoryMap
[
scope
.
row
.
categoryCode
]
||
scope
.
row
.
categoryCode
}}
</
template
>
</el-table-column>
<el-table-column
label=
"危险类别ID"
align=
"center"
prop=
"hazardId"
/>
...
...
@@ -198,6 +218,9 @@
:
limit
.
sync
=
"queryParams.pageSize"
@
pagination
=
"getList"
/>
<
/div
>
<
/pane
>
<
/splitpanes
>
<!--
添加或修改物料对话框
-->
<
el
-
dialog
:
title
=
"title"
:
visible
.
sync
=
"open"
width
=
"900px"
append
-
to
-
body
>
...
...
@@ -211,8 +234,13 @@
<
el
-
input
v
-
model
=
"form.sapNo"
placeholder
=
"请输入SAP物料号"
/>
<
/el-form-item
>
<
el
-
form
-
item
label
=
"物料分类"
prop
=
"categoryCode"
>
<
el
-
select
v
-
model
=
"form.categoryCode"
placeholder
=
"请选择物料分类"
clearable
@
click
=
"getCategoryList"
>
<
el
-
option
v
-
for
=
"item in categoryOptions"
:
key
=
"item.value"
:
label
=
"item.label"
:
value
=
"item.value"
>
<
el
-
select
v
-
model
=
"form.categoryCode"
placeholder
=
"请选择物料分类"
clearable
>
<
el
-
option
v
-
for
=
"item in categoryTreeOptions"
:
key
=
"item.categoryCode"
:
label
=
"item.categoryName"
:
value
=
"item.categoryCode"
>
<
/el-option
>
<
/el-select
>
<
/el-form-item
>
...
...
@@ -243,9 +271,6 @@
<
el
-
form
-
item
label
=
"风险等级"
prop
=
"riskLevel"
>
<
el
-
input
v
-
model
=
"form.riskLevel"
placeholder
=
"请输入风险等级"
/>
<
/el-form-item
>
<!--
<
el
-
form
-
item
label
=
"创建人编码"
prop
=
"createUserCode"
>
<
el
-
input
v
-
model
=
"form.createUserCode"
placeholder
=
"请输入创建人编码"
/>
<
/el-form-item> --
>
<
/el-col
>
<
el
-
col
:
span
=
"12"
>
<
el
-
form
-
item
label
=
"物料名称"
prop
=
"materialName"
>
...
...
@@ -287,9 +312,6 @@
<
el
-
form
-
item
label
=
"排序"
prop
=
"sortNo"
>
<
el
-
input
v
-
model
=
"form.sortNo"
placeholder
=
"请输入排序"
/>
<
/el-form-item
>
<!--
<
el
-
form
-
item
label
=
"更新人编码"
prop
=
"updateUserCode"
>
<
el
-
input
v
-
model
=
"form.updateUserCode"
placeholder
=
"请输入更新人编码"
/>
<
/el-form-item> --
>
<
/el-col
>
<
/el-row
>
<
/el-form
>
...
...
@@ -299,21 +321,6 @@
<
/div
>
<
/el-dialog
>
<!--
物料分类管理抽屉
-->
<
el
-
drawer
title
=
"物料分类管理"
:
visible
.
sync
=
"parentDialogVisible"
direction
=
"rtl"
size
=
"80%"
append
-
to
-
body
>
<
MaterialsCategory
ref
=
"materialsCategoryRef"
:
init
-
query
=
"{ categoryCode: queryParams.categoryCode
}
"
@
dialog
-
close
=
"parentDialogVisible = false"
@
form
-
submit
=
"handleCategorySubmit"
/>
<
/el-drawer
>
<
import
-
excel
ref
=
"import"
title
=
"导入"
...
...
@@ -328,37 +335,61 @@
<
script
>
import
{
listMaterials
,
getMaterials
,
delMaterials
,
addMaterials
,
updateMaterials
}
from
"@/api/inventory/materials"
import
{
listMaterials_category
}
from
"@/api/inventory/materials_category"
import
MaterialsCategory
from
"@/views/inventory/materials_category/index.vue"
import
TreeComponent
from
'@/views/inventory/materials_category/treeComponent.vue'
import
{
Splitpanes
,
Pane
}
from
'splitpanes'
import
'splitpanes/dist/splitpanes.css'
import
Treeselect
from
"@riophae/vue-treeselect"
import
"@riophae/vue-treeselect/dist/vue-treeselect.css"
import
ImportExcel
from
"@/components/ImportExcel/index"
export
default
{
components
:
{
MaterialsCategory
,
ImportExcel
}
,
name
:
"Materials"
,
components
:
{
TreeComponent
,
Splitpanes
,
Pane
,
Treeselect
,
ImportExcel
}
,
data
()
{
return
{
// 树相关数据
categoryTreeData
:
[],
treeProps
:
{
children
:
'children'
,
label
:
'label'
,
value
:
'sid'
}
,
nodeKey
:
'sid'
,
loadingTree
:
false
,
// 分类映射和选项
categoryMap
:
{
}
,
categoryForm
:
''
,
categoryOptions
:
[],
// 遮罩层
loading
:
true
,
categoryNameToCodeMap
:
{
}
,
categoryTreeOptions
:
[],
// 选中数组
ids
:
[],
// 非单个禁用
single
:
true
,
// 非多个禁用
multiple
:
true
,
// 显示搜索条件
showSearch
:
true
,
// 总条数
total
:
0
,
// 物料表格数据
materialsList
:
[],
// 弹出层标题
title
:
""
,
// 是否显示弹出层
open
:
false
,
// 物料分类抽屉显示状态
parentDialogVisible
:
false
,
// 当前选中的树节点ID
currentNodeId
:
null
,
// 查询参数
queryParams
:
{
pageNum
:
1
,
...
...
@@ -368,61 +399,183 @@ export default {
sapNo
:
null
,
tsCode
:
null
,
categoryCode
:
null
,
categoryNameInput
:
null
,
specification
:
null
,
}
,
// 表单参数
form
:
{
}
,
form
:
{
id
:
null
,
materialCode
:
null
,
materialName
:
null
,
sapNo
:
null
,
tsCode
:
null
,
categoryCode
:
null
,
hazardId
:
null
,
specification
:
null
,
materialUnit
:
null
,
unitWeight
:
null
,
packageWeight
:
null
,
totalWeight
:
null
,
volume
:
null
,
shelfLifeDays
:
null
,
storageTemperature
:
null
,
specialRequirements
:
null
,
isBatchManaged
:
0
,
isSerialManaged
:
0
,
minStockLevel
:
null
,
maxStockLevel
:
null
,
isUsed
:
1
,
isActive
:
1
,
riskLevel
:
null
,
sortNo
:
null
,
createUserCode
:
null
,
updateUserCode
:
null
}
,
// 表单校验
rules
:
{
materialCode
:
[{
required
:
true
,
message
:
'请输入物料编码'
,
trigger
:
'blur'
}
],
materialName
:
[{
required
:
true
,
message
:
'请输入物料名称'
,
trigger
:
'blur'
}
],
sapNo
:
[{
required
:
true
,
message
:
'请输入SAP物料号'
,
trigger
:
'blur'
}
],
tsCode
:
[{
required
:
true
,
message
:
'请输入TS Code'
,
trigger
:
'blur'
}
]
}
}
,
loading
:
true
}
}
,
created
()
{
this
.
getList
(),
this
.
getCategoryList
();
async
created
()
{
await
Promise
.
all
([
this
.
getCategoryTreeData
(),
this
.
getCategoryList
()
]);
this
.
getList
()
}
,
methods
:
{
getCategoryList
()
{
listMaterials_category
().
then
(
response
=>
{
this
.
categoryOptions
=
response
.
rows
.
map
(
item
=>
({
label
:
item
.
categoryName
,
value
:
item
.
categoryCode
}
));
this
.
categoryMap
=
response
.
rows
.
reduce
((
map
,
item
)
=>
{
map
[
item
.
categoryCode
]
=
item
.
categoryName
;
return
map
;
}
,
{
}
);
}
).
catch
(
error
=>
{
console
.
error
(
'加载分类失败'
,
error
);
async
getCategoryList
()
{
try
{
const
response
=
await
listMaterials_category
({
pageNum
:
1
,
pageSize
:
1000
}
);
if
(
response
.
rows
&&
response
.
rows
.
length
>
0
)
{
// 正向映射:code → name
this
.
categoryMap
=
{
}
;
// 反向映射:name → code(支持模糊匹配时用数组存储)
this
.
categoryNameToCodeMap
=
{
}
;
response
.
rows
.
forEach
(
item
=>
{
if
(
item
.
isUsed
!==
0
&&
item
.
isUsed
!==
'0'
)
{
this
.
categoryMap
[
item
.
categoryCode
]
=
item
.
categoryName
;
// 反向映射:名称作为key,编码作为value(若名称重复可存数组)
if
(
!
this
.
categoryNameToCodeMap
[
item
.
categoryName
])
{
this
.
categoryNameToCodeMap
[
item
.
categoryName
]
=
item
.
categoryCode
;
}
else
{
// 处理名称重复的情况(可选)
if
(
Array
.
isArray
(
this
.
categoryNameToCodeMap
[
item
.
categoryName
]))
{
this
.
categoryNameToCodeMap
[
item
.
categoryName
].
push
(
item
.
categoryCode
);
}
else
{
this
.
categoryNameToCodeMap
[
item
.
categoryName
]
=
[
this
.
categoryNameToCodeMap
[
item
.
categoryName
],
item
.
categoryCode
];
}
}
}
}
);
this
.
categoryTreeOptions
=
response
.
rows
.
filter
(
item
=>
item
.
isUsed
!==
0
&&
item
.
isUsed
!==
'0'
)
.
map
(
item
=>
({
categoryCode
:
item
.
categoryCode
,
categoryName
:
item
.
categoryName
}
));
}
}
catch
(
error
)
{
console
.
error
(
'获取分类列表失败:'
,
error
);
}
}
,
/** 打开物料分类管理 */
openMaterialsCategory
()
{
this
.
parentDialogVisible
=
true
if
(
this
.
$refs
.
materialsCategoryRef
)
{
this
.
$refs
.
materialsCategoryRef
.
resetForm
()
this
.
$refs
.
materialsCategoryRef
.
getList
()
/** 获取分类树数据 */
async
getCategoryTreeData
()
{
this
.
loadingTree
=
true
try
{
// 调用物料分类列表API获取所有分类
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
)
console
.
log
(
'分类树数据:'
,
this
.
categoryTreeData
)
}
}
catch
(
error
)
{
console
.
error
(
'获取分类树数据失败:'
,
error
)
}
finally
{
this
.
loadingTree
=
false
}
}
,
/** 构建树形结构 */
buildTreeData
(
list
,
parentId
=
null
)
{
const
result
=
list
.
filter
(
item
=>
{
if
(
parentId
===
null
)
{
// 根节点:parentId为null、0或空
return
!
item
.
parentId
||
item
.
parentId
===
0
||
item
.
parentId
===
'0'
}
else
{
// 子节点:parentId匹配
return
item
.
parentId
==
parentId
}
}
)
.
map
(
item
=>
{
const
children
=
this
.
buildTreeData
(
list
,
item
.
id
)
return
{
...
item
,
sid
:
String
(
item
.
id
),
label
:
item
.
categoryName
,
children
:
children
.
length
>
0
?
children
:
undefined
}
}
)
return
result
}
,
/** 物料分类提交回调 */
handleCategorySubmit
(
res
)
{
this
.
parentDialogVisible
=
false
// 刷新物料列表
/** 处理树节点点击 */
handleTreeClick
(
data
)
{
console
.
log
(
'点击树节点:'
,
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'
);
this
.
total
=
response
.
total
this
.
loading
=
false
// 对物料列表中的分类字段做映射处理
this
.
materialsList
=
response
.
rows
.
filter
(
item
=>
item
.
isUsed
!==
0
&&
item
.
isUsed
!==
'0'
)
.
map
(
item
=>
({
...
item
,
// 兜底:如果映射表中没有,显示原始code并标注
displayCategory
:
this
.
categoryMap
[
item
.
categoryCode
]
||
`${item.categoryCode
}
(未匹配分类)`
}
));
this
.
total
=
response
.
total
;
}
).
catch
(()
=>
{
this
.
loading
=
false
;
}
).
finally
(()
=>
{
this
.
loading
=
false
;
}
)
}
,
...
...
@@ -451,29 +604,51 @@ export default {
shelfLifeDays
:
null
,
storageTemperature
:
null
,
specialRequirements
:
null
,
isBatchManaged
:
'0'
,
isSerialManaged
:
'0'
,
isBatchManaged
:
0
,
isSerialManaged
:
0
,
minStockLevel
:
null
,
maxStockLevel
:
null
,
isUsed
:
'1'
,
isActive
:
'1'
,
isUsed
:
1
,
isActive
:
1
,
riskLevel
:
null
,
sortNo
:
null
,
createUserCode
:
null
,
updateUserCode
:
null
}
this
.
resetForm
(
"form"
)
this
.
$refs
.
form
&&
this
.
$refs
.
form
.
resetFields
(
)
}
,
/** 搜索按钮操作 */
handleQuery
()
{
this
.
queryParams
.
pageNum
=
1
this
.
getList
()
// 清空原有分类编码
this
.
queryParams
.
categoryCode
=
null
;
// 获取用户输入的分类名称
const
inputName
=
this
.
queryParams
.
categoryNameInput
;
if
(
inputName
)
{
// 1. 精确匹配名称 → 编码
const
matchedCode
=
this
.
categoryNameToCodeMap
[
inputName
];
if
(
matchedCode
)
{
// 若有多个编码(名称重复),取第一个
this
.
queryParams
.
categoryCode
=
Array
.
isArray
(
matchedCode
)
?
matchedCode
[
0
]
:
matchedCode
;
}
else
{
// 2. 模糊匹配名称 → 编码(可选)
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
.
resetForm
(
"queryForm"
)
this
.
resetForm
(
"queryForm"
)
;
this
.
queryParams
=
{
pageNum
:
1
,
pageSize
:
10
,
...
...
@@ -482,9 +657,20 @@ export default {
sapNo
:
null
,
tsCode
:
null
,
categoryCode
:
null
,
categoryNameInput
:
null
,
specification
:
null
,
}
;
this
.
currentNodeId
=
null
;
// 修复树形高亮重置:直接操作 TreeComponent 内部的 el-tree
if
(
this
.
$refs
.
treeComponent
&&
this
.
$refs
.
treeComponent
.
$refs
.
tree
)
{
this
.
$refs
.
treeComponent
.
$refs
.
tree
.
setCurrentKey
(
null
);
// 清空选中
}
else
if
(
this
.
$refs
.
treeComponent
)
{
// 如果 TreeComponent 有自定义重置方法
this
.
$refs
.
treeComponent
.
resetTree
();
}
this
.
getList
()
this
.
getList
();
}
,
// 多选框选中数据
...
...
@@ -514,7 +700,7 @@ export default {
/** 提交按钮 */
submitForm
()
{
this
.
$refs
[
"form"
]
.
validate
(
valid
=>
{
this
.
$refs
.
form
.
validate
(
valid
=>
{
if
(
valid
)
{
const
promise
=
this
.
form
.
id
?
updateMaterials
(
this
.
form
)
...
...
@@ -524,6 +710,8 @@ export default {
this
.
$modal
.
msgSuccess
(
this
.
form
.
id
?
"修改成功"
:
"新增成功"
)
this
.
open
=
false
this
.
getList
()
}
).
catch
(
error
=>
{
console
.
error
(
'提交失败:'
,
error
)
}
)
}
}
)
...
...
@@ -550,7 +738,28 @@ export default {
this
.
download
(
'inventory/materials/export'
,
{
...
this
.
queryParams
}
,
`materials_${new Date().getTime()
}
.xlsx`
)
}
,
/** 表单重置方法 */
resetForm
(
formName
)
{
if
(
this
.
$refs
[
formName
])
{
this
.
$refs
[
formName
].
resetFields
()
}
}
}
}
<
/script
>
<
style
scoped
>
.
app
-
container
{
height
:
100
vh
;
}
.
custom
-
tree
-
node
{
font
-
size
:
14
px
;
}
.
mb8
{
margin
-
bottom
:
8
px
;
}
<
/style>
\ No newline at end of file
ruoyi-admin-vue/src/views/inventory/materials_category/index.vue
View file @
e76b86c2
<
template
>
<div
class=
"app-container"
>
<div
class=
"app-container"
style=
"overflow: hidden;"
>
<splitpanes
class=
"default-theme"
style=
"height: 100%;"
>
<!-- 树结构:左侧面板 -->
<pane
size=
"16"
style=
"height: 100%; overflow: auto;"
>
<TreeComponent
:tree-data=
"categoryOptions"
:tree-props=
"defaultProps"
:node-key=
"nodeKey"
:show-search=
"true"
search-placeholder=
"请输入分类名称"
:default-expand-all=
"true"
:highlight-current=
"true"
:loading=
"loadingTree"
@
node-click=
"handleTreeClick"
style=
"height: 100%;"
/>
</pane>
<!-- 物料分类管理:右侧面板 -->
<pane
size=
"84"
style=
"height: 100%; overflow: auto;"
>
<div
style=
"padding: 10px; height: 100%; display: flex; flex-direction: column;"
>
<!-- 搜索表单 -->
<el-form
:model=
"queryParams"
...
...
@@ -7,6 +27,7 @@
:inline=
"true"
v-show=
"showSearch"
label-width=
"128px"
style=
"margin-bottom: 10px;"
>
<el-form-item
label=
"物料分类编码"
prop=
"categoryCode"
>
<el-input
...
...
@@ -24,32 +45,6 @@
@
keyup
.
enter=
"handleQuery"
/>
</el-form-item>
<!--
<el-form-item
label=
"排序"
prop=
"sortNo"
>
<el-input
v-model=
"queryParams.sortNo"
placeholder=
"请输入排序"
clearable
@
keyup
.
enter=
"handleQuery"
/>
</el-form-item>
<el-form-item
label=
"创建时间"
prop=
"createTime"
>
<el-date-picker
clearable
v-model=
"queryParams.createTime"
type=
"date"
value-format=
"YYYY-MM-DD"
placeholder=
"请选择创建时间"
>
</el-date-picker>
</el-form-item>
<el-form-item
label=
"修改时间"
prop=
"updateTime"
>
<el-date-picker
clearable
v-model=
"queryParams.updateTime"
type=
"date"
value-format=
"YYYY-MM-DD"
placeholder=
"请选择修改时间"
>
</el-date-picker>
</el-form-item>
-->
<el-form-item>
<el-button
type=
"primary"
icon=
"el-icon-search"
@
click=
"handleQuery"
>
搜索
</el-button>
<el-button
icon=
"el-icon-refresh"
@
click=
"resetQuery"
>
重置
</el-button>
...
...
@@ -57,7 +52,7 @@
</el-form>
<!-- 操作按钮 -->
<el-row
:gutter=
"10"
class=
"mb8
"
>
<el-row
:gutter=
"10"
class=
"mb8"
style=
"margin-bottom: 10px;
"
>
<el-col
:span=
"1.5"
>
<el-button
type=
"primary"
...
...
@@ -89,6 +84,14 @@
</el-col>
<el-col
:span=
"1.5"
>
<el-button
type=
"info"
plain
icon=
"el-icon-sort"
@
click=
"toggleExpandAll"
>
展开/折叠
</el-button>
</el-col>
<el-col
:span=
"1.5"
>
<el-button
type=
"warning"
plain
icon=
"el-icon-download"
...
...
@@ -99,33 +102,52 @@
<right-toolbar
v-model=
"showSearch"
@
queryTable=
"getList"
></right-toolbar>
</el-row>
<!-- 数据表格 -->
<!-- 树形数据表格(移除分页) -->
<div
style=
"flex: 1; overflow: auto;"
>
<el-table
ref=
"treeTable"
v-if=
"refreshTable"
v-loading=
"loading"
:data=
"materials_categoryList
"
:data=
"currentTreeNodeData
"
@
selection-change=
"handleSelectionChange"
style=
"width: 100%;"
row-key=
"id"
:default-expand-all=
"isExpandAll"
:tree-props=
"
{children: 'children', hasChildren: 'hasChildren'}"
>
<el-table-column
type=
"selection"
width=
"55"
align=
"center"
/>
<el-table-column
label=
"物料分类编码"
align=
"center"
prop=
"categoryCode"
/>
<el-table-column
label=
"物料分类名称"
align=
"center"
prop=
"categoryName"
/>
<el-table-column
label=
"排序"
align=
"center"
prop=
"sortNo"
/>
<el-table-column
label=
"创建时间"
align=
"center"
prop=
"createTime"
width=
"120"
>
<el-table-column
label=
"物料分类名称"
align=
"center"
prop=
"categoryName"
min-width=
"200"
/>
<el-table-column
label=
"物料分类编码"
align=
"center"
prop=
"categoryCode"
width=
"200"
/>
<el-table-column
label=
"排序"
align=
"center"
prop=
"sortNo"
width=
"100"
/>
<el-table-column
label=
"创建时间"
align=
"center"
prop=
"createTime"
width=
"200"
>
<template
slot-scope=
"scope"
>
<span>
{{
parseTime
(
scope
.
row
.
createTime
,
'{y
}
-{m
}
-{d
}
'
)
}}
<
/span
>
<
/template
>
<
/el-table-column
>
<
el
-
table
-
column
label
=
"修改时间"
align
=
"center"
prop
=
"updateTime"
width
=
"12
0"
>
<
el
-
table
-
column
label
=
"修改时间"
align
=
"center"
prop
=
"updateTime"
width
=
"20
0"
>
<
template
slot
-
scope
=
"scope"
>
<
span
>
{{
parseTime
(
scope
.
row
.
updateTime
,
'{y
}
-{m
}
-{d
}
'
)
}}
<
/span
>
<
/template
>
<
/el-table-column
>
<
el
-
table
-
column
label
=
"操作"
align
=
"center"
class
-
name
=
"small-padding fixed-width"
width
=
"12
0"
>
<
el
-
table
-
column
label
=
"操作"
align
=
"center"
class
-
name
=
"small-padding fixed-width"
width
=
"25
0"
>
<
template
slot
-
scope
=
"scope"
>
<
el
-
button
size
=
"mini"
link
type
=
"text"
icon
=
"el-icon-plus"
@
click
=
"handleAdd(scope.row.id)"
v
-
hasPermi
=
"['inventory:materials_category:add']"
>
新增下级
<
/el-button
>
<
el
-
button
size
=
"mini"
link
type
=
"text"
icon
=
"el-icon-edit"
@
click
=
"handleUpdate(scope.row)"
v
-
hasPermi
=
"['inventory:materials_category:edit']"
...
...
@@ -141,17 +163,12 @@
<
/template
>
<
/el-table-column
>
<
/el-table
>
<
/div
>
<
/div
>
<
/pane
>
<
/splitpanes
>
<!--
分页组件
-->
<
pagination
v
-
show
=
"total>0"
:
total
=
"total"
:
page
.
sync
=
"queryParams.pageNum"
:
limit
.
sync
=
"queryParams.pageSize"
@
pagination
=
"getList"
/>
<!--
添加
/
修改对话框(通过
props
控制显示)
-->
<!--
添加
/
修改对话框
-->
<
el
-
dialog
:
title
=
"dialogTitle"
:
visible
.
sync
=
"dialogOpen"
...
...
@@ -165,6 +182,15 @@
:
rules
=
"rules"
label
-
width
=
"120px"
>
<
el
-
form
-
item
label
=
"上级分类"
prop
=
"parentId"
v
-
if
=
"form.id && form.parentId"
>
<
treeselect
v
-
model
=
"form.parentId"
:
options
=
"categoryOptions"
:
normalizer
=
"normalizer"
placeholder
=
"选择上级分类"
:
disabled
=
"!!form.id"
/>
<
/el-form-item
>
<
el
-
form
-
item
label
=
"物料分类编码"
prop
=
"categoryCode"
>
<
el
-
input
v
-
model
=
"form.categoryCode"
placeholder
=
"请输入物料编码"
/>
<
/el-form-item
>
...
...
@@ -174,11 +200,14 @@
<
el
-
form
-
item
label
=
"排序"
prop
=
"sortNo"
>
<
el
-
input
v
-
model
=
"form.sortNo"
placeholder
=
"请输入排序"
/>
<
/el-form-item
>
<!--
<
el
-
form
-
item
label
=
"创建人编码"
prop
=
"createUserCode"
>
<
el
-
input
v
-
model
=
"form.createUserCode"
placeholder
=
"请输入创建人编码"
/>
<
/el-form-item
>
<
el
-
form
-
item
label
=
"更新人编码"
prop
=
"updateUserCode"
>
<
el
-
input
v
-
model
=
"form.updateUserCode"
placeholder
=
"请输入更新人编码"
/>
<!--
<
el
-
form
-
item
label
=
"状态"
prop
=
"isUsed"
>
<
el
-
radio
-
group
v
-
model
=
"form.isUsed"
>
<
el
-
radio
v
-
for
=
"dict in dict.type.sys_normal_disable"
:
key
=
"dict.value"
:
label
=
"dict.value"
>
{{
dict
.
label
}}
<
/el-radio
>
<
/el-radio-group
>
<
/el-form-item> --
>
<
/el-form
>
<
div
slot
=
"footer"
class
=
"dialog-footer"
>
...
...
@@ -186,6 +215,7 @@
<
el
-
button
@
click
=
"handleDialogClose"
>
取
消
<
/el-button
>
<
/div
>
<
/el-dialog
>
<
/div
>
<
/template
>
...
...
@@ -195,28 +225,32 @@ import {
getMaterials_category
,
delMaterials_category
,
addMaterials_category
,
updateMaterials_category
updateMaterials_category
,
categoryTreeSelect
}
from
"@/api/inventory/materials_category"
import
{
Splitpanes
,
Pane
}
from
'splitpanes'
import
"@riophae/vue-treeselect/dist/vue-treeselect.css"
import
'splitpanes/dist/splitpanes.css'
import
Treeselect
from
"@riophae/vue-treeselect"
import
TreeComponent
from
"./treeComponent.vue"
export
default
{
name
:
"MaterialsCategory"
,
components
:
{
Treeselect
,
Splitpanes
,
Pane
,
TreeComponent
}
,
dicts
:
[
'sys_normal_disable'
],
props
:
{
// 外部传入的初始查询参数(可选)
initQuery
:
{
type
:
Object
,
default
:
()
=>
({
}
)
}
,
// 外部控制对话框显示(可选)
dialogVisible
:
{
type
:
Boolean
,
default
:
false
}
,
// 外部传入的表单数据(编辑用)
dialogFormData
:
{
type
:
Object
,
default
:
()
=>
({
}
)
}
,
// 外部传入的对话框标题
dialogTitle
:
{
type
:
String
,
default
:
"新增物料分类"
...
...
@@ -225,50 +259,64 @@ export default {
data
()
{
return
{
materials_categoryList
:
[],
currentTreeNodeData
:
[],
loading
:
true
,
loadingTree
:
false
,
showSearch
:
true
,
ids
:
[],
single
:
true
,
multiple
:
true
,
total
:
0
,
// 内部对话框状态(避免直接修改props)
dialogOpen
:
false
,
categoryOptions
:
[],
defaultProps
:
{
children
:
'children'
,
label
:
'label'
,
value
:
'sid'
}
,
nodeKey
:
'sid'
,
currentNodeId
:
null
,
isExpandAll
:
true
,
refreshTable
:
true
,
form
:
{
id
:
null
,
categoryCode
:
null
,
categoryName
:
null
,
sortNo
:
null
,
createUserCode
:
null
,
updateUserCode
:
null
updateUserCode
:
null
,
parentId
:
null
,
isUsed
:
1
}
,
queryParams
:
{
pageNum
:
1
,
pageSize
:
10
,
pageSize
:
10
00
,
// 设置为较大的值,一次性获取所有数据
categoryCode
:
null
,
categoryName
:
null
,
sortNo
:
null
,
createTime
:
null
,
updateTime
:
null
,
parentId
:
null
,
isUsed
:
1
}
,
rules
:
{
}
rules
:
{
categoryCode
:
[{
required
:
true
,
message
:
'请输入物料分类编码'
,
trigger
:
'blur'
}
],
categoryName
:
[{
required
:
true
,
message
:
'请输入物料分类名称'
,
trigger
:
'blur'
}
]
}
}
}
,
watch
:
{
// 监听外部传入的对话框显示状态
dialogVisible
:
{
immediate
:
true
,
handler
(
val
)
{
this
.
dialogOpen
=
val
}
}
,
// 监听外部传入的表单数据
dialogFormData
:
{
immediate
:
true
,
handler
(
val
)
{
this
.
form
=
{
...
val
}
}
}
,
// 监听初始查询参数
initQuery
:
{
immediate
:
true
,
handler
(
val
)
{
...
...
@@ -279,26 +327,318 @@ export default {
}
,
created
()
{
this
.
getList
()
this
.
getCategoryOptions
()
}
,
methods
:
{
/** 查询列表(内部方法) */
/** 查询分类树结构 */
getCategoryOptions
()
{
this
.
loadingTree
=
true
categoryTreeSelect
().
then
(
response
=>
{
this
.
categoryOptions
=
response
.
data
this
.
loadingTree
=
false
}
).
catch
(()
=>
{
this
.
loadingTree
=
false
}
)
}
,
/** 处理树节点点击 */
/** 处理树节点点击 */
handleTreeClick
(
data
)
{
console
.
log
(
'点击树节点:'
,
data
)
// 确保数据存在且有sid属性
if
(
!
data
||
!
data
.
sid
)
{
console
.
warn
(
'无效的节点数据,缺少sid属性'
);
return
;
}
// 确保使用字符串类型的id进行操作,避免类型转换问题
this
.
currentNodeId
=
String
(
data
.
sid
)
console
.
log
(
this
.
categoryOptions
)
// 1. 找到当前节点的根节点
const
rootNode
=
this
.
findRootNode
(
this
.
currentNodeId
,
this
.
categoryOptions
);
if
(
rootNode
)
{
// 2. 筛选根节点的完整分支数据
const
rootNodeIdStr
=
String
(
rootNode
.
sid
);
this
.
filterRootBranchData
(
this
.
materials_categoryList
,
rootNodeIdStr
);
// 3. 自动展开到当前节点
this
.
$nextTick
(()
=>
{
// 尝试展开节点,即使数据可能尚未完全准备好
// expandToNode方法内部已经有适当的错误处理
this
.
expandToNode
(
this
.
currentNodeId
);
}
);
}
}
,
/** 查找表格数据中的节点ID */
findTableNodeId
(
treeNode
)
{
if
(
!
treeNode
)
return
null
// 首先在materials_categoryList中查找对应的节点
const
tableNode
=
this
.
materials_categoryList
.
find
(
item
=>
item
.
categoryCode
===
treeNode
.
categoryCode
||
item
.
categoryName
===
treeNode
.
label
||
item
.
id
===
treeNode
.
id
)
return
tableNode
?
tableNode
.
id
:
null
}
,
/** 筛选根节点的完整分支数据 */
filterRootBranchData
(
allData
,
rootNodeId
)
{
// 确保rootNodeId为字符串类型
const
rootNodeIdStr
=
String
(
rootNodeId
);
// 获取根节点分支的所有节点ID(包含根节点和所有子节点)
const
branchNodeIds
=
this
.
getAllChildNodeIds
(
allData
,
rootNodeIdStr
);
// 筛选出根分支的所有数据
// 使用字符串比较避免类型转换问题
const
filteredData
=
allData
.
filter
(
item
=>
branchNodeIds
.
some
(
branchId
=>
String
(
branchId
)
===
String
(
item
.
id
))
);
// 构建树形结构并赋值给表格
this
.
currentTreeNodeData
=
this
.
handleTree
(
filteredData
,
"id"
);
}
,
/** 展开到指定节点 */
expandToNode
(
nodeId
)
{
const
treeTable
=
this
.
$refs
.
treeTable
;
// 增加对treeTable.store.nodesMap的检查
if
(
!
treeTable
||
!
treeTable
.
store
||
!
treeTable
.
store
.
nodesMap
)
{
console
.
log
(
treeTable
)
console
.
warn
(
'树表格组件未完全初始化或nodesMap不存在'
);
return
;
}
// 确保nodeId为字符串类型
const
nodeIdStr
=
String
(
nodeId
);
// 找到节点路径
const
nodePath
=
this
.
findNodePath
(
this
.
currentTreeNodeData
,
nodeIdStr
);
// 逐级展开
if
(
nodePath
&&
nodePath
.
length
>
0
)
{
nodePath
.
forEach
(
id
=>
{
const
idStr
=
String
(
id
);
try
{
// 安全地查找节点,避免访问不存在的属性
const
node
=
treeTable
.
store
.
nodesMap
[
idStr
]
||
treeTable
.
store
.
nodesMap
[
id
];
if
(
node
&&
typeof
node
===
'object'
&&
node
.
expanded
===
false
&&
node
.
expandable
)
{
node
.
expanded
=
true
;
}
}
catch
(
error
)
{
console
.
warn
(
`展开节点时出错: ${error.message
}
, 节点ID: ${idStr
}
`
);
}
}
);
}
}
,
/** 查找节点路径 */
findNodePath
(
treeData
,
targetId
,
path
=
[])
{
// 确保targetId为字符串类型
const
targetIdStr
=
String
(
targetId
);
for
(
const
item
of
treeData
)
{
if
(
String
(
item
.
id
)
===
targetIdStr
)
{
return
[...
path
,
item
.
id
];
}
if
(
item
.
children
&&
item
.
children
.
length
)
{
const
found
=
this
.
findNodePath
(
item
.
children
,
targetIdStr
,
[...
path
,
item
.
id
]);
if
(
found
)
return
found
;
}
}
return
null
;
}
,
/** 转换部门数据结构 */
normalizer
(
node
)
{
if
(
node
.
children
&&
!
node
.
children
.
length
)
{
delete
node
.
children
}
return
{
id
:
node
.
sid
,
label
:
node
.
label
,
children
:
node
.
children
}
}
,
/** 查询物料分类列表 */
/** 查询物料分类列表 */
getList
()
{
this
.
loading
=
true
listMaterials_category
(
this
.
queryParams
).
then
(
response
=>
{
this
.
materials_categoryList
=
response
.
rows
this
.
total
=
response
.
total
this
.
materials_categoryList
=
response
.
rows
.
filter
(
item
=>
item
.
isUsed
!==
0
&&
item
.
isUsed
!==
'0'
);
// 如果没有选中树节点,显示所有数据
if
(
!
this
.
currentNodeId
)
{
this
.
currentTreeNodeData
=
this
.
handleTree
(
this
.
materials_categoryList
,
"id"
);
}
else
{
// 如果有选中的树节点,保持当前显示
// 直接使用 currentNodeId(sid)作为表格数据的 id
const
rootNode
=
this
.
findRootNode
(
this
.
currentNodeId
,
this
.
categoryOptions
);
if
(
rootNode
)
{
// rootNode.sid 就是表格中的 id
this
.
filterRootBranchData
(
this
.
materials_categoryList
,
rootNode
.
sid
);
}
}
this
.
loading
=
false
// 通知父组件列表加载完成
this
.
$emit
(
"list-loaded"
,
{
list
:
response
.
rows
,
total
:
response
.
total
total
:
response
.
rows
.
length
}
)
}
)
}
,
/** 选择指定的树节点 */
selectTreeNode
(
nodeId
)
{
if
(
!
nodeId
)
return
;
// 确保nodeId为字符串类型
const
nodeIdStr
=
String
(
nodeId
);
// 查找对应的树节点
const
findTreeNode
=
(
nodes
)
=>
{
for
(
const
node
of
nodes
)
{
if
(
String
(
node
.
sid
)
===
nodeIdStr
)
{
return
node
;
}
if
(
node
.
children
&&
node
.
children
.
length
>
0
)
{
const
found
=
findTreeNode
(
node
.
children
);
if
(
found
)
return
found
;
}
}
return
null
;
}
;
// 在categoryOptions中查找节点
const
treeNode
=
findTreeNode
(
this
.
categoryOptions
);
if
(
treeNode
)
{
// 如果找到节点,触发点击事件
this
.
handleTreeClick
(
treeNode
);
}
else
{
console
.
warn
(
`未找到ID为${nodeIdStr
}
的树节点`
);
// 如果未找到节点,可能是根节点已变更,尝试找到新的根节点
const
rootNode
=
this
.
findRootNode
(
nodeIdStr
,
this
.
materials_categoryList
);
if
(
rootNode
)
{
this
.
filterRootBranchData
(
this
.
materials_categoryList
,
rootNode
.
id
);
}
}
}
,
/** 获取节点及其所有子节点的ID(基于表格数据) */
getAllChildNodeIds
(
tableData
,
nodeId
)
{
const
result
=
[];
// 确保nodeId为字符串类型
const
nodeIdStr
=
String
(
nodeId
);
// 递归查找所有子节点
const
findChildren
=
(
parentId
)
=>
{
const
parentIdStr
=
String
(
parentId
);
// 使用字符串比较确保兼容性
const
children
=
tableData
.
filter
(
item
=>
item
.
parentId
&&
String
(
item
.
parentId
)
===
parentIdStr
);
children
.
forEach
(
child
=>
{
result
.
push
(
child
.
id
);
findChildren
(
child
.
id
);
}
);
}
;
// 添加当前节点
// 使用字符串比较查找当前节点
const
currentNode
=
tableData
.
find
(
item
=>
String
(
item
.
id
)
===
nodeIdStr
);
if
(
currentNode
)
{
result
.
push
(
currentNode
.
id
);
findChildren
(
currentNode
.
id
);
}
return
result
;
}
,
/** 查找当前节点的根节点 */
findRootNode
(
nodeId
,
treeData
)
{
// 确保nodeId为字符串类型
const
nodeIdStr
=
String
(
nodeId
);
// 首先找到当前节点
const
findNodeById
=
(
nodes
,
id
)
=>
{
// 检查nodes是否有效
if
(
!
nodes
||
!
Array
.
isArray
(
nodes
))
return
null
;
for
(
const
node
of
nodes
)
{
// 确保比较时使用字符串类型,处理表格数据和树数据的不同字段名
if
(
String
(
node
.
sid
||
node
.
id
)
===
id
)
{
return
node
;
}
if
(
node
.
children
&&
node
.
children
.
length
>
0
)
{
const
found
=
findNodeById
(
node
.
children
,
id
);
if
(
found
)
return
found
;
}
}
return
null
;
}
;
const
currentNode
=
findNodeById
(
treeData
,
nodeIdStr
);
if
(
!
currentNode
)
return
null
;
// 查找根节点(parentId为null或空或0)
const
findRoot
=
(
node
)
=>
{
if
(
!
node
)
return
null
;
// 检查多种可能的根节点条件
const
parentId
=
String
(
node
.
parentId
||
''
);
if
(
!
parentId
||
parentId
===
'0'
||
parentId
===
'null'
||
parentId
===
'undefined'
)
{
return
node
;
}
const
parentNode
=
findNodeById
(
treeData
,
parentId
);
// 如果找不到父节点,当前节点就是根节点
console
.
log
(
parentNode
)
return
parentNode
?
findRoot
(
parentNode
)
:
node
;
}
;
return
findRoot
(
currentNode
);
}
,
/** 处理树形数据 */
handleTree
(
data
,
id
,
parentId
,
children
)
{
id
=
id
||
'id'
parentId
=
parentId
||
'parentId'
children
=
children
||
'children'
// 确保根节点筛选逻辑正确,处理各种可能的parentId值
const
rootNodes
=
data
.
filter
(
item
=>
{
const
pId
=
item
[
parentId
];
return
!
pId
||
pId
===
null
||
pId
===
0
||
String
(
pId
)
===
'0'
||
String
(
pId
)
===
''
;
}
)
const
addChildren
=
(
parent
)
=>
{
// 使用字符串比较查找子节点,确保类型一致性
const
childNodes
=
data
.
filter
(
item
=>
{
return
String
(
item
[
parentId
])
===
String
(
parent
[
id
]);
}
)
if
(
childNodes
.
length
>
0
)
{
parent
[
children
]
=
childNodes
childNodes
.
forEach
(
child
=>
addChildren
(
child
))
}
}
rootNodes
.
forEach
(
root
=>
addChildren
(
root
))
return
rootNodes
}
,
/** 搜索按钮操作 */
handleQuery
()
{
this
.
queryParams
.
pageNum
=
1
this
.
currentNodeId
=
null
// 搜索时清除当前选中的节点
this
.
getList
()
}
,
...
...
@@ -307,35 +647,62 @@ export default {
this
.
$refs
[
"queryRef"
].
resetFields
()
this
.
queryParams
=
{
pageNum
:
1
,
pageSize
:
10
,
pageSize
:
10
00
,
categoryCode
:
null
,
categoryName
:
null
,
sortNo
:
null
,
createTime
:
null
,
updateTime
:
null
,
...
this
.
initQuery
// 保留初始查询参数
parentId
:
null
,
...
this
.
initQuery
}
// 重置时清除当前选中的节点
this
.
currentNodeId
=
null
// 重置左侧树的选择状态
if
(
this
.
$refs
.
treeComponent
&&
this
.
$refs
.
treeComponent
.
resetTree
)
{
this
.
$refs
.
treeComponent
.
resetTree
();
}
this
.
getList
()
}
,
/** 展开/折叠操作 */
toggleExpandAll
()
{
this
.
refreshTable
=
false
this
.
isExpandAll
=
!
this
.
isExpandAll
this
.
$nextTick
(()
=>
{
this
.
refreshTable
=
true
// 手动设置展开/折叠
const
treeTable
=
this
.
$refs
.
treeTable
;
if
(
treeTable
&&
treeTable
.
store
)
{
Object
.
keys
(
treeTable
.
store
.
nodesMap
).
forEach
(
key
=>
{
const
node
=
treeTable
.
store
.
nodesMap
[
key
];
if
(
node
&&
node
.
expandable
)
{
node
.
expanded
=
this
.
isExpandAll
;
}
}
);
}
}
)
}
,
/** 多选框选中事件 */
handleSelectionChange
(
selection
)
{
this
.
ids
=
selection
.
map
(
item
=>
item
.
id
)
this
.
single
=
selection
.
length
!==
1
this
.
multiple
=
!
selection
.
length
// 通知父组件选中数据变化
this
.
$emit
(
"selection-change"
,
selection
)
}
,
/** 新增按钮操作 */
handleAdd
()
{
handleAdd
(
parentId
)
{
this
.
form
=
{
id
:
null
,
categoryCode
:
null
,
categoryName
:
null
,
sortNo
:
null
,
createUserCode
:
null
,
updateUserCode
:
null
updateUserCode
:
null
,
parentId
:
parentId
||
null
,
isUsed
:
1
}
this
.
dialogOpen
=
true
this
.
$emit
(
"dialog-open"
,
{
type
:
"add"
,
form
:
this
.
form
}
)
...
...
@@ -363,8 +730,38 @@ export default {
const
type
=
this
.
form
.
id
?
"update"
:
"add"
this
.
$modal
.
msgSuccess
(
`${type === "add" ? "新增" : "修改"
}
成功`
)
this
.
dialogOpen
=
false
this
.
getList
()
// 通知父组件提交成功
// 保存当前节点ID,用于数据重新加载后恢复选择
const
currentNodeIdBeforeReload
=
this
.
currentNodeId
;
const
isAddChild
=
type
===
"add"
&&
this
.
form
.
parentId
;
// 重新加载数据
Promise
.
all
([
// 先重新加载树数据
new
Promise
(
resolve
=>
{
this
.
getCategoryOptions
();
// 延迟一下确保树数据加载完成
setTimeout
(()
=>
resolve
(),
100
);
}
),
// 再重新加载列表数据
new
Promise
(
resolve
=>
{
this
.
getList
();
// 延迟一下确保列表数据加载完成
setTimeout
(()
=>
resolve
(),
100
);
}
)
]).
then
(()
=>
{
// 数据加载完成后,恢复或更新选择
this
.
$nextTick
(()
=>
{
if
(
isAddChild
)
{
// 新增下级后,选择父节点
this
.
selectTreeNode
(
this
.
form
.
parentId
);
}
else
if
(
currentNodeIdBeforeReload
)
{
// 修改后,保持当前选择
this
.
selectTreeNode
(
currentNodeIdBeforeReload
);
}
}
);
}
);
this
.
$emit
(
"form-submit"
,
{
type
,
data
:
this
.
form
,
...
...
@@ -381,9 +778,10 @@ export default {
this
.
$modal
.
confirm
(
`是否确认删除物料分类编号为"${_ids
}
"的数据项?`
).
then
(()
=>
{
return
delMaterials_category
(
_ids
)
}
).
then
(()
=>
{
// 重新加载数据
this
.
getList
()
this
.
getCategoryOptions
()
this
.
$modal
.
msgSuccess
(
"删除成功"
)
// 通知父组件删除成功
this
.
$emit
(
"item-delete"
,
{
ids
:
_ids
}
)
}
).
catch
(()
=>
{
}
)
}
,
...
...
@@ -393,7 +791,6 @@ export default {
this
.
download
(
'inventory/materials_category/export'
,
{
...
this
.
queryParams
}
,
`materials_category_${new Date().getTime()
}
.xlsx`
)
// 通知父组件导出操作
this
.
$emit
(
"export-data"
,
this
.
queryParams
)
}
,
...
...
@@ -403,7 +800,7 @@ export default {
this
.
$emit
(
"dialog-close"
)
}
,
/** 表单重置
(供外部调用)
*/
/** 表单重置 */
resetForm
()
{
this
.
form
=
{
id
:
null
,
...
...
@@ -411,10 +808,28 @@ export default {
categoryName
:
null
,
sortNo
:
null
,
createUserCode
:
null
,
updateUserCode
:
null
updateUserCode
:
null
,
parentId
:
null
,
isUsed
:
1
}
this
.
$refs
[
"materials_categoryRef"
]?.
resetFields
()
}
}
}
<
/script
>
<
style
scoped
>
.
app
-
container
{
height
:
100
%
;
}
.
mb8
{
margin
-
bottom
:
8
px
;
}
/* 添加滚动条样式 */
.
el
-
table
{
max
-
height
:
100
%
;
overflow
-
y
:
auto
;
}
<
/style>
\ No newline at end of file
ruoyi-admin-vue/src/views/inventory/materials_category/treeComponent.vue
0 → 100644
View file @
e76b86c2
<
template
>
<div
class=
"tree-container"
:style=
"containerStyle"
>
<!-- 搜索框 -->
<div
class=
"tree-header"
v-if=
"showSearch"
>
<el-input
v-model=
"searchText"
:placeholder=
"searchPlaceholder"
clearable
size=
"small"
prefix-icon=
"el-icon-search"
@
input=
"handleSearch"
style=
"width: 100%; margin-bottom: 10px;"
/>
</div>
<!-- 树组件 -->
<div
class=
"tree-body"
:style=
"treeBodyStyle"
>
<el-tree
v-if=
"treeData && treeData.length > 0"
ref=
"treeRef"
:data=
"filteredTreeData"
:props=
"treeProps"
:node-key=
"nodeKey"
:default-expand-all=
"defaultExpandAll"
:expand-on-click-node=
"expandOnClickNode"
:highlight-current=
"highlightCurrent"
:filter-node-method=
"filterNodeMethod"
:empty-text=
"emptyText"
:style=
"treeStyle"
@
node-click=
"handleNodeClick"
@
node-expand=
"handleNodeExpand"
@
node-collapse=
"handleNodeCollapse"
@
current-change=
"handleCurrentChange"
>
<!-- 自定义节点内容插槽 -->
<template
#
default=
"
{ node, data }">
<slot
name=
"node-content"
:node=
"node"
:data=
"data"
>
<span
class=
"custom-tree-node"
>
<span>
{{
node
.
label
}}
</span>
</span>
</slot>
</
template
>
</el-tree>
<!-- 空状态 -->
<div
v-else
class=
"tree-empty"
>
<slot
name=
"empty"
>
<div
style=
"padding: 20px; text-align: center; color: #999;"
>
{{ loading ? '加载中...' : '暂无数据' }}
</div>
</slot>
</div>
</div>
</div>
</template>
<
script
>
export
default
{
name
:
'TreeComponent'
,
props
:
{
// 树数据
treeData
:
{
type
:
Array
,
default
:
()
=>
[]
},
// 树配置
treeProps
:
{
type
:
Object
,
default
:
()
=>
({
children
:
'children'
,
label
:
'label'
,
value
:
'sid'
})
},
// 节点key
nodeKey
:
{
type
:
String
,
default
:
'sid'
},
// 是否显示搜索框
showSearch
:
{
type
:
Boolean
,
default
:
true
},
// 搜索框占位符
searchPlaceholder
:
{
type
:
String
,
default
:
'请输入搜索内容'
},
// 是否默认展开所有节点
defaultExpandAll
:
{
type
:
Boolean
,
default
:
true
},
// 是否点击节点时展开
expandOnClickNode
:
{
type
:
Boolean
,
default
:
false
},
// 是否高亮当前选中节点
highlightCurrent
:
{
type
:
Boolean
,
default
:
true
},
// 容器样式
containerStyle
:
{
type
:
Object
,
default
:
()
=>
({
height
:
'100%'
,
padding
:
'10px'
})
},
// 树容器样式
treeBodyStyle
:
{
type
:
Object
,
default
:
()
=>
({
height
:
'calc(100% - 50px)'
,
overflow
:
'auto'
})
},
// 树样式
treeStyle
:
{
type
:
Object
,
default
:
()
=>
({})
},
// 空状态文本
emptyText
:
{
type
:
String
,
default
:
'暂无数据'
},
// 加载状态
loading
:
{
type
:
Boolean
,
default
:
false
},
// 初始选中的节点key
defaultSelectedKey
:
{
type
:
[
String
,
Number
],
default
:
null
}
},
data
()
{
return
{
searchText
:
''
,
filteredTreeData
:
[],
selectedNode
:
null
}
},
watch
:
{
treeData
:
{
immediate
:
true
,
handler
(
newData
)
{
this
.
filteredTreeData
=
newData
this
.
$nextTick
(()
=>
{
if
(
this
.
defaultSelectedKey
&&
this
.
$refs
.
treeRef
)
{
this
.
$refs
.
treeRef
.
setCurrentKey
(
this
.
defaultSelectedKey
)
}
})
}
},
defaultSelectedKey
:
{
immediate
:
true
,
handler
(
newKey
)
{
if
(
newKey
&&
this
.
$refs
.
treeRef
)
{
this
.
$refs
.
treeRef
.
setCurrentKey
(
newKey
)
}
}
}
},
methods
:
{
/**
* 过滤节点方法
*/
filterNodeMethod
(
value
,
data
,
node
)
{
if
(
!
value
)
return
true
const
label
=
data
[
this
.
treeProps
.
label
]
||
''
return
label
.
toLowerCase
().
includes
(
value
.
toLowerCase
())
},
/**
* 处理搜索
*/
handleSearch
(
value
)
{
this
.
$refs
.
treeRef
.
filter
(
value
)
},
/**
* 节点点击事件
*/
handleNodeClick
(
data
,
node
,
component
)
{
this
.
selectedNode
=
{
data
,
node
,
component
}
this
.
$emit
(
'node-click'
,
data
,
node
,
component
)
},
/**
* 节点展开事件
*/
handleNodeExpand
(
data
,
node
,
component
)
{
this
.
$emit
(
'node-expand'
,
data
,
node
,
component
)
},
/**
* 节点折叠事件
*/
handleNodeCollapse
(
data
,
node
,
component
)
{
this
.
$emit
(
'node-collapse'
,
data
,
node
,
component
)
},
/**
* 当前节点变化事件
*/
handleCurrentChange
(
data
,
node
)
{
this
.
$emit
(
'current-change'
,
data
,
node
)
},
/**
* 重置树结构
*/
resetTree
()
{
// 修复:使用正确的 ref 名称 treeRef
if
(
this
.
$refs
.
treeRef
)
{
this
.
$refs
.
treeRef
.
setCurrentKey
(
null
);
this
.
searchText
=
''
;
this
.
$refs
.
treeRef
.
filter
(
''
);
// 清空搜索
}
},
/**
* 设置当前选中的节点
*/
setCurrentNode
(
node
)
{
this
.
$refs
.
treeRef
.
setCurrentNode
(
node
)
},
/**
* 设置当前选中的节点key
*/
setCurrentKey
(
key
)
{
this
.
$refs
.
treeRef
.
setCurrentKey
(
key
)
},
/**
* 获取当前选中的节点
*/
getCurrentNode
()
{
return
this
.
$refs
.
treeRef
.
getCurrentNode
()
},
/**
* 获取当前选中的节点key
*/
getCurrentKey
()
{
return
this
.
$refs
.
treeRef
.
getCurrentKey
()
},
/**
* 展开指定节点
*/
expandNode
(
node
)
{
this
.
$refs
.
treeRef
.
expandNode
(
node
)
},
/**
* 折叠指定节点
*/
collapseNode
(
node
)
{
this
.
$refs
.
treeRef
.
collapseNode
(
node
)
},
/**
* 展开所有节点
*/
expandAll
()
{
this
.
$refs
.
treeRef
.
expandAll
()
},
/**
* 折叠所有节点
*/
collapseAll
()
{
this
.
$refs
.
treeRef
.
collapseAll
()
},
/**
* 更新节点数据
*/
updateKeyChildren
(
key
,
data
)
{
this
.
$refs
.
treeRef
.
updateKeyChildren
(
key
,
data
)
},
/**
* 获取节点信息
*/
getNode
(
key
)
{
return
this
.
$refs
.
treeRef
.
getNode
(
key
)
},
/**
* 移除节点
*/
remove
(
key
)
{
this
.
$refs
.
treeRef
.
remove
(
key
)
},
/**
* 追加节点数据
*/
append
(
data
,
parentNode
)
{
this
.
$refs
.
treeRef
.
append
(
data
,
parentNode
)
},
/**
* 插入节点数据
*/
insertBefore
(
data
,
refNode
)
{
this
.
$refs
.
treeRef
.
insertBefore
(
data
,
refNode
)
},
/**
* 插入节点数据后
*/
insertAfter
(
data
,
refNode
)
{
this
.
$refs
.
treeRef
.
insertAfter
(
data
,
refNode
)
}
}
}
</
script
>
<
style
scoped
>
.tree-container
{
height
:
100%
;
display
:
flex
;
flex-direction
:
column
;
}
.tree-header
{
flex-shrink
:
0
;
}
.tree-body
{
flex
:
1
;
overflow
:
auto
;
}
.custom-tree-node
{
flex
:
1
;
display
:
flex
;
align-items
:
center
;
justify-content
:
space-between
;
font-size
:
14px
;
padding-right
:
8px
;
}
.tree-empty
{
height
:
100%
;
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
color
:
#999
;
}
</
style
>
\ No newline at end of file
ruoyi-admin-vue/src/views/system/user/index.vue
View file @
e76b86c2
...
...
@@ -9,7 +9,16 @@
<el-input
v-model=
"deptName"
placeholder=
"请输入部门名称"
clearable
size=
"small"
prefix-icon=
"el-icon-search"
style=
"margin-bottom: 20px"
/>
</div>
<div
class=
"head-container"
>
<el-tree
:data=
"deptOptions"
:props=
"defaultProps"
:expand-on-click-node=
"false"
:filter-node-method=
"filterNode"
ref=
"tree"
node-key=
"id"
default-expand-all
highlight-current
@
node-click=
"handleNodeClick"
/>
<el-tree
:data=
"deptOptions"
:props=
"defaultProps"
:expand-on-click-node=
"false"
:filter-node-method=
"filterNode"
ref=
"tree"
node-key=
"id"
default-expand-all
highlight-current
@
node-click=
"handleNodeClick"
/>
</div>
</el-col>
</pane>
...
...
ruoyi-admin/src/main/java/com/ruoyi/web/controller/inventory/MaterialsCategoryController.java
View file @
e76b86c2
...
...
@@ -3,6 +3,7 @@ package com.ruoyi.web.controller.inventory;
import
java.util.List
;
import
javax.servlet.http.HttpServletResponse
;
import
com.ruoyi.common.core.domain.entity.SysDept
;
import
com.ruoyi.common.utils.uuid.UUID
;
import
org.springframework.security.access.prepost.PreAuthorize
;
import
org.springframework.beans.factory.annotation.Autowired
;
...
...
@@ -18,7 +19,7 @@ import com.ruoyi.common.annotation.Log;
import
com.ruoyi.common.core.controller.BaseController
;
import
com.ruoyi.common.core.domain.AjaxResult
;
import
com.ruoyi.common.enums.BusinessType
;
import
com.ruoyi.
inventory.domain
.MaterialsCategory
;
import
com.ruoyi.
common.core.domain.entity
.MaterialsCategory
;
import
com.ruoyi.inventory.service.IMaterialsCategoryService
;
import
com.ruoyi.common.utils.poi.ExcelUtil
;
import
com.ruoyi.common.core.page.TableDataInfo
;
...
...
@@ -72,6 +73,16 @@ public class MaterialsCategoryController extends BaseController
}
/**
* 获取分类树结构
*/
@PreAuthorize
(
"@ss.hasPermi('inventory:materials_category:list')"
)
@GetMapping
(
"/categoryTree"
)
public
AjaxResult
categoryTree
(
MaterialsCategory
materialsCategory
)
{
return
success
(
materialsCategoryService
.
selectMaterialsCategoryTreeList
(
materialsCategory
));
}
/**
* 新增物料分类
*/
@PreAuthorize
(
"@ss.hasPermi('inventory:materials_category:add')"
)
...
...
ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java
View file @
e76b86c2
...
...
@@ -63,6 +63,7 @@ public class UserConstants
/** InnerLink组件标识 */
public
final
static
String
INNER_LINK
=
"InnerLink"
;
/** 校验是否唯一的返回标识 */
public
final
static
boolean
UNIQUE
=
true
;
public
final
static
boolean
NOT_UNIQUE
=
false
;
...
...
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java
View file @
e76b86c2
...
...
@@ -5,6 +5,7 @@ import java.util.List;
import
java.util.stream.Collectors
;
import
com.fasterxml.jackson.annotation.JsonInclude
;
import
com.ruoyi.common.constant.UserConstants
;
import
com.ruoyi.common.core.domain.entity.MaterialsCategory
;
import
com.ruoyi.common.core.domain.entity.SysDept
;
import
com.ruoyi.common.core.domain.entity.SysMenu
;
import
com.ruoyi.common.utils.StringUtils
;
...
...
@@ -21,6 +22,8 @@ public class TreeSelect implements Serializable
/** 节点ID */
private
String
id
;
/** String节点ID */
private
String
sid
;
/** 节点名称 */
private
String
label
;
...
...
@@ -43,7 +46,12 @@ public class TreeSelect implements Serializable
this
.
disabled
=
StringUtils
.
equals
(
UserConstants
.
DEPT_DISABLE
,
dept
.
getStatus
());
this
.
children
=
dept
.
getChildren
().
stream
().
map
(
TreeSelect:
:
new
).
collect
(
Collectors
.
toList
());
}
public
TreeSelect
(
MaterialsCategory
materialsCategory
){
this
.
sid
=
materialsCategory
.
getId
();
this
.
label
=
materialsCategory
.
getCategoryName
();
this
.
disabled
=
StringUtils
.
equals
(
String
.
valueOf
(
0
),
String
.
valueOf
(
materialsCategory
.
getIsUsed
()));
this
.
children
=
materialsCategory
.
getChildren
().
stream
().
map
(
TreeSelect:
:
new
).
collect
(
Collectors
.
toList
());
}
public
TreeSelect
(
SysMenu
menu
)
{
this
.
id
=
String
.
valueOf
(
menu
.
getMenuId
());
...
...
@@ -90,4 +98,12 @@ public class TreeSelect implements Serializable
{
this
.
children
=
children
;
}
public
String
getSid
()
{
return
sid
;
}
public
void
setSid
(
String
sid
)
{
this
.
sid
=
sid
;
}
}
ruoyi-
inventory/src/main/java/com/ruoyi/inventory/domain
/MaterialsCategory.java
→
ruoyi-
common/src/main/java/com/ruoyi/common/core/domain/entity
/MaterialsCategory.java
View file @
e76b86c2
package
com
.
ruoyi
.
inventory
.
domain
;
package
com
.
ruoyi
.
common
.
core
.
domain
.
entity
;
import
org.apache.commons.lang3.builder.ToStringBuilder
;
import
org.apache.commons.lang3.builder.ToStringStyle
;
import
com.ruoyi.common.annotation.Excel
;
import
com.ruoyi.common.core.domain.BaseEntity
;
import
java.util.ArrayList
;
import
java.util.List
;
/**
* 物料分类对象 materials_category
*
...
...
@@ -31,6 +34,15 @@ public class MaterialsCategory extends BaseEntity
@Excel
(
name
=
"排序"
)
private
Long
sortNo
;
@Excel
(
name
=
"父级Code"
)
private
String
parentId
;
@Excel
(
name
=
"使用状态"
)
private
int
isUsed
;
private
String
parentName
;
private
List
<
MaterialsCategory
>
children
=
new
ArrayList
<
MaterialsCategory
>();
/** 创建日期 */
private
String
createUserCode
;
...
...
@@ -97,6 +109,38 @@ public class MaterialsCategory extends BaseEntity
return
updateUserCode
;
}
public
String
getParentId
()
{
return
parentId
;
}
public
void
setParentId
(
String
parentId
)
{
this
.
parentId
=
parentId
;
}
public
int
getIsUsed
()
{
return
isUsed
;
}
public
void
setIsUsed
(
int
isUsed
)
{
this
.
isUsed
=
isUsed
;
}
public
String
getParentName
()
{
return
parentName
;
}
public
void
setParentName
(
String
parentName
)
{
this
.
parentName
=
parentName
;
}
public
List
<
MaterialsCategory
>
getChildren
()
{
return
children
;
}
public
void
setChildren
(
List
<
MaterialsCategory
>
children
)
{
this
.
children
=
children
;
}
@Override
public
String
toString
()
{
return
new
ToStringBuilder
(
this
,
ToStringStyle
.
MULTI_LINE_STYLE
)
...
...
@@ -108,6 +152,10 @@ public class MaterialsCategory extends BaseEntity
.
append
(
"createUserCode"
,
getCreateUserCode
())
.
append
(
"updateTime"
,
getUpdateTime
())
.
append
(
"updateUserCode"
,
getUpdateUserCode
())
.
append
(
"parentId"
,
getParentId
())
.
append
(
"isUsed"
,
getIsUsed
())
.
append
(
"parentName"
,
getParentName
())
.
append
(
"children"
,
getChildren
())
.
toString
();
}
}
ruoyi-inventory/pom.xml
View file @
e76b86c2
...
...
@@ -22,5 +22,6 @@
<groupId>
com.ruoyi
</groupId>
<artifactId>
ruoyi-common
</artifactId>
</dependency>
</dependencies>
</project>
\ No newline at end of file
ruoyi-inventory/src/main/java/com/ruoyi/inventory/mapper/MaterialsCategoryMapper.java
View file @
e76b86c2
package
com
.
ruoyi
.
inventory
.
mapper
;
import
java.util.List
;
import
com.ruoyi.
inventory.domain
.MaterialsCategory
;
import
com.ruoyi.
common.core.domain.entity
.MaterialsCategory
;
/**
* 物料分类Mapper接口
...
...
@@ -18,7 +18,6 @@ public interface MaterialsCategoryMapper
* @return 物料分类
*/
public
MaterialsCategory
selectMaterialsCategoryById
(
String
id
);
/**
* 查询物料分类列表
*
...
...
ruoyi-inventory/src/main/java/com/ruoyi/inventory/mapper/MaterialsMapper.java
View file @
e76b86c2
...
...
@@ -61,7 +61,12 @@ public interface MaterialsMapper
* @return 结果
*/
public
int
deleteMaterialsByIds
(
String
[]
ids
);
/**
* 批量删除,修改物料的使用状态
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public
int
updateMaterialsIsUsedByIds
(
String
[]
ids
);
}
ruoyi-inventory/src/main/java/com/ruoyi/inventory/service/IMaterialsCategoryService.java
View file @
e76b86c2
package
com
.
ruoyi
.
inventory
.
service
;
import
java.util.List
;
import
com.ruoyi.inventory.domain.MaterialsCategory
;
import
com.ruoyi.common.core.domain.TreeSelect
;
import
com.ruoyi.common.core.domain.entity.MaterialsCategory
;
/**
* 物料分类Service接口
...
...
@@ -28,6 +30,30 @@ public interface IMaterialsCategoryService
public
List
<
MaterialsCategory
>
selectMaterialsCategoryList
(
MaterialsCategory
materialsCategory
);
/**
* 查询分类树结构
*
* @param materialsCategory 物料分类
* @return 结果
*/
public
List
<
TreeSelect
>
selectMaterialsCategoryTreeList
(
MaterialsCategory
materialsCategory
);
/**
* 构建前端所需要树结构
*
* @param materialsCategorys 物料分类
* @return 结果
*/
public
List
<
MaterialsCategory
>
buildMaterialsCategoryTree
(
List
<
MaterialsCategory
>
materialsCategorys
);
/**
* 构建前端所需要下拉树结构
*
* @param materialsCategorys 物料分类
* @return 结果
*/
public
List
<
TreeSelect
>
buildTreeSelect
(
List
<
MaterialsCategory
>
materialsCategorys
);
/**
* 新增物料分类
*
* @param materialsCategory 物料分类
...
...
ruoyi-inventory/src/main/java/com/ruoyi/inventory/service/impl/MaterialsCategoryServiceImpl.java
View file @
e76b86c2
package
com
.
ruoyi
.
inventory
.
service
.
impl
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.Iterator
;
import
java.util.List
;
import
java.util.stream.Collectors
;
import
com.ruoyi.common.core.domain.TreeSelect
;
import
com.ruoyi.common.utils.DateUtils
;
import
com.ruoyi.common.utils.StringUtils
;
import
com.ruoyi.common.utils.spring.SpringUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
com.ruoyi.inventory.mapper.MaterialsCategoryMapper
;
import
com.ruoyi.
inventory.domain
.MaterialsCategory
;
import
com.ruoyi.
common.core.domain.entity
.MaterialsCategory
;
import
com.ruoyi.inventory.service.IMaterialsCategoryService
;
/**
...
...
@@ -43,6 +51,86 @@ public class MaterialsCategoryServiceImpl implements IMaterialsCategoryService
{
return
materialsCategoryMapper
.
selectMaterialsCategoryList
(
materialsCategory
);
}
/**
* 查询分类树结构
*
* @param materialsCategory 物料分类
* @return 结果
*/
@Override
public
List
<
TreeSelect
>
selectMaterialsCategoryTreeList
(
MaterialsCategory
materialsCategory
)
{
List
<
MaterialsCategory
>
materialsCategorys
=
SpringUtils
.
getAopProxy
(
this
).
selectMaterialsCategoryList
(
materialsCategory
);
return
buildTreeSelect
(
materialsCategorys
);
}
/**
* 构建前端所需要树结构
*
* @param materialsCategorys 物料分类
* @return 结果
*/
@Override
public
List
<
MaterialsCategory
>
buildMaterialsCategoryTree
(
List
<
MaterialsCategory
>
materialsCategorys
)
{
List
<
MaterialsCategory
>
returnList
=
new
ArrayList
<
MaterialsCategory
>();
// List<String> tempList = materialsCategorys.stream().map(MaterialsCategory::getId).collect(Collectors.toList());
for
(
MaterialsCategory
materialsCategory
:
materialsCategorys
)
{
// 如果是顶级节点, 遍历该父节点的所有子节点
if
(
StringUtils
.
isNull
(
materialsCategory
.
getParentId
())
||
materialsCategory
.
getParentId
().
isEmpty
()){
recursionFn
(
materialsCategorys
,
materialsCategory
);
returnList
.
add
(
materialsCategory
);
}
}
if
(
returnList
.
isEmpty
()){
returnList
=
materialsCategorys
;
}
return
returnList
;
}
/**
* 递归列表
*/
private
void
recursionFn
(
List
<
MaterialsCategory
>
materialsCategoryList
,
MaterialsCategory
materialsCategory
)
{
// 得到子节点列表
List
<
MaterialsCategory
>
childList
=
getChildList
(
materialsCategoryList
,
materialsCategory
);
materialsCategory
.
setChildren
(
childList
);
// 如果有子节点,递归处理
if
(!
childList
.
isEmpty
())
{
for
(
MaterialsCategory
child
:
childList
)
{
recursionFn
(
materialsCategoryList
,
child
);
}
}
}
/**
* 得到子节点列表
*/
private
List
<
MaterialsCategory
>
getChildList
(
List
<
MaterialsCategory
>
list
,
MaterialsCategory
materialsCategory
){
List
<
MaterialsCategory
>
childList
=
new
ArrayList
<>();
Iterator
<
MaterialsCategory
>
iterator
=
list
.
iterator
();
while
(
iterator
.
hasNext
()){
MaterialsCategory
m
=
(
MaterialsCategory
)
iterator
.
next
();
if
(
StringUtils
.
equals
(
m
.
getParentId
(),
materialsCategory
.
getId
())){
childList
.
add
(
m
);
}
}
return
childList
;
}
/**
* 判断是否有子节点
*/
private
boolean
hasChild
(
List
<
MaterialsCategory
>
list
,
MaterialsCategory
m
){
return
getChildList
(
list
,
m
).
size
()
>
0
;
}
/**
* 构建前端所需要下拉树结构
*
* @param materialsCategorys 物料分类
* @return 结果
*/
@Override
public
List
<
TreeSelect
>
buildTreeSelect
(
List
<
MaterialsCategory
>
materialsCategorys
)
{
List
<
MaterialsCategory
>
materialsCategories
=
buildMaterialsCategoryTree
(
materialsCategorys
);
return
materialsCategories
.
stream
().
map
(
TreeSelect:
:
new
).
collect
(
Collectors
.
toList
());
}
/**
* 新增物料分类
...
...
ruoyi-inventory/src/main/resources/mapper/inventory/MaterialsCategoryMapper.xml
View file @
e76b86c2
...
...
@@ -13,20 +13,24 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result
property=
"createUserCode"
column=
"create_user_code"
/>
<result
property=
"updateTime"
column=
"update_time"
/>
<result
property=
"updateUserCode"
column=
"update_user_code"
/>
<result
property=
"parentId"
column=
"parent_id"
/>
<result
property=
"isUsed"
column=
"is_used"
/>
</resultMap>
<sql
id=
"selectMaterialsCategoryVo"
>
select id, category_code, category_name, sort_no, create_time, create_user_code, update_time, update_user_code from materials_category
select id, category_code, category_name, sort_no, create_time, create_user_code, update_time, update_user_code
, parent_id, is_used
from materials_category
</sql>
<select
id=
"selectMaterialsCategoryList"
parameterType=
"MaterialsCategory"
resultMap=
"MaterialsCategoryResult"
>
<include
refid=
"selectMaterialsCategoryVo"
/>
<where>
<if
test=
"id != null and id != ''"
>
and id = #{id}
</if>
<if
test=
"categoryCode != null and categoryCode != ''"
>
and category_code like concat('%', #{categoryCode}, '%')
</if>
<if
test=
"categoryName != null and categoryName != ''"
>
and category_name like concat('%', #{categoryName}, '%')
</if>
<if
test=
"sortNo != null "
>
and sort_no = #{sortNo}
</if>
<if
test=
"createTime != null "
>
and create_time like concat('%', #{createTime}, '%')
</if>
<if
test=
"updateTime != null "
>
and update_time like concat('%', #{updateTime}, '%')
</if>
<if
test=
"parentId != null "
>
and parent_id = #{parentId}
</if>
</where>
order by sort_no asc
</select>
...
...
@@ -48,6 +52,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if
test=
"createUserCode != null"
>
create_user_code,
</if>
<if
test=
"updateTime != null"
>
update_time,
</if>
<if
test=
"updateUserCode != null"
>
update_user_code,
</if>
<if
test=
"parentId != null"
>
parent_id,
</if>
<if
test=
"isUsed != null"
>
is_used,
</if>
</trim>
<trim
prefix=
"values ("
suffix=
")"
suffixOverrides=
","
>
<if
test=
"id != null"
>
#{id},
</if>
...
...
@@ -58,6 +64,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if
test=
"createUserCode != null"
>
#{createUserCode},
</if>
<if
test=
"updateTime != null"
>
#{updateTime},
</if>
<if
test=
"updateUserCode != null"
>
#{updateUserCode},
</if>
<if
test=
"parentId != null"
>
#{parentId},
</if>
<if
test=
"isUsed != null"
>
#{isUsed},
</if>
</trim>
</insert>
...
...
@@ -71,6 +79,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if
test=
"createUserCode != null"
>
create_user_code = #{createUserCode},
</if>
<if
test=
"updateTime != null"
>
update_time = #{updateTime},
</if>
<if
test=
"updateUserCode != null"
>
update_user_code = #{updateUserCode},
</if>
<if
test=
"parentId != null"
>
parent_id = #{parentId},
</if>
<if
test=
"isUsed != null"
>
is_used = #{isUsed},
</if>
</trim>
where id = #{id}
</update>
...
...
ruoyi-inventory/src/main/resources/mapper/inventory/MaterialsMapper.xml
View file @
e76b86c2
...
...
@@ -46,7 +46,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if
test=
"materialName != null and materialName != ''"
>
and material_name like concat('%', #{materialName}, '%')
</if>
<if
test=
"sapNo != null and sapNo != ''"
>
and sap_no like concat('%', #{sapNo}, '%')
</if>
<if
test=
"tsCode != null and tsCode != ''"
>
and ts_code like concat('%', #{tsCode}, '%')
</if>
<if
test=
"categoryCode != null and categoryCode != ''"
>
and category_code
like concat('%', #{categoryCode}, '%')
</if>
<if
test=
"categoryCode != null and categoryCode != ''"
>
and category_code
= #{categoryCode}
</if>
<if
test=
"hazardId != null and hazardId != ''"
>
and hazard_id like concat('%', #{hazardId}, '%')
</if>
<if
test=
"specification != null and specification != ''"
>
and specification like concat('%', #{specification}, '%')
</if>
<if
test=
"materialUnit != null and materialUnit != ''"
>
and material_unit like concat('%', #{materialUnit}, '%')
</if>
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论