@@ -1,166 +1,111 @@
< template >
< el-dialog
v-model = "visible"
title = "选择用户"
width = "900px"
append -to -body
@close ="handleClose"
>
< div class = "user-selector" >
< el-tabs v-model = "activeTab" @tab-click="handleTabClick" >
< ! - - 选择用户 - - >
< el-tab-pane label = "选择用户" name = "selectUser" >
< div class = "user-list-container" >
<!-- 搜索筛选区域 -- >
< div class = "filter-section" >
< el-form :inline = "true" :model = "searchParams" class = "search-form" >
< el-form-item label = "关键词" >
< el-input
v-model = "searchParams.key"
placeholder = "搜索用户名或ID"
clearable
@keyup.enter ="handleSearch"
style = "width: 200px"
>
< template # prefix >
< el-icon > < Search / > < / el-icon >
< / template >
< / el-input >
< / el-form-item >
< el-form-item label = "用户状态" >
< el-select
v-model = "searchParams.status"
placeholder = "全部状态"
clearable
style = "width: 120px"
>
< el-option label = "正常" value = "1" / >
< el-option label = "禁用" value = "0" / >
< / el-select >
< / el-form-item >
< el-form-item >
< el-button type = "primary" @click ="handleSearch" :icon = "Search" >
搜索
< / el-button >
< el-button @click ="handleReset" :icon = "Refresh" >
重置
< / el-button >
< el-button type = "success" @click ="switchToAdd" :icon = "Plus" >
添加新用户
< / el-button >
< / el-form-item >
< / el-form >
< / div >
< el-dialog v-model = "visible" title="选择用户" width="860px" append-to-body @close="handleClose" class="user-selector-dialog" >
< div class = "uls-root" >
< el-tabs v-model = "activeTab" @tab-click="handleTabClick" class="uls-tabs" >
< ! - - = = = = = = 选择用户 = = = = = = - - >
< el-tab-pane name = "selectUser" >
< template # label >
< span class = "tab-lbl" >
< svg viewBox = "0 0 24 24" width = "16" height = "16" > < path d = "M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z" fill = "currentColor" / > < / svg >
选择用户
< / span >
< / template >
<!-- 用户列表表格 -- >
< el-table
v-loading = "loading"
:data = "u serList"
highlight -current -row
@ current -change = " handleCurrentChange "
style = "width: 100%"
:height = "350"
:row-class-name = "tableRowClassName"
<!-- 搜索栏 -- >
< div class = "uls-search" >
< el-input v-model = "searchParams.key" placeholder="搜索用户名 / 邮箱 / ID" clearable @keyup.enter="handleSearch" class="uls-search-input" :prefix-icon="Search" / >
< el-select v-model = "searchParams.is_admin" placeholder="全部身份" clearable style="width: 120px" @change="handleSearch" >
< el -option label = "管理员" :value = "true" / >
< el-option label = "普通用户" :value = "false" / >
< / el-select >
< el-button type = "primary" @click ="handleSearch" :icon = "Search" circle / >
< el-button @click ="handleReset" :icon = "Refresh" circle / >
< / div >
<!-- 已选提示 -- >
< transition name = "fade" >
< div class = "uls-selected-bar" v-if = "selectedUser" >
< div class = "uls-sel-left" >
< svg viewBox = "0 0 24 24" width = "16" height = "16" > < path d = "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" fill = "#67c23a" / > < / svg >
< span > 已选择 : < / span >
< el-avatar :size = "24" :src = "selectedUser.cover" class = "sel-avatar" > { { selectedUser . user _name ? . charAt ( 0 ) ? . toUpperCase ( ) || 'U' } } < / el-avatar >
< b > { { selectedUser . user _name } } < / b >
< span class = "sel-id" > # { { selectedUser . user _id } } < / span >
< / div >
< el-button size = "small" link type = "danger" @click ="selectedUser = null" > 取消选择 < / el -button >
< / div >
< / transition >
<!-- 用户卡片列表 -- >
< div class = "uls-grid" v-loading = "loading" >
< div
v-for = "user in userList" :key="user.user_id"
class = "uls-card" : class = "{ active: selectedUser?.user_id === user.user_id }"
@click ="handleCurrentChange(user)"
>
< el-table-column type = "index " label = "序号" width = "60" align = "center" / >
< el-table-column prop = "user_id " label = "用户ID " width = "100 " align = "center" / >
< el-table-column prop = "user_name" label = "用户名" min -width = " 120 " >
< template # default = "{ row }" >
< div class = "user-info-cell " >
< el-avatar :size = "32" :src = "row.cover ">
< el-icon > < User / > < / el-icon >
< / el-avatar >
< span class = "user-name" > { { row . user _name } } < / span >
< / div >
< / template >
< / el-table-column >
< el-table-column prop = "email" label = "邮箱" min -width = " 180 " show -overflow -tooltip / >
< el-table-column prop = "phone" label = "手机号" width = "130" show -overflow -tooltip / >
<!-- < el-table-column prop = "status" label = "状态" width = "80" align = "center" >
< template # default = "{ row }" >
< el-tag : type = "row.status === 1 ? 'success' : 'danger'" size = "small" >
{ { row . status === 1 ? '正常' : '禁用' } }
< / el-tag >
< / template >
< / el-table-column > -- >
< el-table-column prop = "created_at" label = "注册时间" width = "160" show -overflow -tooltip / >
< / el-table >
<!-- 分页 -- >
< div class = "pagination-container" v-if = "total > 0" >
< el -pagination
v -model :current-page = "searchParams.page"
v -model :page-size = "searchParams.count"
: page -sizes = " [ 10 , 20 , 50 , 100 ] "
:total = "total"
layout = "total, sizes, prev, pager, next, jumper"
background
@ size -change = " handleSizeChange "
@ current -change = " handlePageChange "
/ >
< div class = "uls-card-check " v-if = "selectedUser?.user_id === user.user_id" >
< svg viewBox = "0 0 24 24 " width = "16 " height = "16" > < path d = "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z " fill = "#fff" / > < / svg >
< / div >
< el-avatar :size = "42" :src = "user.cover" class = "uls-avatar" > { { user . user _name ? . charAt ( 0 ) ? . toUpperCase ( ) || 'U' } } < / el-avatar >
< div class = "uls-card-body " >
< div class = "uls-card-name ">
{ { user . user _name } }
< el-tag v-if = "user.is_admin" type="warning" size="small" effect="dark" round class="admin-tag" > 管理员 < / el -tag >
< / div >
< div class = "uls-card-meta" >
< span class = "meta-id" > # { { user . user _id } } < / span >
< span v-if = "user.email" class="meta-email" > {{ user.email }} < / span >
< span v-if = "user.phone" class="meta-phone" > {{ user.phone }} < / span >
< / div >
< / div >
< / div >
< el-empty v-if = "userList.length === 0 && !loading" description="暂无用户数据" / >
< / div >
< el -empty v-if = "userList.length === 0 && !loading" description="暂无用户数据" :image-size="80" / >
<!-- 分页 -- >
< div class = "uls-pagination" v-if = "total > 0" >
< el -pagination
v -model :current-page = "searchParams.page"
v -model :page-size = "searchParams.count"
: page -sizes = " [ 12 , 24 , 48 ] "
:total = "total"
layout = "total, sizes, prev, pager, next"
background small
@ size -change = " s = > { searchParams . count = s ; searchParams . page = 1 ; fetchUserList ( ) } "
@current-change=" p => { searchParams . page = p ; fetchUserList ( ) } "
/>
</div>
</el-tab-pane>
<!-- 添加用户 -- >
< el-tab-pane label = "添加用户" name = "addUser" >
< div class = "add-user-section" >
< el-form
ref = "addFormRef"
:model = "addForm"
:rules = "addFormRules"
label -width = " 100px "
class = "add-user-form"
>
<!-- ====== 添加用户 ====== -->
<el-tab-pane name=" addUser ">
<template #label>
<span class=" tab - lbl ">
<svg viewBox=" 0 0 24 24 " width=" 16 " height=" 16 "><path d=" M15 12 c2 .21 0 4 - 1.79 4 - 4 s - 1.79 - 4 - 4 - 4 - 4 1.79 - 4 4 1.79 4 4 4 zm - 9 - 2 V7H4v3H1v2h3v3h2v - 3 h3v - 2 H6zm9 4 c - 2.67 0 - 8 1.34 - 8 4 v2h16v - 2 c0 - 2.66 - 5.33 - 4 - 8 - 4 z " fill=" currentColor "/></svg>
添加用户
</span>
</template>
<div class=" uls - add - section ">
<el-form ref=" addFormRef " :model=" addForm " :rules=" addFormRules " label-width=" 90 px " class=" uls - add - form ">
<el-form-item label=" 用户名 " prop=" user _name ">
< el-input
v-model = "addForm.user_name"
placeholder = "请输入用户名"
maxlength = "50"
show -word -limit
/ >
<el-input v-model=" addForm . user _name " placeholder=" 请输入用户名 " maxlength=" 50 " show-word-limit />
</el-form-item>
<el-form-item label=" 邮箱 " prop=" email ">
< el-input
v-model = "addForm.email"
placeholder = "请输入邮箱地址"
type = "email"
/ >
<el-input v-model=" addForm . email " placeholder=" 请输入邮箱地址 " type=" email " />
</el-form-item>
<el-form-item label=" 手机号 " prop=" phone ">
< el-input
v-model = "addForm.phone"
placeholder = "请输入手机号"
maxlength = "11"
/ >
<el-input v-model=" addForm . phone " placeholder=" 请输入手机号 ( 选填 ) " maxlength=" 11 " />
</el-form-item>
<el-form-item label=" 密码 " prop=" password ">
< el-input
v-model = "addForm.password"
placeholder = "请输入密码"
type = "password"
show -password
/ >
<el-input v-model=" addForm . password " placeholder=" 请输入密码 " type=" password " show-password />
</el-form-item>
<el-form-item label=" 确认密码 " prop=" confirmPassword ">
< el-input
v-model = "addForm.confirmPassword"
placeholder = "请再次输入密码"
type = "password"
show -password
/ >
<el-input v-model=" addForm . confirmPassword " placeholder=" 请再次输入密码 " type=" password " show-password />
</el-form-item>
<el-form-item>
< el-button type = "primary" @click ="handleAddUser" :loading = "addLoading" >
< el-icon > < Plus / > < / el-icon >
立即创建
< / el-button >
< el-button @click ="resetAddForm" >
< el -icon > < Refresh / > < / el-icon >
重置表单
< / el-button >
<el-button type=" primary " @click=" handleAddUser " :loading=" addLoading " :icon=" Plus ">立即创建</el-button>
<el-button @click=" resetAddForm " :icon=" Refresh ">重置</el-button>
</el-form-item>
</el-form>
</div>
@@ -169,16 +114,9 @@
</div>
<template #footer>
< div class = "dialog-footer" >
<div class=" uls - footer ">
<el-button @click=" handleClose ">取消</el-button>
< el-button
type = "primary"
@click ="handleConfirm"
:disabled = "!selectedUser"
v-if = "activeTab === 'selectUser'"
>
确定选择
< / el-button >
<el-button type=" primary " @click=" handleConfirm " :disabled=" ! selectedUser " v-if=" activeTab === 'selectUser' " > 确定选择 < / el-button >
< / div >
< / template >
< / el-dialog >
@@ -190,23 +128,12 @@ import { ElMessage } from 'element-plus'
import { Search , Refresh , Plus , User } from '@element-plus/icons-vue'
import { getUserList , createTask } from '@/api/admin/user'
// Props
const props = defineProps ( {
modelValue : {
type : Boolean ,
default : false
} ,
// 当前已选中的用户ID(用于回显)
currentUserId : {
type : [ String , Number ] ,
default : ''
}
modelValue : { type : Boolean , default : false } ,
currentUserId : { type : [ String , Number ] , default : '' }
} )
// Emits
const emit = defineEmits ( [ 'update:modelValue' , 'confirm' ] )
// 响应式数据
const visible = ref ( false )
const activeTab = ref ( 'selectUser' )
const loading = ref ( false )
@@ -216,352 +143,131 @@ const total = ref(0)
const selectedUser = ref ( null )
const addFormRef = ref ( null )
// 搜索参数
const searchParams = reactive ( {
key : '' ,
status : '' ,
page : 1 ,
count : 10
} )
const searchParams = reactive ( { key : '' , is _admin : undefined , page : 1 , count : 12 } )
// 添加用户表单
const addForm = reactive ( {
user _name : '' ,
email : '' ,
phone : '' ,
password : '' ,
confirmPassword : ''
} )
// 密码确认验证
const addForm = reactive ( { user _name : '' , email : '' , phone : '' , password : '' , confirmPassword : '' } )
const validateConfirmPassword = ( rule , value , callback ) => {
if ( value === ' ') {
callback ( new Error ( '请再 次输入密码' ) )
} else if ( value !== addForm . password ) {
callback ( new Error ( '两次输入密码不一致' ) )
} else {
callback ( )
}
if ( ! value ) callback ( new Error ( '请再次输入密码 ') )
else if ( value !== addForm . password ) callback ( new Error ( '两 次输入密码不一致 ' ) )
else callback ( )
}
// 添加用户表单验证规则
const addFormRules = {
user _name : [
{ required : true , message : '请输入用户名 ' , trigger : 'blur' } ,
{ min : 2 , max : 50 , message : '用户名长度在 2 到 50 个字符 ', trigger : 'blur' }
] ,
email : [
{ required : true , message : '请输入邮箱地址' , trigger : 'blur' } ,
{ type : 'email' , message : '请输入正确的邮箱地址' , trigger : 'blur' }
] ,
phone : [
{ pattern : /^1[3-9]\d{9}$/ , message : '请输入正确的手机号' , trigger : 'blur' }
] ,
password : [
{ required : true , message : '请输入密码' , trigger : 'blur' } ,
{ min : 6 , max : 20 , message : '密码长度在 6 到 20 个字符' , trigger : 'blur' }
] ,
confirmPassword : [
{ required : true , message : '请再次输入密码' , trigger : 'blur' } ,
{ validator : validateConfirmPassword , trigger : 'blur' }
]
user _name : [ { required : true , message : '请输入用户名' , trigger : 'blur' } , { min : 2 , max : 50 , message : '2-50 个字符' , trigger : 'blur' } ] ,
email : [ { required : true , message : '请输入邮箱' , trigger : 'blur' } , { type : 'email' , message : '邮箱格式不正确 ', trigger : 'blur' } ] ,
phone : [ { pattern : /^1[3-9]\d{9}$/ , message : '手机号格式不正确 ', trigger : 'blur' } ] ,
password : [ { required : true , message : '请输入密码' , trigger : 'blur' } , { min : 6 , max : 20 , message : '6-20 个字符' , trigger : 'blur' } ] ,
confirmPassword : [ { required : true , message : '请确认密码' , trigger : 'blur' } , { validator : validateConfirmPassword , trigger : 'blur' } ]
}
// 监听 modelValue 变化
watch ( ( ) => props . modelValue , ( newVal ) => {
visible . value = newVal
if ( newVal ) {
// 重置状态
activeTab . value = 'selectUser'
selectedUser . value = null
searchParams . page = 1
fetchUserList ( )
}
watch ( ( ) => props . modelValue , ( v ) => {
visible . value = v
if ( v ) { activeTab . value = 'selectUser' ; selectedUser . value = null ; searchParams . page = 1 ; fetchUserList ( ) }
} )
watch ( visible , ( v ) => emit ( 'update:modelValue' , v ) )
// 监听 visible 变化
watch ( visible , ( newVal ) => {
emit ( 'update:modelValue' , newVal )
} )
// 获取用户列表
const fetchUserList = async ( ) => {
loading . value = true
userList . value = [ ]
loading . value = true ; userList . value = [ ]
try {
const params = {
page : searchParams . page ,
count : searchParams . count ,
key : searchParams . key || ''
}
const params = { page : searchParams . page , count : searchParams . count , key : searchParams . key || '' }
if ( searchParams . is _admin !== undefined && searchParams . is _admin !== null && searchParams . is _admin !== '' ) params . is _admin = searchParams . is _admin
const res = await getUserList ( params )
if ( res . data . code === 200 ) {
userList . value = res . data . data ? . data || [ ]
total . value = res . data . data ? . all _count || 0
// 如果有当前选中的用户ID,自动选中
if ( props . currentUserId ) {
const currentUser = userList . value . find (
user => user . user _id === props . currentUserId
)
if ( currentUser ) {
selectedUser . value = currentUser
}
}
} else {
ElMessage . error ( res . data . msg || '获取用户列表失败' )
if ( props . currentUserId ) { const u = userList . value . find ( u => u . user _id === props . currentUserId ) ; if ( u ) selectedUser . value = u }
}
} catch ( error ) {
console . error ( '获取用户列表失败:' , error )
ElMessage . error ( '获取用户列表失败' )
} finally {
loading . value = false
}
} catch { ElMessage . error ( '获取用户列表失败' ) }
finally { loading . value = false }
}
// 处理标签页切换
const handleTabClick = ( tab ) => {
if ( tab . paneName === 'selectUser ' ) {
fetchUserList ( )
}
}
const handleTabClick = ( tab ) => { if ( tab . paneName === 'selectUser' ) fetchUserList ( ) }
const handleSearch = ( ) => { searchParams . page = 1 ; fetchUserList ( ) }
const handleReset = ( ) => { searchParams . key = '' ; searchParams . is _admin = undefined ; searchParams . page = 1 ; fetchUserList ( ) }
const handleCurrentChange = ( row ) => { selectedUser . value = ( selectedUser . value ? . user _id === row . user _id ) ? null : row }
const switchToAdd = ( ) => { activeTab . value = 'addUser' }
// 搜索
const handleSearch = ( ) => {
searchParams . page = 1
fetchUserList ( )
}
// 重置搜索
const handleReset = ( ) => {
searchParams . key = ''
searchParams . status = ''
searchParams . page = 1
fetchUserList ( )
}
// 分页处理
const handleSizeChange = ( size ) => {
searchParams . count = size
searchParams . page = 1
fetchUserList ( )
}
const handlePageChange = ( page ) => {
searchParams . page = page
fetchUserList ( )
}
// 切换到添加用户标签页
const switchToAdd = ( ) => {
activeTab . value = 'addUser'
}
// 选择用户
const handleCurrentChange = ( row ) => {
selectedUser . value = row
}
// 表格行样式
const tableRowClassName = ( { row } ) => {
if ( selectedUser . value && row . user _id === selectedUser . value . user _id ) {
return 'selected-row'
}
return ''
}
// 添加用户
const handleAddUser = async ( ) => {
if ( ! addFormRef . value ) return
await addFormRef . value . validate ( async ( valid ) => {
if ( ! valid ) return
addLoading . value = true
try {
const formData = new FormData ( )
formData . append ( 'user_name' , addForm . user _name )
formData . append ( 'email ' , addForm . email )
if ( addForm . phone ) {
formData . append ( 'phone' , addForm . phone )
}
formData . append ( 'password' , addForm . password )
const res = await createTask ( formData )
const fd = new FormData ( )
fd . append ( 'user_name' , addForm . user _name ) ; fd . append ( 'email' , addForm . email )
if ( addForm . phone ) fd . append ( 'phone ' , addForm . phone )
fd . append ( 'password' , addForm . password )
const res = await createTask ( fd )
if ( res . data . code === 200 ) {
ElMessage . success ( '用户创建成功' )
// 获取新创建的用户信息
const newUser = res . data . data
// 自动选择新创建的用户
if ( newUser ) {
selectedUser . value = {
user _id : newUser . user _id || newUser . id ,
user _name : newUser . user _name || addForm . user _name ,
email : newUser . email || addForm . email ,
phone : newUser . phone || addForm . phone ,
... newUser
}
// 触发确认事件并关闭弹窗
emit ( 'confirm' , selectedUser . value )
handleClose ( )
} else {
// 如果没有返回用户信息,切换到选择标签页并刷新列表
activeTab . value = 'selectUser'
searchParams . page = 1
await fetchUserList ( )
}
// 重置表单
if ( newUser ) { selectedUser . value = { user _id : newUser . user _id || newUser . id , user _name : newUser . user _name || addForm . user _name , email : newUser . email || addForm . email , phone : newUser . phone || addForm . phone , ... newUser } ; emit ( 'confirm' , selectedUser . value ) ; handleClose ( ) }
else { activeTab . value = 'selectUser' ; searchParams . page = 1 ; await fetchUserList ( ) }
resetAddForm ( )
} else {
ElMessage . error ( res . data . msg || '用户 创建失败')
}
} catch ( error ) {
console . error ( '用户创建失败:' , error )
ElMessage . error ( '用户创建失败' )
} finally {
addLoading . value = false
}
} else { ElMessage . error ( res . data . msg || '创建失败' ) }
} catch { ElMessage . error ( ' 创建失败') }
finally { addLoading . value = false }
} )
}
// 重置添加表单
const resetAddForm = ( ) => {
addForm . user _name = ''
addForm . email = ''
addForm . phone = ''
addForm . password = ''
addForm . confirmPassword = ''
addFormRef . value ? . resetFields ( )
}
// 关闭对话框
const handleClose = ( ) => {
visible . value = false
selectedUser . value = null
userList . value = [ ]
searchParams . key = ''
searchParams . status = ''
searchParams . page = 1
total . value = 0
resetAddForm ( )
}
// 确认选择
const handleConfirm = ( ) => {
if ( selectedUser . value ) {
emit ( 'confirm' , selectedUser . value )
handleClose ( )
} else {
ElMessage . warning ( '请选择一个用户' )
}
}
const resetAddForm = ( ) => { Object . assign ( addForm , { user _name : '' , email : '' , phone : '' , password : '' , confirmPassword : '' } ) ; addFormRef . value ? . resetFields ( ) }
const handleClose = ( ) => { visible . value = false ; selectedUser . value = null ; userList . value = [ ] ; searchParams . key = '' ; searchParams . is _admin = undefined ; searchParams . page = 1 ; total . value = 0 ; resetAddForm ( ) }
const handleConfirm = ( ) => { if ( selectedUser . value ) { emit ( 'confirm' , selectedUser . value ) ; handleClose ( ) } else ElMessage . warning ( '请选择一个用户' ) }
< / script >
< style scoped >
. user - selector {
min - height : 450 px ;
}
. uls - root { min - height : 460 px ; }
. user - list - container {
padding : 10 px 0 ;
}
/* 标签页 */
. tab - lbl { display : inline - flex ; align - items : center ; gap : 5 px ; }
: deep ( . el - tabs _ _item ) { font - size : 15 px ; padding : 0 20 px ; }
: deep ( . el - tabs _ _item . is - active ) { font - weight : 600 ; }
. filter - section {
margin - bottom : 16 px ;
padding : 16 px ;
background - color : # f5f7fa ;
border - radius : 8 px ;
}
/* 搜索栏 */
. uls - search { display : flex ; align - items : center ; gap : 8 px ; margin - bottom : 14 px ; }
. uls - search - input { flex : 1 ; max - width : 320 px ; }
. search - form {
display : flex ;
flex - wrap : wrap ;
align - items : center ;
gap : 8 px ;
}
/* 已选提示条 */
. uls - selected - bar { display : flex ; align - items : center ; justify - content : space - between ; padding : 8 px 14 px ; margin - bottom : 12 px ; background : linear - gradient ( 135 deg , # f0f9eb 0 % , # e1f3d8 100 % ) ; border : 1 px solid # c2e7b0 ; border - radius : 8 px ; }
. uls - sel - left { display : flex ; align - items : center ; gap : 6 px ; font - size : 13 px ; color : # 1 d2129 ; }
. uls - sel - left b { font - weight : 600 ; }
. sel - id { color : # 86909 c ; font - size : 12 px ; }
. sel - avatar { flex - shrink : 0 ; font - size : 11 px ; background : linear - gradient ( 135 deg , # 67 c23a , # 85 ce61 ) ; color : # fff ; }
. search - form : deep ( . el - form - item ) {
margin - bottom : 0 ;
margin - right : 12 px ;
}
. fade - enter - active , . fade - leave - active { transition : all .25 s ease ; }
. fade - enter - from , . fade - leave - to { opacity : 0 ; transform : translateY ( - 6 px ) ; }
. user - info - cell {
display : flex ;
align - items : center ;
gap : 10 px ;
}
/* 卡片网格 */
. uls - grid { display : grid ; grid - template - columns : repeat ( auto - fill , minmax ( 240 px , 1 fr ) ) ; gap : 10 px ; max - height : 340 px ; overflow - y : auto ; padding : 2 px ; }
. user - name {
font - weight : 500 ;
color : # 303133 ;
}
. uls - card { position : relative ; display : flex ; align - items : center ; gap : 12 px ; padding : 12 px 14 px ; border : 2 px solid # ebeef5 ; border - radius : 10 px ; cursor : pointer ; transition : all .2 s ease ; background : # fff ; }
. uls - card : hover { border - color : # b3d8ff ; background : # f5faff ; transform : translateY ( - 1 px ) ; box - shadow : 0 4 px 12 px rgba ( 64 , 158 , 255 , .1 ) ; }
. uls - card . active { border - color : # 409 eff ; background : # ecf5ff ; }
. pagination - container {
margin - top : 20 px ;
display : flex ;
justify - content : flex - end ;
}
. uls - card - check { position : absolute ; top : - 1 px ; right : - 1 px ; width : 24 px ; height : 24 px ; background : # 409 eff ; border - radius : 0 8 px 0 8 px ; display : flex ; align - items : center ; justify - content : center ; }
. add - user - section {
padding : 30 px 60 px ;
}
. uls - avatar { flex - shrink : 0 ; font - size : 16 px ; font - weight : 700 ; background : linear - gradient ( 135 deg , # c6e2ff , # 409 eff ) ; color : # fff ; }
. uls - card . active . uls - avatar { background : linear - gradient ( 135 deg , # 409 eff , # 337 ecc ) ; }
. add - user - form {
max - width : 500 px ;
margin : 0 auto ;
}
. uls - card - body { flex : 1 ; min - width : 0 ; display : flex ; flex - direction : column ; gap : 3 px ; }
. uls - card - name { font - size : 14 px ; font - weight : 600 ; color : # 1 d2129 ; display : flex ; align - items : center ; gap : 6 px ; white - space : nowrap ; overflow : hidden ; text - overflow : ellipsis ; }
. admin - tag { transform : scale ( .85 ) ; transform - origin : left center ; }
. add - user - form : deep ( . el - input ) {
width : 100 % ;
}
. uls - card - meta { display : flex ; flex - wrap : wrap ; gap : 4 px 8 px ; font - size : 11 px ; color : # a8abb2 ; line - height : 1.3 ; }
. meta - id { color : # 86909 c ; font - weight : 500 ; }
. meta - email , . meta - phone { overflow : hidden ; text - overflow : ellipsis ; white - space : nowrap ; max - width : 150 px ; }
. dialog - footer {
display : flex ;
justify - content : flex - end ;
gap : 10 px ;
}
/* 分页 */
. uls - pagination { margin - top : 14 px ; display : flex ; justify - content : flex - end ; }
/* 表格样式 */
: deep ( . el - table _ _row ) {
cursor : pointer ;
}
/* 添加用户 */
. uls - add - section { padding : 24 px 40 px ; }
. uls - add - form { max - width : 460 px ; margin : 0 auto ; }
: deep ( . el - table _ _row : hover ) {
background - color : # f5f7fa ;
}
/* 底部 */
. uls - footer { display : flex ; justify - content : flex - end ; gap : 10 px ; }
: deep ( . selected - row ) {
background - color : var ( -- el - color - primary - light - 9 ) ! important ;
}
: deep ( . selected - row td ) {
background - color : var ( -- el - color - primary - light - 9 ) ! important ;
}
: deep ( . el - table _ _body tr . current - row > td ) {
background - color : var ( -- el - color - primary - light - 8 ) ! important ;
}
/* 标签页样式 */
: deep ( . el - tabs _ _header ) {
margin - bottom : 16 px ;
}
: deep ( . el - tabs _ _item ) {
font - size : 15 px ;
padding : 0 24 px ;
}
: deep ( . el - tabs _ _item . is - active ) {
font - weight : 600 ;
}
/* 滚动条美化 */
. uls - grid : : - webkit - scrollbar { width : 5 px ; }
. uls - grid : : - webkit - scrollbar - thumb { background : # dcdfe6 ; border - radius : 4 px ; }
. uls - grid : : - webkit - scrollbar - thumb : hover { background : # c0c4cc ; }
< / style >