Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
E
EMS
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
hejie
EMS
Commits
a3402cdf
提交
a3402cdf
authored
4月 24, 2025
作者:
hejie
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat: 用户管理
上级
49ff1dae
全部展开
隐藏空白字符变更
内嵌
并排
正在显示
12 个修改的文件
包含
811 行增加
和
21 行删除
+811
-21
system.ts
src/api/system.ts
+12
-5
user.ts
src/api/user.ts
+7
-1
index.vue
src/views/systems/user/form/index.vue
+176
-0
role.vue
src/views/systems/user/form/role.vue
+53
-0
index.vue
src/views/systems/user/index.vue
+266
-15
expand.svg
src/views/systems/user/svg/expand.svg
+2
-0
unexpand.svg
src/views/systems/user/svg/unexpand.svg
+2
-0
tree.vue
src/views/systems/user/tree.vue
+211
-0
hook.tsx
src/views/systems/user/utils/hook.tsx
+0
-0
reset.css
src/views/systems/user/utils/reset.css
+5
-0
rule.ts
src/views/systems/user/utils/rule.ts
+39
-0
types.ts
src/views/systems/user/utils/types.ts
+38
-0
没有找到文件。
src/api/system.ts
浏览文件 @
a3402cdf
...
@@ -9,19 +9,22 @@ type ResultTable = {
...
@@ -9,19 +9,22 @@ type ResultTable = {
success
:
boolean
;
success
:
boolean
;
data
?:
{
data
?:
{
/** 列表数据 */
/** 列表数据 */
list
:
Array
<
any
>
;
list
?
:
Array
<
any
>
;
/** 总条目数 */
/** 总条目数 */
total
?:
number
;
total
?:
number
;
/** 每页显示条目个数 */
/** 每页显示条目个数 */
pageSize
?:
number
;
pageSize
?:
number
;
/** 当前页数 */
/** 当前页数 */
currentPage
?:
number
;
currentPage
?:
number
;
records
?:
Array
<
any
>
;
};
};
};
};
/** 获取系统管理-用户管理列表 */
/** 获取系统管理-用户管理列表 */
export
const
getUserList
=
(
data
?:
object
)
=>
{
export
const
getUserList
=
(
data
?:
object
)
=>
{
return
http
.
request
<
ResultTable
>
(
"post"
,
"/user"
,
{
data
});
return
http
.
request
<
ResultTable
>
(
"post"
,
"/api/user/find-user-list-by-page"
,
{
data
});
};
};
/** 系统管理-用户管理-获取所有角色列表 */
/** 系统管理-用户管理-获取所有角色列表 */
...
@@ -53,9 +56,13 @@ export const addMenu = (data?: object) => {
...
@@ -53,9 +56,13 @@ export const addMenu = (data?: object) => {
/** 获取系统管理-部门管理列表 */
/** 获取系统管理-部门管理列表 */
export
const
getDeptList
=
(
data
?:
object
)
=>
{
export
const
getDeptList
=
(
data
?:
object
)
=>
{
return
http
.
request
<
Result
>
(
"post"
,
"/api/depart/get-depart-list-by-page"
,
{
return
http
.
request
<
ResultTable
>
(
data
"post"
,
});
"/api/depart/get-depart-list-by-page"
,
{
data
}
);
};
};
/** 新增部门-部门管理列表 */
/** 新增部门-部门管理列表 */
...
...
src/api/user.ts
浏览文件 @
a3402cdf
...
@@ -54,7 +54,8 @@ export type UserInfo = {
...
@@ -54,7 +54,8 @@ export type UserInfo = {
export
type
UserInfoResult
=
{
export
type
UserInfoResult
=
{
success
:
boolean
;
success
:
boolean
;
data
:
UserInfo
;
data
?:
UserInfo
;
code
?:
number
;
};
};
type
ResultTable
=
{
type
ResultTable
=
{
...
@@ -90,3 +91,8 @@ export const getMine = () => {
...
@@ -90,3 +91,8 @@ export const getMine = () => {
export
const
getMineLogs
=
(
data
?:
object
)
=>
{
export
const
getMineLogs
=
(
data
?:
object
)
=>
{
return
http
.
request
<
ResultTable
>
(
"get"
,
"/mine-logs"
,
{
data
});
return
http
.
request
<
ResultTable
>
(
"get"
,
"/mine-logs"
,
{
data
});
};
};
/** 系统管理-用户管理-新增用户 */
export
const
addUser
=
(
data
?:
object
)
=>
{
return
http
.
request
<
UserInfoResult
>
(
"post"
,
"/api/user/add-user"
,
{
data
});
};
src/views/systems/user/form/index.vue
0 → 100644
浏览文件 @
a3402cdf
<
script
setup
lang=
"ts"
>
import
{
ref
}
from
"vue"
;
import
ReCol
from
"@/components/ReCol"
;
import
{
formRules
}
from
"../utils/rule"
;
import
{
FormProps
}
from
"../utils/types"
;
import
{
usePublicHooks
}
from
"../../hooks"
;
const
props
=
withDefaults
(
defineProps
<
FormProps
>
(),
{
formInline
:
()
=>
({
title
:
"新增"
,
higherDeptOptions
:
[],
parentId
:
0
,
nickname
:
""
,
username
:
""
,
password
:
""
,
phone
:
""
,
email
:
""
,
sex
:
""
,
status
:
1
,
remark
:
""
})
});
const
sexOptions
=
[
{
value
:
0
,
label
:
"男"
},
{
value
:
1
,
label
:
"女"
}
];
const
ruleFormRef
=
ref
();
const
{
switchStyle
}
=
usePublicHooks
();
const
newFormInline
=
ref
(
props
.
formInline
);
function
getRef
()
{
return
ruleFormRef
.
value
;
}
defineExpose
({
getRef
});
</
script
>
<
template
>
<el-form
ref=
"ruleFormRef"
:model=
"newFormInline"
:rules=
"formRules"
label-width=
"82px"
>
<el-row
:gutter=
"30"
>
<re-col
:value=
"12"
:xs=
"24"
:sm=
"24"
>
<el-form-item
label=
"用户昵称"
prop=
"nickname"
>
<el-input
v-model=
"newFormInline.nickname"
clearable
placeholder=
"请输入用户昵称"
/>
</el-form-item>
</re-col>
<re-col
:value=
"12"
:xs=
"24"
:sm=
"24"
>
<el-form-item
label=
"用户名称"
prop=
"username"
>
<el-input
v-model=
"newFormInline.username"
clearable
placeholder=
"请输入用户名称"
/>
</el-form-item>
</re-col>
<re-col
v-if=
"newFormInline.title === '新增'"
:value=
"12"
:xs=
"24"
:sm=
"24"
>
<el-form-item
label=
"用户密码"
prop=
"password"
>
<el-input
v-model=
"newFormInline.password"
clearable
placeholder=
"请输入用户密码"
/>
</el-form-item>
</re-col>
<re-col
:value=
"12"
:xs=
"24"
:sm=
"24"
>
<el-form-item
label=
"手机号"
prop=
"phone"
>
<el-input
v-model=
"newFormInline.phone"
clearable
placeholder=
"请输入手机号"
/>
</el-form-item>
</re-col>
<re-col
:value=
"12"
:xs=
"24"
:sm=
"24"
>
<el-form-item
label=
"邮箱"
prop=
"email"
>
<el-input
v-model=
"newFormInline.email"
clearable
placeholder=
"请输入邮箱"
/>
</el-form-item>
</re-col>
<re-col
:value=
"12"
:xs=
"24"
:sm=
"24"
>
<el-form-item
label=
"用户性别"
>
<el-select
v-model=
"newFormInline.sex"
placeholder=
"请选择用户性别"
class=
"w-full"
clearable
>
<el-option
v-for=
"(item, index) in sexOptions"
:key=
"index"
:label=
"item.label"
:value=
"item.value"
/>
</el-select>
</el-form-item>
</re-col>
<re-col
:value=
"12"
:xs=
"24"
:sm=
"24"
>
<el-form-item
label=
"归属部门"
>
<el-cascader
v-model=
"newFormInline.parentId"
class=
"w-full"
:options=
"newFormInline.higherDeptOptions"
:props=
"
{
value: 'id',
label: 'name',
emitPath: false,
checkStrictly: true
}"
clearable
filterable
placeholder="请选择归属部门"
>
<template
#
default=
"
{ node, data }">
<span>
{{
data
.
name
}}
</span>
<span
v-if=
"!node.isLeaf"
>
(
{{
data
.
children
.
length
}}
)
</span>
</
template
>
</el-cascader>
</el-form-item>
</re-col>
<re-col
v-if=
"newFormInline.title === '新增'"
:value=
"12"
:xs=
"24"
:sm=
"24"
>
<el-form-item
label=
"用户状态"
>
<el-switch
v-model=
"newFormInline.status"
inline-prompt
:active-value=
"1"
:inactive-value=
"0"
active-text=
"启用"
inactive-text=
"停用"
:style=
"switchStyle"
/>
</el-form-item>
</re-col>
<re-col>
<el-form-item
label=
"备注"
>
<el-input
v-model=
"newFormInline.remark"
placeholder=
"请输入备注信息"
type=
"textarea"
/>
</el-form-item>
</re-col>
</el-row>
</el-form>
</template>
src/views/systems/user/form/role.vue
0 → 100644
浏览文件 @
a3402cdf
<
script
setup
lang=
"ts"
>
import
{
ref
}
from
"vue"
;
import
ReCol
from
"@/components/ReCol"
;
import
{
RoleFormProps
}
from
"../utils/types"
;
const
props
=
withDefaults
(
defineProps
<
RoleFormProps
>
(),
{
formInline
:
()
=>
({
username
:
""
,
nickname
:
""
,
roleOptions
:
[],
ids
:
[]
})
});
const
newFormInline
=
ref
(
props
.
formInline
);
</
script
>
<
template
>
<el-form
:model=
"newFormInline"
>
<el-row
:gutter=
"30"
>
<!--
<re-col>
<el-form-item
label=
"用户名称"
prop=
"username"
>
<el-input
disabled
v-model=
"newFormInline.username"
/>
</el-form-item>
</re-col>
-->
<re-col>
<el-form-item
label=
"用户昵称"
prop=
"nickname"
>
<el-input
v-model=
"newFormInline.nickname"
disabled
/>
</el-form-item>
</re-col>
<re-col>
<el-form-item
label=
"角色列表"
prop=
"ids"
>
<el-select
v-model=
"newFormInline.ids"
placeholder=
"请选择"
class=
"w-full"
clearable
multiple
>
<el-option
v-for=
"(item, index) in newFormInline.roleOptions"
:key=
"index"
:value=
"item.id"
:label=
"item.name"
>
{{
item
.
name
}}
</el-option>
</el-select>
</el-form-item>
</re-col>
</el-row>
</el-form>
</
template
>
src/views/systems/user/index.vue
浏览文件 @
a3402cdf
<
script
setup
lang=
"ts"
>
import
{
ref
}
from
"vue"
;
import
tree
from
"./tree.vue"
;
import
{
useUser
}
from
"./utils/hook"
;
import
{
PureTableBar
}
from
"@/components/RePureTableBar"
;
import
{
useRenderIcon
}
from
"@/components/ReIcon/src/hooks"
;
import
Upload
from
"~icons/ri/upload-line"
;
import
Role
from
"~icons/ri/admin-line"
;
import
Password
from
"~icons/ri/lock-password-line"
;
import
More
from
"~icons/ep/more-filled"
;
import
Delete
from
"~icons/ep/delete"
;
import
EditPen
from
"~icons/ep/edit-pen"
;
import
Refresh
from
"~icons/ep/refresh"
;
import
AddFill
from
"~icons/ri/add-circle-line"
;
defineOptions
({
name
:
"SystemUser"
});
const
treeRef
=
ref
();
const
formRef
=
ref
();
const
tableRef
=
ref
();
const
{
form
,
loading
,
columns
,
dataList
,
treeData
,
treeLoading
,
selectedNum
,
pagination
,
buttonClass
,
deviceDetection
,
onSearch
,
resetForm
,
onbatchDel
,
openDialog
,
onTreeSelect
,
handleUpdate
,
handleDelete
,
handleUpload
,
handleReset
,
handleRole
,
handleSizeChange
,
onSelectionCancel
,
handleCurrentChange
,
handleSelectionChange
}
=
useUser
(
tableRef
,
treeRef
);
</
script
>
<
template
>
<
template
>
<div
class=
"systems"
>
<div
:class=
"['flex', 'justify-between', deviceDetection() && 'flex-wrap']"
>
<h2>
Systems
</h2>
<tree
<slot
/>
ref=
"treeRef"
:class=
"['mr-2', deviceDetection() ? 'w-full' : 'min-w-[200px]']"
:treeData=
"treeData"
:treeLoading=
"treeLoading"
@
tree-select=
"onTreeSelect"
/>
<div
:class=
"[deviceDetection() ? ['w-full', 'mt-2'] : 'w-[calc(100%-200px)]']"
>
<el-form
ref=
"formRef"
:inline=
"true"
:model=
"form"
class=
"search-form bg-bg_color w-full pl-8 pt-[12px] overflow-auto"
>
<el-form-item
label=
"用户名称:"
prop=
"username"
>
<el-input
v-model=
"form.username"
placeholder=
"请输入用户名称"
clearable
class=
"w-[180px]!"
/>
</el-form-item>
<el-form-item
label=
"手机号码:"
prop=
"phone"
>
<el-input
v-model=
"form.phone"
placeholder=
"请输入手机号码"
clearable
class=
"w-[180px]!"
/>
</el-form-item>
<el-form-item
label=
"状态:"
prop=
"status"
>
<el-select
v-model=
"form.status"
placeholder=
"请选择"
clearable
class=
"w-[180px]!"
>
<el-option
label=
"已开启"
value=
"1"
/>
<el-option
label=
"已关闭"
value=
"0"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button
type=
"primary"
:icon=
"useRenderIcon('ri/search-line')"
:loading=
"loading"
@
click=
"onSearch"
>
搜索
</el-button>
<el-button
:icon=
"useRenderIcon(Refresh)"
@
click=
"resetForm(formRef)"
>
重置
</el-button>
</el-form-item>
</el-form>
<PureTableBar
title=
"用户管理(仅演示,操作后不生效)"
:columns=
"columns"
@
refresh=
"onSearch"
>
<template
#
buttons
>
<el-button
type=
"primary"
:icon=
"useRenderIcon(AddFill)"
@
click=
"openDialog()"
>
新增用户
</el-button>
</
template
>
<
template
v-slot=
"{ size, dynamicColumns }"
>
<div
v-if=
"selectedNum > 0"
v-motion-fade
class=
"bg-[var(--el-fill-color-light)] w-full h-[46px] mb-2 pl-4 flex items-center"
>
<div
class=
"flex-auto"
>
<span
style=
"font-size: var(--el-font-size-base)"
class=
"text-[rgba(42,46,54,0.5)] dark:text-[rgba(220,220,242,0.5)]"
>
已选
{{
selectedNum
}}
项
</span>
<el-button
type=
"primary"
text
@
click=
"onSelectionCancel"
>
取消选择
</el-button>
</div>
<el-popconfirm
title=
"是否确认删除?"
@
confirm=
"onbatchDel"
>
<template
#
reference
>
<el-button
type=
"danger"
text
class=
"mr-1!"
>
批量删除
</el-button>
</
template
>
</el-popconfirm>
</div>
<pure-table
ref=
"tableRef"
row-key=
"id"
adaptive
:adaptiveConfig=
"{ offsetBottom: 108 }"
align-whole=
"center"
table-layout=
"auto"
:loading=
"loading"
:size=
"size"
:data=
"dataList"
:columns=
"dynamicColumns"
:pagination=
"{ ...pagination, size }"
:header-cell-style=
"{
background: 'var(--el-fill-color-light)',
color: 'var(--el-text-color-primary)'
}"
@
selection-change=
"handleSelectionChange"
@
page-size-change=
"handleSizeChange"
@
page-current-change=
"handleCurrentChange"
>
<
template
#
operation=
"{ row }"
>
<el-button
class=
"reset-margin"
link
type=
"primary"
:size=
"size"
:icon=
"useRenderIcon(EditPen)"
@
click=
"openDialog('修改', row)"
>
修改
</el-button>
<el-popconfirm
:title=
"`是否确认删除用户编号为$
{row.id}的这条数据`"
@confirm="handleDelete(row)"
>
<template
#
reference
>
<el-button
class=
"reset-margin"
link
type=
"primary"
:size=
"size"
:icon=
"useRenderIcon(Delete)"
>
删除
</el-button>
</
template
>
</el-popconfirm>
<el-dropdown>
<el-button
class=
"ml-3! mt-[2px]!"
link
type=
"primary"
:size=
"size"
:icon=
"useRenderIcon(More)"
@
click=
"handleUpdate(row)"
/>
<
template
#
dropdown
>
<el-dropdown-menu>
<el-dropdown-item>
<el-button
:class=
"buttonClass"
link
type=
"primary"
:size=
"size"
:icon=
"useRenderIcon(Upload)"
@
click=
"handleUpload(row)"
>
上传头像
</el-button>
</el-dropdown-item>
<el-dropdown-item>
<el-button
:class=
"buttonClass"
link
type=
"primary"
:size=
"size"
:icon=
"useRenderIcon(Password)"
@
click=
"handleReset(row)"
>
重置密码
</el-button>
</el-dropdown-item>
<el-dropdown-item>
<el-button
:class=
"buttonClass"
link
type=
"primary"
:size=
"size"
:icon=
"useRenderIcon(Role)"
@
click=
"handleRole(row)"
>
分配角色
</el-button>
</el-dropdown-item>
</el-dropdown-menu>
</
template
>
</el-dropdown>
</template>
</pure-table>
</template>
</PureTableBar>
</div>
</div>
</div>
</template>
</template>
<
script
setup
lang=
"ts"
>
<
style
lang=
"scss"
scoped
>
// 组件逻辑部分
:deep
(
.el-dropdown-menu__item
i
)
{
import
{
ref
}
from
"vue"
;
margin
:
0
;
}
const
count
=
ref
(
0
);
:deep
(
.el-button
:focus-visible
)
{
outline
:
none
;
}
const
increment
=
()
=>
{
.main-content
{
count
.
value
++
;
margin
:
24px
24px
0
!
important
;
};
}
</
script
>
<
style
scoped
lang=
"scss"
>
.search-form
{
.systems
{
:deep
(
.el-form-item
)
{
padding
:
20
px
;
margin-bottom
:
12
px
;
border
:
1px
solid
#ccc
;
}
}
}
</
style
>
</
style
>
src/views/systems/user/svg/expand.svg
0 → 100644
浏览文件 @
a3402cdf
<svg
width=
"32"
height=
"32"
viewBox=
"0 0 24 24"
><path
fill=
"currentColor"
d=
"M22 4V2H2v2h9v14.17l-5.5-5.5-1.42 1.41L12 22l7.92-7.92-1.42-1.41-5.5 5.5V4z"
/></svg>
\ No newline at end of file
src/views/systems/user/svg/unexpand.svg
0 → 100644
浏览文件 @
a3402cdf
<svg
width=
"32"
height=
"32"
viewBox=
"0 0 24 24"
><path
fill=
"currentColor"
d=
"M4 2H2v20h2v-9h14.17l-5.5 5.5 1.41 1.42L22 12l-7.92-7.92-1.41 1.42 5.5 5.5H4z"
/></svg>
\ No newline at end of file
src/views/systems/user/tree.vue
0 → 100644
浏览文件 @
a3402cdf
<
script
setup
lang=
"ts"
>
import
{
useRenderIcon
}
from
"@/components/ReIcon/src/hooks"
;
import
{
ref
,
computed
,
watch
,
getCurrentInstance
}
from
"vue"
;
import
Dept
from
"~icons/ri/git-branch-line"
;
// import Reset from "~icons/ri/restart-line";
import
More2Fill
from
"~icons/ri/more-2-fill?width=18&height=18"
;
import
OfficeBuilding
from
"~icons/ep/office-building"
;
import
LocationCompany
from
"~icons/ep/add-location"
;
import
ExpandIcon
from
"./svg/expand.svg?component"
;
import
UnExpandIcon
from
"./svg/unexpand.svg?component"
;
interface
Tree
{
id
:
number
;
name
:
string
;
highlight
?:
boolean
;
children
?:
Tree
[];
}
defineProps
({
treeLoading
:
Boolean
,
treeData
:
Array
});
const
emit
=
defineEmits
([
"tree-select"
]);
const
treeRef
=
ref
();
const
isExpand
=
ref
(
true
);
const
searchValue
=
ref
(
""
);
const
highlightMap
=
ref
({});
const
{
proxy
}
=
getCurrentInstance
();
const
defaultProps
=
{
children
:
"children"
,
label
:
"name"
};
const
buttonClass
=
computed
(()
=>
{
return
[
"h-[20px]!"
,
"text-sm!"
,
"reset-margin"
,
"text-(--el-text-color-regular)!"
,
"dark:text-white!"
,
"dark:hover:text-primary!"
];
});
const
filterNode
=
(
value
:
string
,
data
:
Tree
)
=>
{
if
(
!
value
)
return
true
;
return
data
.
name
.
includes
(
value
);
};
function
nodeClick
(
value
)
{
const
nodeId
=
value
.
$treeNodeId
;
highlightMap
.
value
[
nodeId
]
=
highlightMap
.
value
[
nodeId
]?.
highlight
?
Object
.
assign
({
id
:
nodeId
},
highlightMap
.
value
[
nodeId
],
{
highlight
:
false
})
:
Object
.
assign
({
id
:
nodeId
},
highlightMap
.
value
[
nodeId
],
{
highlight
:
true
});
Object
.
values
(
highlightMap
.
value
).
forEach
((
v
:
Tree
)
=>
{
if
(
v
.
id
!==
nodeId
)
{
v
.
highlight
=
false
;
}
});
emit
(
"tree-select"
,
highlightMap
.
value
[
nodeId
]?.
highlight
?
Object
.
assign
({
...
value
,
selected
:
true
})
:
Object
.
assign
({
...
value
,
selected
:
false
})
);
}
function
toggleRowExpansionAll
(
status
)
{
isExpand
.
value
=
status
;
const
nodes
=
(
proxy
.
$refs
[
"treeRef"
]
as
any
).
store
.
_getAllNodes
();
for
(
let
i
=
0
;
i
<
nodes
.
length
;
i
++
)
{
nodes
[
i
].
expanded
=
status
;
}
}
/** 重置部门树状态(选中状态、搜索框值、树初始化) */
function
onTreeReset
()
{
highlightMap
.
value
=
{};
searchValue
.
value
=
""
;
toggleRowExpansionAll
(
true
);
}
watch
(
searchValue
,
val
=>
{
treeRef
.
value
!
.
filter
(
val
);
});
defineExpose
({
onTreeReset
});
</
script
>
<
template
>
<div
v-loading=
"treeLoading"
class=
"h-full bg-bg_color overflow-hidden relative"
:style=
"
{ minHeight: `calc(100vh - 141px)` }"
>
<div
class=
"flex items-center h-[34px]"
>
<el-input
v-model=
"searchValue"
class=
"ml-2"
size=
"small"
placeholder=
"请输入部门名称"
clearable
>
<template
#
suffix
>
<el-icon
class=
"el-input__icon"
>
<IconifyIconOffline
v-show=
"searchValue.length === 0"
icon=
"ri/search-line"
/>
</el-icon>
</
template
>
</el-input>
<el-dropdown
:hide-on-click=
"false"
>
<More2Fill
class=
"w-[28px] cursor-pointer outline-hidden"
/>
<
template
#
dropdown
>
<el-dropdown-menu>
<el-dropdown-item>
<el-button
:class=
"buttonClass"
link
type=
"primary"
:icon=
"useRenderIcon(isExpand ? ExpandIcon : UnExpandIcon)"
@
click=
"toggleRowExpansionAll(isExpand ? false : true)"
>
{{
isExpand
?
"折叠全部"
:
"展开全部"
}}
</el-button>
</el-dropdown-item>
<!--
<el-dropdown-item>
<el-button
:class=
"buttonClass"
link
type=
"primary"
:icon=
"useRenderIcon(Reset)"
@
click=
"onTreeReset"
>
重置状态
</el-button>
</el-dropdown-item>
-->
</el-dropdown-menu>
</
template
>
</el-dropdown>
</div>
<el-divider
/>
<el-scrollbar
height=
"calc(90vh - 88px)"
>
<el-tree
ref=
"treeRef"
:data=
"treeData"
node-key=
"id"
size=
"small"
:props=
"defaultProps"
default-expand-all
:expand-on-click-node=
"false"
:filter-node-method=
"filterNode"
@
node-click=
"nodeClick"
>
<
template
#
default=
"{ node, data }"
>
<div
:class=
"[
'rounded-sm',
'flex',
'items-center',
'select-none',
'hover:text-primary',
searchValue.trim().length > 0 &&
node.label.includes(searchValue) &&
'text-red-500',
highlightMap[node.id]?.highlight ? 'dark:text-primary' : ''
]"
:style=
"
{
color: highlightMap[node.id]?.highlight
? 'var(--el-color-primary)'
: '',
background: highlightMap[node.id]?.highlight
? 'var(--el-color-primary-light-7)'
: 'transparent'
}"
>
<IconifyIconOffline
:icon=
"
data.type === 1
? OfficeBuilding
: data.type === 2
? LocationCompany
: Dept
"
/>
<span
class=
"w-[120px]! truncate!"
:title=
"node.label"
>
{{
node
.
label
}}
</span>
</div>
</
template
>
</el-tree>
</el-scrollbar>
</div>
</template>
<
style
lang=
"scss"
scoped
>
:deep
(
.el-divider
)
{
margin
:
0
;
}
:deep
(
.el-tree
)
{
--el-tree-node-hover-bg-color
:
transparent
;
}
</
style
>
src/views/systems/user/utils/hook.tsx
0 → 100644
浏览文件 @
a3402cdf
差异被折叠。
点击展开。
src/views/systems/user/utils/reset.css
0 → 100644
浏览文件 @
a3402cdf
/** 局部重置 ElProgress 的部分样式 */
.el-progress-bar__outer
,
.el-progress-bar__inner
{
border-radius
:
0
;
}
src/views/systems/user/utils/rule.ts
0 → 100644
浏览文件 @
a3402cdf
import
{
reactive
}
from
"vue"
;
import
type
{
FormRules
}
from
"element-plus"
;
import
{
isPhone
,
isEmail
}
from
"@pureadmin/utils"
;
/** 自定义表单规则校验 */
export
const
formRules
=
reactive
(
<
FormRules
>
{
nickname
:
[{
required
:
true
,
message
:
"用户昵称为必填项"
,
trigger
:
"blur"
}],
username
:
[{
required
:
true
,
message
:
"用户名称为必填项"
,
trigger
:
"blur"
}],
password
:
[{
required
:
true
,
message
:
"用户密码为必填项"
,
trigger
:
"blur"
}],
phone
:
[
{
validator
:
(
rule
,
value
,
callback
)
=>
{
if
(
value
===
""
)
{
callback
();
}
else
if
(
!
isPhone
(
value
))
{
callback
(
new
Error
(
"请输入正确的手机号码格式"
));
}
else
{
callback
();
}
},
trigger
:
"blur"
// trigger: "click" // 如果想在点击确定按钮时触发这个校验,trigger 设置成 click 即可
}
],
email
:
[
{
validator
:
(
rule
,
value
,
callback
)
=>
{
if
(
value
===
""
)
{
callback
();
}
else
if
(
!
isEmail
(
value
))
{
callback
(
new
Error
(
"请输入正确的邮箱格式"
));
}
else
{
callback
();
}
},
trigger
:
"blur"
}
]
});
src/views/systems/user/utils/types.ts
0 → 100644
浏览文件 @
a3402cdf
interface
FormItemProps
{
id
?:
number
;
/** 用于判断是`新增`还是`修改` */
title
:
string
;
higherDeptOptions
:
Record
<
string
,
unknown
>
[];
parentId
:
number
;
nickname
:
string
;
username
:
string
;
password
:
string
;
mobile
:
string
|
number
;
email
:
string
;
gender
:
string
|
number
;
status
:
number
;
dept
?:
{
id
?:
number
;
name
?:
string
;
};
remark
:
string
;
name
?:
string
;
deptId
?:
number
;
}
interface
FormProps
{
formInline
:
FormItemProps
;
}
interface
RoleFormItemProps
{
username
:
string
;
nickname
:
string
;
/** 角色列表 */
roleOptions
:
any
[];
/** 选中的角色列表 */
ids
:
Record
<
number
,
unknown
>
[];
}
interface
RoleFormProps
{
formInline
:
RoleFormItemProps
;
}
export
type
{
FormItemProps
,
FormProps
,
RoleFormItemProps
,
RoleFormProps
};
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论