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
dec88768
Commit
dec88768
authored
Dec 02, 2025
by
zhangtw
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
物料分类管理新增页面
parent
f3255ab9
显示空白字符变更
内嵌
并排
正在显示
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 @
dec88768
...
...
@@ -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 @
dec88768
<
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 @
dec88768
<
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 @
dec88768
<
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 @
dec88768
...
...
@@ -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 @
dec88768
...
...
@@ -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 @
dec88768
...
...
@@ -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 @
dec88768
...
...
@@ -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
Long
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
=
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 @
dec88768
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 @
dec88768
...
...
@@ -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 @
dec88768
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 @
dec88768
...
...
@@ -59,7 +59,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 @
dec88768
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 @
dec88768
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 @
dec88768
...
...
@@ -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 @
dec88768
...
...
@@ -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
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论