明树Git Lab
Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
J
jt_front
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
jt_front
Commits
4cfcb74f
Commit
4cfcb74f
authored
Dec 11, 2025
by
yangyajing
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
部门管理
parent
e1030023
Pipeline
#104515
passed with stage
in 14 seconds
Changes
2
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
233 additions
and
335 deletions
+233
-335
manage.less
src/styles/manage.less
+2
-2
departManage.vue
src/views/systemManage/departManage.vue
+231
-333
No files found.
src/styles/manage.less
View file @
4cfcb74f
...
...
@@ -23,7 +23,7 @@
.manage-content{
flex: 1;
height: 0;
&>
.common-table{
.common-table{
height: 100%;
display: flex;
flex-direction: column;
...
...
@@ -70,7 +70,7 @@
height: 0;
display: flex;
flex-direction: column;
&>
.common-table{
.common-table{
height: 100%;
display: flex;
flex-direction: column;
...
...
src/views/systemManage/departManage.vue
View file @
4cfcb74f
<
template
>
<div
class=
"depart-manage"
v-loading=
"loading"
>
<div
class=
"manage-left"
>
<div
class=
"
origin-title
"
>
<
h4>
部门
</h4
>
<div
class=
"
handle-btn
"
>
<
el-button
type=
"primary"
size=
"small"
@
click=
"handleAdd"
>
新增
</el-button
>
</div>
<div
class=
"tree-content"
>
<span
class=
"filterRow"
>
<el-dropdown>
<span
class=
"el-dropdown-link"
>
<i
class=
"iconfont icon-gengduo"
></i>
</span>
<template
#
dropdown
>
<el-dropdown-menu>
<el-dropdown-item
@
click=
"handleAdd"
><i
class=
"iconfont icon-tianjia"
></i
>
添加组织
</el-dropdown-item
>
<el-dropdown-item
@
click=
"handleOriginEdit"
><i
class=
"iconfont icon-bianji"
></i
>
编辑组织
</el-dropdown-item
>
<el-dropdown-item
@
click=
"handleDeleteOrigin"
><i
class=
"iconfont icon-shanchu"
></i
>
删除组织
</el-dropdown-item
>
</el-dropdown-menu>
</
template
>
</el-dropdown>
</span>
<el-tree
:data=
"treeData"
node-key=
"id"
default-expand-all
draggable
:props=
"
{label: 'name'}"
@node-click="handleNodeClick"
>
<template
#
default=
"
{ node, data }">
<div
class=
"custom-tree-node"
>
<span
class=
"node-name"
>
{{
node
.
label
}}
</span>
<el-dropdown>
<span
class=
"el-dropdown-link"
>
<i
class=
"iconfont icon-gengduo"
></i>
</span>
<template
#
dropdown
>
<el-dropdown-menu>
<el-dropdown-item
@
click=
"handleAddChild(data)"
><i
class=
"iconfont icon-tianjia"
></i
>
添加子部门
</el-dropdown-item
>
<el-dropdown-item
@
click=
"handleEdit(data)"
><i
class=
"iconfont icon-bianji"
></i
>
编辑
</el-dropdown-item
>
<el-dropdown-item
@
click=
"handleDelete(data)"
><i
class=
"iconfont icon-shanchu"
></i
>
删除
</el-dropdown-item
>
</el-dropdown-menu>
</
template
>
</el-dropdown>
</div>
</template>
</el-tree>
</div>
</div>
<div
class=
"
table-container
"
v-loading=
"userLoading"
>
<div
class=
"search-contain"
>
<
div
>
人员信息:
<el-input
placeholder=
"请输入人员信息"
v-model=
"userName
"
/>
</div
>
<div
>
<el-button
type=
""
@
click=
"handleReset"
>
重置
</el-button>
<
el-button
type=
"primary"
@
click=
"handleUserData"
>
查询
</el-button
>
</
div
>
<div
class=
"
user-content
"
v-loading=
"userLoading"
>
<div
class=
"search-contain
er
"
>
<
el-form
:inline=
"true"
:model=
"searchForm"
>
<el-form-item
label=
"关键字查询"
>
<el-input
v-model=
"searchForm.name"
:style=
"{width: '220px'}"
clearable
placeholder=
"请输入用户姓名
"
/>
</el-form-item
>
<el-form-item
>
<el-button
type=
"primary"
@
click=
"handleSearch"
>
查询
</el-button>
<
/el-form-item
>
</
el-form
>
</div>
<common-table
:autoHeight=
"true"
:maxRows=
"10"
:data=
"tableData"
:columns=
"tableColumns"
:total=
"total"
...
...
@@ -74,16 +76,19 @@
v-model=
"dialogVisible"
:title=
"dialogTitle"
width=
"400px"
@
close=
"
handleDialogClose
"
@
close=
"
cancelDepartForm
"
>
<commonForm
v-model=
"originForm"
:config=
"formConfig"
:items=
"formItems"
:rules=
"formRules"
@
submit=
"handleFormSubmit"
@
reset=
"handleFormReset"
/>
<el-form
:model=
"departFormData"
ref=
"departForm"
:rules=
"departRules"
label-width=
"100"
>
<el-form-item
label=
"项目名称"
prop=
"name"
>
<el-input
v-model=
"departFormData.name"
/>
</el-form-item>
</el-form>
<
template
#
footer
>
<div
class=
"dialog-footer"
>
<el-button
@
click=
"cancelDepartForm"
>
取消
</el-button>
<el-button
type=
"primary"
@
click=
"saveDepartForm"
>
保存
</el-button>
</div>
</
template
>
</el-dialog>
</div>
</template>
...
...
@@ -91,276 +96,95 @@
<
script
setup
>
import
{
ref
,
reactive
,
onMounted
,
getCurrentInstance
,
computed
}
from
"vue"
;
import
{
ElMessage
,
ElMessageBox
}
from
"element-plus"
;
import
commonForm
from
"@/components/common/commonForm.vue"
;
import
CommonTable
from
"@/components/common/commonTable.vue"
;
const
{
proxy
}
=
getCurrentInstance
();
const
loading
=
ref
(
false
);
const
userLoading
=
ref
(
false
);
const
treeData
=
ref
([]);
const
originTreeData
=
ref
([]);
const
selectedNode
=
ref
(
null
);
const
userName
=
ref
(
""
);
// 数据转换函数
const
convertToTreeData
=
(
apiData
,
type
)
=>
{
if
(
type
===
"id"
)
{
return
apiData
.
map
((
item
)
=>
({
id
:
item
.
id
,
label
:
item
.
name
,
parentId
:
item
.
parentId
,
children
:
item
.
children
?
convertToTreeData
(
item
.
children
,
"id"
)
:
[],
}));
}
else
{
return
apiData
.
map
((
item
)
=>
({
parentId
:
item
.
parentId
,
value
:
item
.
id
,
label
:
item
.
name
,
children
:
item
.
children
?
convertToTreeData
(
item
.
children
,
"value"
)
:
[],
}));
}
};
// 表格数据
const
tableData
=
ref
([]);
const
total
=
ref
(
0
);
const
currentPage
=
ref
(
1
);
const
pageSize
=
ref
(
10
);
// 表格列配置
const
tableColumns
=
[
{
prop
:
"name"
,
label
:
"用户姓名"
,
minWidth
:
100
,
showOverflowTooltip
:
true
,
},
{
prop
:
"departs"
,
label
:
"所属部门"
,
minWidth
:
80
,
showOverflowTooltip
:
true
,
},
{
prop
:
"positions"
,
label
:
"岗位"
,
minWidth
:
100
,
showOverflowTooltip
:
true
,
},
{
prop
:
"roles"
,
label
:
"角色"
,
minWidth
:
100
,
showOverflowTooltip
:
true
,
},
{
prop
:
"mobile"
,
label
:
"手机号码"
,
minWidth
:
100
,
},
{
prop
:
"createdAt"
,
label
:
"创建时间"
,
minWidth
:
160
,
},
{
prop
:
"enable"
,
label
:
"状态"
,
width
:
100
,
slot
:
"enable"
,
align
:
"center"
,
},
];
// 对话框相关
const
dialogVisible
=
ref
(
false
);
const
dialogTitle
=
ref
(
"新增用户"
);
const
isEdit
=
ref
(
false
);
// 用户表单数据
const
originForm
=
ref
({
name
:
""
,
parentId
:
""
,
});
// 用户表单配置
const
formConfig
=
{
labelWidth
:
"100px"
,
showButtons
:
true
,
submitText
:
"保存"
,
resetText
:
"取消"
,
};
// 用户表单项配置
const
formItems
=
computed
(()
=>
[
{
type
:
"tree"
,
prop
:
"parentId"
,
label
:
"上级组织"
,
placeholder
:
"请选择上级组织"
,
data
:
originTreeData
.
value
,
clearable
:
true
,
filterable
:
true
,
checkStrictly
:
true
,
renderAfterExpand
:
false
,
showCheckbox
:
false
,
multiple
:
false
,
span
:
24
,
// required: true,
// rules: [{ required: true, message: "请选择上级组织", trigger: "blur" }],
},
{
type
:
"input"
,
prop
:
"name"
,
label
:
"组织名称:"
,
placeholder
:
"请输入组织名称"
,
required
:
true
,
rules
:
[{
required
:
true
,
message
:
"请输入组织名称"
,
trigger
:
"blur"
}],
span
:
24
,
},
]);
const
dialogTitle
=
ref
(
""
);
let
departFormData
=
ref
({});
const
departForm
=
ref
();
// 表单验证规则
const
formRules
=
{};
const
handleSizeChange
=
(
size
)
=>
{
pageSize
.
value
=
size
;
currentPage
.
value
=
1
;
loadTableData
();
const
departRules
=
{
name
:
[
{
required
:
true
,
message
:
"请输入部门名称"
,
trigger
:
"blur"
}
]
};
const
handleCurrentPageChange
=
(
page
)
=>
{
currentPage
.
value
=
page
;
loadTableData
();
};
// 新增用户
// 新增部门
const
handleAdd
=
()
=>
{
isEdit
.
value
=
false
;
dialogTitle
.
value
=
"新增组织"
;
dialogTitle
.
value
=
"新增部门"
;
dialogVisible
.
value
=
true
;
console
.
log
(
selectedNode
.
value
);
originForm
.
value
=
{
parentId
:
""
,
name
:
""
,
};
};
let
currentID
=
ref
(
""
);
// 处理树节点点击事件
const
handleNodeClick
=
(
data
,
node
,
element
)
=>
{
selectedNode
.
value
=
data
;
currentID
.
value
=
selectedNode
.
value
.
id
;
handleUserData
();
};
// 组织详情
const
handleOriginEdit
=
()
=>
{
if
(
selectedNode
.
value
===
null
)
{
ElMessage
.
warning
(
"请选择要编辑的数据"
);
}
else
{
isEdit
.
value
=
true
;
dialogVisible
.
value
=
true
;
dialogTitle
.
value
=
"编辑组织"
;
const
selectID
=
{
id
:
selectedNode
.
value
.
id
,
};
proxy
.
$post
({
url
:
"/api/user/depart/getDepart"
,
data
:
selectID
,
callback
:
(
data
)
=>
{
originForm
.
value
=
{
...
data
};
currentID
.
value
=
data
.
id
;
},
error
:
(
err
)
=>
{
ElMessage
.
error
(
"编辑失败:"
,
err
);
},
});
}
};
// 组织删除
const
handleDeleteOrigin
=
()
=>
{
console
.
log
(
selectedNode
.
value
);
if
(
selectedNode
.
value
===
null
)
{
ElMessage
.
warning
(
"请选择要删除的组织"
);
}
else
{
const
deleteItem
=
{
id
:
selectedNode
.
value
.
id
,
name
:
selectedNode
.
value
.
label
,
parentId
:
selectedNode
.
value
.
parentId
?
selectedNode
.
value
.
parentId
:
null
,
};
proxy
.
$post
({
url
:
"/api/user/depart/deleteDepart"
,
data
:
deleteItem
,
callback
:
(
data
)
=>
{
handleTreeData
();
ElMessage
.
success
(
"删除成功"
);
},
error
:
(
err
)
=>
{
ElMessage
.
error
(
"删除失败"
,
err
);
},
// 添加子部门
const
handleAddChild
=
(
data
)
=>
{
dialogTitle
.
value
=
"新增子部门"
;
departFormData
.
value
.
parentId
=
data
.
id
;
dialogVisible
.
value
=
true
;
}
const
handleEdit
=
(
data
)
=>
{
departFormData
.
value
=
{...
data
};
dialogTitle
.
value
=
"编辑部门"
;
dialogVisible
.
value
=
true
;
}
const
handleDelete
=
(
data
)
=>
{
ElMessageBox
.
confirm
(
`确定删除
${
data
.
name
}
?`
,
"提示"
,
{
confirmButtonText
:
"确定"
,
cancelButtonText
:
"取消"
,
type
:
"warning"
,
}).
then
(()
=>
{
proxy
.
$post
({
url
:
"/api/user/depart/deleteDepart"
,
data
:
{
id
:
data
.
id
},
callback
:
(
data
)
=>
{
ElMessage
.
success
(
"删除成功"
);
loadTreeData
();
},
error
:
(
err
)
=>
{
ElMessage
.
error
(
"删除失败:"
,
err
);
},
});
});
}
};
}
const
handleFormSubmit
=
(
formData
)
=>
{
if
(
isEdit
.
value
)
{
// 编辑组织
const
updateOriForm
=
{
...
formData
,
parentId
:
formData
.
parentId
?
formData
.
parentId
:
null
,
id
:
currentID
.
value
,
};
proxy
.
$post
({
url
:
"/api/user/depart/updateDepart"
,
data
:
updateOriForm
,
callback
:
(
data
)
=>
{
dialogVisible
.
value
=
false
;
handleTreeData
();
ElMessage
.
success
(
"组织更新成功"
);
},
error
:
(
err
)
=>
{
ElMessage
.
error
(
"组织更新失败"
,
err
);
},
});
}
else
{
// 新增组织
const
addOroginForm
=
{
...
formData
,
parentId
:
formData
.
parentId
?
formData
.
parentId
:
null
,
};
proxy
.
$post
({
url
:
"/api/user/depart/createDepart"
,
data
:
addOroginForm
,
callback
:
(
data
)
=>
{
dialogVisible
.
value
=
false
;
handleTreeData
();
ElMessage
.
success
(
"组织添加成功"
);
},
error
:
(
err
)
=>
{
ElMessage
.
error
(
"组织添加失败:"
,
err
);
},
});
}
};
const
handleFormReset
=
()
=>
{
dialogVisible
.
value
=
false
;
selectedNode
.
value
=
""
;
const
saveDepartForm
=
()
=>
{
let
url
=
departFormData
.
value
.
id
?
"updateDepart"
:
"createDepart"
proxy
.
$post
({
url
:
"/api/user/depart/"
+
url
,
data
:
departFormData
.
value
,
callback
:
(
data
)
=>
{
ElMessage
.
success
(
dialogTitle
.
value
+
"成功"
);
cancelDepartForm
();
loadTreeData
();
},
error
:
(
err
)
=>
{
ElMessage
.
error
(
"组织添加失败:"
,
err
);
},
});
};
const
handleDialogClose
=
()
=>
{
const
cancelDepartForm
=
()
=>
{
departForm
.
value
.
resetFields
();
departFormData
.
value
=
{};
dialogVisible
.
value
=
false
;
selectedNode
.
value
=
null
;
};
const
handleReset
=
()
=>
{
userName
.
value
=
""
;
currentPage
.
value
=
1
;
// 处理树节点点击事件
const
handleNodeClick
=
(
data
,
node
,
element
)
=>
{
selectedNode
.
value
=
data
;
handleUserData
();
};
// 树形数据
const
handle
TreeData
=
()
=>
{
const
load
TreeData
=
()
=>
{
loading
.
value
=
true
;
proxy
.
$post
({
url
:
"/api/user/depart/treeDepart"
,
...
...
@@ -369,8 +193,7 @@ const handleTreeData = () => {
pageSize
:
pageSize
.
value
,
},
callback
:
(
data
)
=>
{
treeData
.
value
=
convertToTreeData
(
data
,
"id"
);
originTreeData
.
value
=
convertToTreeData
(
data
,
"value"
);
treeData
.
value
=
data
;
selectedNode
.
value
=
data
[
0
].
id
;
loading
.
value
=
false
;
},
...
...
@@ -380,6 +203,8 @@ const handleTreeData = () => {
},
});
};
// 人员信息
const
handleUserData
=
()
=>
{
userLoading
.
value
=
true
;
...
...
@@ -388,8 +213,8 @@ const handleUserData = () => {
data
:
{
page
:
currentPage
.
value
,
pageSize
:
pageSize
.
value
,
departId
:
currentID
.
value
,
name
:
userName
.
valu
e
,
departId
:
selectedNode
.
value
.
id
,
name
:
searchForm
.
value
.
nam
e
,
},
callback
:
(
data
)
=>
{
tableData
.
value
=
data
.
rows
.
map
((
item
)
=>
{
...
...
@@ -407,9 +232,71 @@ const handleUserData = () => {
},
});
};
// 表格数据
const
tableData
=
ref
([]);
const
total
=
ref
(
0
);
const
currentPage
=
ref
(
1
);
const
pageSize
=
ref
(
10
);
const
searchForm
=
ref
({});
// 表格列配置
const
tableColumns
=
[
{
prop
:
"name"
,
label
:
"用户姓名"
,
minWidth
:
100
,
showOverflowTooltip
:
true
,
},
{
prop
:
"departs"
,
label
:
"所属部门"
,
minWidth
:
80
,
showOverflowTooltip
:
true
,
},
{
prop
:
"positions"
,
label
:
"岗位"
,
minWidth
:
100
,
showOverflowTooltip
:
true
,
},
{
prop
:
"roles"
,
label
:
"角色"
,
minWidth
:
100
,
showOverflowTooltip
:
true
,
},
{
prop
:
"mobile"
,
label
:
"手机号码"
,
minWidth
:
100
,
},
{
prop
:
"enable"
,
label
:
"状态"
,
width
:
100
,
slot
:
"enable"
,
align
:
"center"
,
},
];
const
handleSearch
=
()
=>
{
currentPage
.
value
=
1
;
handleUserData
();
};
const
handleSizeChange
=
(
size
)
=>
{
pageSize
.
value
=
size
;
currentPage
.
value
=
1
;
handleUserData
();
};
const
handleCurrentPageChange
=
(
page
)
=>
{
currentPage
.
value
=
page
;
handleUserData
();
};
onMounted
(()
=>
{
handle
TreeData
();
load
TreeData
();
});
</
script
>
...
...
@@ -427,36 +314,18 @@ onMounted(() => {
padding: 20px;
margin-right: 20px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
width: 240px;
overflow: auto;
}
.origin-title {
display: flex;
justify-content: space-between;
margin-bottom: 20px;
span {
color: #2561ef;
cursor: pointer;
}
}
.search-contain {
width: 270px;
display: flex;
justify-content: space-between;
.el-input {
width: 255px;
}
flex-direction: column;
}
.filterRow {
display: inline-block;
cursor: pointer;
.handle-btn{
display: flex;
justify-content: end;
.icon-gedian {
color: rgba(37, 97, 239, 1);
font-size: 20px;
}
justify-content: flex-end;
}
.tree-content {
flex: 1;
height: 0;
overflow: auto;
margin-top: 20px;
position: relative;
.el-tree {
...
...
@@ -485,15 +354,52 @@ onMounted(() => {
}
}
}
.custom-tree-node {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding-right: 8px;
.node-name{
flex: 1;
width: 0;
-webkit-background-clip: text;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
.
table-container
{
.
user-content
{
flex: 1;
width: 0;
background: rgba(255, 255, 255, 0.9);
border-radius: 8px;
padding: 20px;
padding: 20px
12px
;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
display: flex;
flex-direction: column;
.search-container{
padding: 0 20px;
}
.common-table{
flex: 1;
height: 0;
display: flex;
flex-direction: column;
.table-container{
flex: 1;
height: 0;
display: flex;
flex-direction: column;
.el-table{
flex: 1;
height: 0;
}
}
}
}
}
.el-input__wrapper {
...
...
@@ -508,17 +414,9 @@ onMounted(() => {
}
:deep(.el-tree-node.is-current > .el-tree-node__content) {
background-color:
rgba(37, 97, 239, 1)
;
color: #
f
ff;
background-color:
#ecf5ff
;
color: #
409e
ff;
height: 40px;
border-radius: 3px;
.el-tree-node__label {
color: white !important;
}
.el-icon {
color: white !important;
}
}
</
style
>
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment