Commit 8ac047d6 by 周海峰

用户管理

parent 451064d2
<template>
<div class="key-management">
<!-- 标题 -->
<div class="title">
<i class="el-icon-lock"></i>
密钥管理
</div>
<!-- 密管选择区域 -->
<div class="section-card">
<div class="section-title">密管选择区域:</div>
<div class="section-content">
<div class="form-item">
<span class="label">密管方式</span>
<el-select v-model="keyManageType" placeholder="请选择" style="width: 200px;padding-right: 10px;">
<el-option label="三末加密机" value="threeTerm"></el-option>
</el-select>
<el-checkbox v-model="isEnabled">是否启用</el-checkbox>
<span class="tip">
* 平台只能选择一种密管方式,切换加密规则,平台可切换密管方式。
</span>
</div>
</div>
</div>
<!-- 参数配置区域 -->
<div class="section-card">
<div class="section-title">参数配置区域:</div>
<div class="section-content">
<div class="button-group">
<el-button type="primary">下载配置模板</el-button>
<el-button type="primary">上传配置文件</el-button>
</div>
</div>
</div>
<!-- 底部按钮 -->
<div class="footer">
<el-button type="primary">编辑</el-button>
</div>
</div>
</template>
<script>
/**
* 规则管理-密钥管理
*/
export default {
name: 'KeyManagement',
data() {
return {
keyManageType: '三末加密机',
isEnabled: false
}
}
}
</script>
<style lang="scss" scoped>
.key-management {
padding: 20px;
.title {
font-size: 18px;
color: #333;
margin-bottom: 20px;
i {
color: #409EFF;
margin-right: 8px;
}
}
.section-card {
background: #fff;
border-radius: 4px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 2px 12px 0 rgba(0,0,0,0.1);
.section-title {
color: #409EFF;
font-size: 14px;
margin-bottom: 20px;
position: relative;
padding-left: 12px;
&:before {
content: '';
width: 4px;
height: 14px;
background: #409EFF;
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
}
}
.section-content {
.form-item {
display: flex;
align-items: center;
.label {
width: 100px;
margin-right: 10px;
}
.tip {
color: #f56c6c;
margin-left: 10px;
font-size: 12px;
}
}
.button-group {
button {
margin-right: 10px;
}
}
}
}
.footer {
text-align: center;
margin-top: 20px;
}
}
</style>
\ No newline at end of file
++ "b/src/views/ruleConfig/\350\247\204\345\210\231\347\256\241\347\220\206"
# 应用用户维护
\ No newline at end of file
# 用户组维护
\ No newline at end of file
<template>
<el-dialog
title="编辑用户"
:model-value="visible"
@update:model-value="$emit('update:visible', $event)"
width="800px"
:close-on-click-modal="false"
append-to-body
destroy-on-close
:align-center="true"
:fullscreen="false"
@close="handleClose"
class="user-edit-dialog"
>
<div class="dialog-content" style="padding: 20px; padding-bottom: 80px;height: 700px;overflow-y: auto;">
<el-form
ref="formRef"
:model="form"
:rules="rules"
label-width="100px"
>
<!-- 姓名和角色名 -->
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="角色名" prop="roleName">
<el-input v-model="form.roleName" placeholder="请输入角色名" />
</el-form-item>
</el-col>
</el-row>
<!-- 备注 -->
<el-form-item label="备注" prop="remark">
<el-input
v-model="form.remark"
type="textarea"
placeholder="请输入备注"
/>
</el-form-item>
<!-- 权限设置 -->
<el-form-item label="权限设置">
<div class="permission-area">
<div class="all-select">
<el-checkbox v-model="allPermissionsSelected" @change="handleAllPermissionsChange">全选</el-checkbox>
</div>
<div class="permission-list">
<div v-for="(item, index) in permissionList" :key="index" class="permission-item">
<!-- 父级权限项 -->
<div class="permission-header" @click="toggleExpand(item)">
<div class="left">
<el-icon class="expand-icon" :class="{ expanded: item.expanded }">
<ArrowRight />
</el-icon>
<el-checkbox
v-model="item.selected"
:indeterminate="item.indeterminate"
@change="(val) => handlePermissionChange(item, val)"
>
{{ item.name }}
</el-checkbox>
</div>
<div class="right">
<el-tag size="small" v-if="item.children">{{ item.children.length }}</el-tag>
</div>
</div>
<!-- 子级权限列表 -->
<div v-if="item.children" class="sub-permissions" v-show="item.expanded">
<el-checkbox
v-for="child in item.children"
:key="child.id"
v-model="child.selected"
@change="(val) => handleSubPermissionChange(item, child, val)"
>
{{ child.name }}
</el-checkbox>
</div>
</div>
</div>
</div>
</el-form-item>
</el-form>
</div>
<template #footer>
<div class="dialog-footer">
<div class="footer-buttons">
<el-button @click="handleClose">取 消</el-button>
<el-button type="primary" @click="handleSubmit">确 定</el-button>
</div>
</div>
</template>
</el-dialog>
</template>
<script>
export default {
name: 'RoleEdit',
props: {
visible: {
type: Boolean,
default: false
},
formData: {
type: Object,
default: () => null
}
},
emits: ['update:visible', 'success'],
watch: {
visible(val) {
if (val && this.formData) {
this.form = {
...this.formData,
password: '',
confirmPassword: ''
}
}
}
},
data() {
// 密码验证
const validatePassword = (rule, value, callback) => {
if (value === '') {
callback(new Error('请输入密码'))
} else {
if (this.form.confirmPassword !== '') {
this.$refs.formRef.validateField('confirmPassword')
}
callback()
}
}
// 确认密码验证
const validateConfirmPassword = (rule, value, callback) => {
if (value === '') {
callback(new Error('请再次输入密码'))
} else if (value !== this.form.password) {
callback(new Error('两次输入密码不一致!'))
} else {
callback()
}
}
return {
form: {
realname: '',
roleName: '',
password: '',
confirmPassword: '',
email: '',
userGroup: '',
remark: '',
isDisabled: false
},
rules: {
roleName: [
{ required: true, message: '请输入角色名', trigger: 'blur' }
]
},
allSelected: false,
searchRole: '',
selectedRoles: [],
allPermissionsSelected: false,
permissionList: [
{
id: 1,
name: '管理首页',
selected: false,
expanded: false,
indeterminate: false
},
{
id: 2,
name: '项目管理',
selected: false,
expanded: false
},
{
id: 3,
name: '规则管理',
selected: false,
children: [
{ id: '3-1', name: '规则管理子项1', selected: false },
{ id: '3-2', name: '规则管理子项2', selected: false }
]
},
{
id: 4,
name: '资产库',
selected: false
},
{
id: 5,
name: '系统设置',
selected: false,
children: [
{ id: '5-1', name: '设置子项1', selected: false },
{ id: '5-2', name: '设置子项2', selected: false }
]
},
{
id: 6,
name: '用户管理',
selected: false,
children: [
{ id: '6-1', name: '用户管理子项1', selected: false },
{ id: '6-2', name: '用户管理子项2', selected: false }
]
}
]
}
},
computed: {
filteredRoles() {
return this.roles.filter(role =>
role.name.toLowerCase().includes(this.searchRole.toLowerCase())
)
}
},
methods: {
handleClose() {
this.$emit('update:visible', false)
this.$refs.formRef?.resetFields()
this.form = {
realname: '',
roleName: '',
password: '',
confirmPassword: '',
email: '',
userGroup: '',
remark: '',
isDisabled: false
}
},
handleSubmit() {
this.$refs.formRef.validate((valid) => {
if (valid) {
// 提交表单逻辑
const params = { ...this.form }
// 如果是编辑模式且没有修改密码,则不提交密码字段
if (this.formData && !params.password) {
delete params.password
delete params.confirmPassword
}
console.log('submit form', params)
// 调用接口保存数据
this.$emit('success')
this.handleClose()
}
})
},
handleSelectAll(val) {
this.roles.forEach(role => {
role.selected = val
})
},
handleRoleSelect(role, val) {
role.selected = val
this.allSelected = this.roles.every(role => role.selected)
},
addSelected() {
const selectedRoles = this.roles.filter(role => role.selected)
this.selectedRoles = [...new Set([...this.selectedRoles, ...selectedRoles])]
this.roles = this.roles.filter(role => !role.selected)
this.allSelected = false
},
removeSelected() {
this.roles = [...this.roles, ...this.selectedRoles]
this.selectedRoles = []
},
clearSelected() {
this.roles = [...this.roles, ...this.selectedRoles]
this.selectedRoles = []
},
// 权限相关方法
handleAllPermissionsChange(val) {
// 处理全选
this.permissionList.forEach(item => {
item.selected = val
if (item.children) {
item.children.forEach(child => {
child.selected = val
})
}
})
},
handlePermissionChange(item, val) {
// 处理父级权限选择
item.selected = val
item.indeterminate = false // 清除半选状态
if (item.children) {
item.children.forEach(child => {
child.selected = val
})
}
this.checkAllPermissionsStatus()
},
handleSubPermissionChange(parent, child, val) {
// 处理子级权限选择
child.selected = val
// 检查父级状态
if (parent.children) {
// 如果所有子项都选中,父级完全选中
const allSelected = parent.children.every(c => c.selected)
// 如果部分子项选中,父级半选
const someSelected = parent.children.some(c => c.selected)
parent.selected = allSelected
parent.indeterminate = !allSelected && someSelected
}
this.checkAllPermissionsStatus()
},
checkAllPermissionsStatus() {
// 检查是否全部选中
this.allPermissionsSelected = this.permissionList.every(item => {
if (item.children) {
return item.selected && item.children.every(child => child.selected)
}
return item.selected
})
},
toggleExpand(item) {
// 展开/收起子菜单
item.expanded = !item.expanded
}
}
}
</script>
<style lang="scss" scoped>
.role-transfer {
display: flex;
align-items: flex-start;
gap: 10px;
.transfer-list {
flex: 1;
border: 1px solid #dcdfe6;
border-radius: 4px;
height: 300px;
display: flex;
flex-direction: column;
.transfer-header {
padding: 8px 12px;
border-bottom: 1px solid #dcdfe6;
display: flex;
justify-content: space-between;
align-items: center;
background-color: #f5f7fa;
}
.role-list, .selected-list {
flex: 1;
overflow-y: auto;
padding: 6px 0;
}
.role-item {
padding: 6px 12px;
cursor: pointer;
&:hover {
background-color: #f5f7fa;
}
}
}
.transfer-operation {
display: flex;
flex-direction: column;
gap: 10px;
padding: 10px 0;
}
}
.permission-area {
border: 1px solid #dcdfe6;
border-radius: 4px;
width: 100%;
display: flex;
flex-direction: column;
.all-select {
padding: 8px 12px;
background-color: #f5f7fa;
border-bottom: 1px solid #dcdfe6;
}
.permission-list {
padding: 12px;
.permission-item {
border-bottom: 1px solid #ebeef5;
&:last-child {
border-bottom: none;
}
.permission-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px 0;
cursor: pointer;
.left {
display: flex;
align-items: center;
gap: 8px;
.expand-icon {
transition: transform 0.3s;
font-size: 12px;
color: #909399;
&.expanded {
transform: rotate(90deg);
}
}
}
}
.sub-permissions {
padding: 8px 0 8px 32px;
display: flex;
flex-direction: column;
gap: 12px;
background-color: #f8f9fb;
border-top: 1px solid #ebeef5;
}
}
}
}
:deep(.el-transfer-panel) {
width: 100%;
}
.user-edit-dialog {
:deep(.el-dialog) {
display: flex;
flex-direction: column;
margin: 0 auto !important;
max-height: 90vh;
position: relative;
.el-dialog__body {
flex: 1;
overflow: hidden;
padding: 0;
}
.dialog-content {
height: 100%;
overflow-y: auto;
padding: 20px;
padding-bottom: 80px;
}
}
}
.dialog-footer {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
padding: 20px;
background-color: #fff;
border-top: 1px solid #dcdfe6;
z-index: 9999;
.footer-buttons {
display: flex;
gap: 10px;
justify-content: flex-end;
}
}
</style>
<template>
<div class="user-config">
<!-- 标题 -->
<div class="title">
<el-icon><User /></el-icon>
角色
</div>
<!-- 搜索和操作区域 -->
<div class="search-area">
<el-form :inline="true" :model="searchForm" class="search-form">
<div class="left-area">
<el-form-item label="角色名:">
<el-input v-model="searchForm.roleName" placeholder="请输入角色名"></el-input>
</el-form-item>
<el-form-item label="备注:">
<el-input v-model="searchForm.remark" placeholder="请输入备注"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleSearch">搜索</el-button>
</el-form-item>
</div>
<div class="right-area">
<el-button type="primary" icon="Plus" @click="handleAdd">新增角色</el-button>
</div>
</el-form>
</div>
<!-- 列表 -->
<div class="user-list">
<div class="user-grid">
<div v-for="(user, index) in userList" :key="index" class="user-card">
<div class="user-info">
<div class="avatar">
<el-avatar :size="50" icon="User"></el-avatar>
</div>
<div class="info">
<div class="roleName">角色名: {{ user.roleName }}</div>
<div class="remark">备注: {{ user.remark }}</div>
</div>
<!-- 遮罩层和操作按钮 -->
<div class="hover-mask">
<div class="operation-buttons">
<div class="operation-btn" @click="handleDelete(user)">
<i class="el-icon-delete"></i>
<span>删除</span>
</div>
<div class="operation-btn" @click="handleEdit(user)">
<i class="el-icon-edit"></i>
<span>编辑</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 分页 -->
<div class="pagination">
<div class="pagination-info">共有记录 1条,每页显示 8条,共 1页</div>
<el-pagination
background
layout="prev, pager, next, jumper"
:total="total"
:current-page.sync="currentPage"
:page-size="pageSize"
@current-change="handlePageChange">
</el-pagination>
</div>
<!-- 编辑弹窗 -->
<role-edit
v-model:visible="editVisible"
:form-data="editData"
@success="handleEditSuccess"
/>
</div>
</template>
<script>
import RoleEdit from './edit.vue'
export default {
name: 'RoleConfig',
components: {
RoleEdit
},
data() {
return {
searchForm: {
name: '',
roleName: '',
remark: ''
},
userList: [
{
realname: 'admin',
roleName: 'admin',
remark: ''
}
],
total: 1,
currentPage: 1,
pageSize: 8,
editVisible: false,
editData: null
}
},
methods: {
handleSearch() {
// 实现搜索逻辑
},
handleAdd() {
// 打开新增角色弹窗
this.editData = null
this.editVisible = true
},
handlePageChange(page) {
// 实现分页逻辑
},
handleDelete(row) {
// 实现删除角色逻辑
this.$confirm('确认删除该角色吗?', '提示', {
type: 'warning'
}).then(() => {
// 调用删除接口
console.log('删除角色', row)
}).catch(() => {})
},
handleEdit(row) {
// 打开编辑角色弹窗
this.editData = { ...row }
this.editVisible = true
},
handleEditSuccess() {
// 编辑成功后的回调
this.editVisible = false
// 刷新列表数据
this.getList()
},
getList() {
// 获取角色列表数据
}
}
}
</script>
<style lang="scss" scoped>
.user-config {
padding: 20px;
.title {
font-size: 18px;
color: #333;
margin-bottom: 20px;
display: flex;
align-items: center;
i {
color: #409EFF;
margin-right: 8px;
font-size: 20px;
}
}
.search-area {
background: #fff;
padding: 20px;
border-radius: 4px;
margin-bottom: 20px;
.search-form {
display: flex;
justify-content: space-between;
align-items: center;
.left-area {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.right-area {
margin-left: 20px;
}
}
.el-form-item {
margin-bottom: 0;
}
}
.user-list {
margin-bottom: 20px;
.user-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 20px;
}
.user-card {
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
overflow: hidden;
}
.user-info {
display: flex;
align-items: center;
padding: 20px;
position: relative;
cursor: pointer;
height: 100%;
.avatar {
margin-right: 15px;
}
.info {
flex: 1;
.name {
font-size: 16px;
font-weight: bold;
margin-bottom: 8px;
color: #333;
}
.roleName, .remark {
color: #666;
font-size: 14px;
margin-bottom: 5px;
}
}
.hover-mask {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.6);
display: none;
justify-content: center;
align-items: center;
.operation-buttons {
display: flex;
gap: 30px;
.operation-btn {
display: flex;
flex-direction: column;
align-items: center;
color: white;
cursor: pointer;
i {
font-size: 24px;
margin-bottom: 8px;
}
span {
font-size: 14px;
}
&:hover {
color: #409EFF;
}
}
}
}
&:hover {
.hover-mask {
display: flex;
}
}
}
.operation-time {
color: #666;
i {
margin-right: 5px;
}
}
}
.pagination {
background: #fff;
padding: 15px 20px;
border-radius: 4px;
display: flex;
justify-content: space-between;
align-items: center;
.pagination-info {
color: #666;
font-size: 14px;
}
}
}
</style>
# 角色维护
\ No newline at end of file
# 用户管理模块 包含
# 用户
# 用户组
# 角色
# 应用用户
<template>
<el-dialog
title="编辑用户"
:model-value="visible"
@update:model-value="$emit('update:visible', $event)"
width="800px"
:close-on-click-modal="false"
append-to-body
destroy-on-close
:align-center="true"
:fullscreen="false"
@close="handleClose"
class="user-edit-dialog"
>
<div class="dialog-content" style="padding: 20px; padding-bottom: 80px;height: 700px;overflow-y: auto;">
<el-form
ref="formRef"
:model="form"
:rules="rules"
label-width="100px"
>
<!-- 姓名和用户名 -->
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="真实姓名" prop="realname">
<el-input v-model="form.realname" placeholder="请输入真实姓名" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="用户名" prop="username">
<el-input v-model="form.username" placeholder="请输入用户名" />
</el-form-item>
</el-col>
</el-row>
<!-- 密码和确认密码 -->
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="密码" prop="password">
<el-input
v-model="form.password"
type="password"
placeholder="请输入密码"
show-password
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="确认密码" prop="confirmPassword">
<el-input
v-model="form.confirmPassword"
type="password"
placeholder="请确认密码"
show-password
/>
</el-form-item>
</el-col>
</el-row>
<!-- 邮箱 -->
<el-form-item label="邮箱" prop="email">
<el-input v-model="form.email" placeholder="请输入邮箱" />
</el-form-item>
<!-- 用户组 -->
<el-form-item label="用户组" prop="userGroup">
<el-select v-model="form.userGroup" placeholder="请选择">
<el-option
v-for="item in userGroupOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<!-- 备注 -->
<el-form-item label="备注" prop="remark">
<el-input
v-model="form.remark"
type="textarea"
placeholder="请输入备注"
/>
</el-form-item>
<!-- 用户是否禁用 -->
<el-form-item label="用户是否禁用">
<el-switch v-model="form.isDisabled" />
</el-form-item>
<!-- 角色选择 -->
<el-form-item label="选择角色">
<div class="role-transfer">
<div class="transfer-list">
<div class="transfer-header">
<span>角色列表</span>
<el-checkbox v-model="allSelected" @change="handleSelectAll">全选</el-checkbox>
</div>
<el-input v-model="searchRole" placeholder="请输入搜索内容" />
<div class="role-list">
<div v-for="role in filteredRoles" :key="role.id" class="role-item">
<el-checkbox
v-model="role.selected"
@change="(val) => handleRoleSelect(role, val)"
>
{{ role.name }}
</el-checkbox>
</div>
</div>
</div>
<div class="transfer-operation">
<el-button type="primary" plain icon="ArrowRight" @click="addSelected" />
<el-button type="primary" plain icon="ArrowLeft" @click="removeSelected" />
</div>
<div class="transfer-list">
<div class="transfer-header">
<span>已选择角色列表</span>
<el-button link type="primary" @click="clearSelected">清空</el-button>
</div>
<div class="selected-list">
<div v-for="role in selectedRoles" :key="role.id" class="role-item">
{{ role.name }}
</div>
</div>
</div>
</div>
</el-form-item>
<!-- 权限设置 -->
<el-form-item label="权限设置">
<div class="permission-area">
<div class="all-select">
<el-checkbox v-model="allPermissionsSelected" @change="handleAllPermissionsChange">全选</el-checkbox>
</div>
<div class="permission-list">
<div v-for="(item, index) in permissionList" :key="index" class="permission-item">
<!-- 父级权限项 -->
<div class="permission-header" @click="toggleExpand(item)">
<div class="left">
<el-icon class="expand-icon" :class="{ expanded: item.expanded }">
<ArrowRight />
</el-icon>
<el-checkbox
v-model="item.selected"
:indeterminate="item.indeterminate"
@change="(val) => handlePermissionChange(item, val)"
>
{{ item.name }}
</el-checkbox>
</div>
<div class="right">
<el-tag size="small" v-if="item.children">{{ item.children.length }}</el-tag>
</div>
</div>
<!-- 子级权限列表 -->
<div v-if="item.children" class="sub-permissions" v-show="item.expanded">
<el-checkbox
v-for="child in item.children"
:key="child.id"
v-model="child.selected"
@change="(val) => handleSubPermissionChange(item, child, val)"
>
{{ child.name }}
</el-checkbox>
</div>
</div>
</div>
</div>
</el-form-item>
</el-form>
</div>
<template #footer>
<div class="dialog-footer">
<div class="footer-buttons">
<el-button @click="handleClose">取 消</el-button>
<el-button type="primary" @click="handleSubmit">确 定</el-button>
</div>
</div>
</template>
</el-dialog>
</template>
<script>
export default {
name: 'UserEdit',
props: {
visible: {
type: Boolean,
default: false
},
formData: {
type: Object,
default: () => null
}
},
emits: ['update:visible', 'success'],
watch: {
visible(val) {
if (val && this.formData) {
this.form = {
...this.formData,
password: '',
confirmPassword: ''
}
}
}
},
data() {
// 密码验证
const validatePassword = (rule, value, callback) => {
if (value === '') {
callback(new Error('请输入密码'))
} else {
if (this.form.confirmPassword !== '') {
this.$refs.formRef.validateField('confirmPassword')
}
callback()
}
}
// 确认密码验证
const validateConfirmPassword = (rule, value, callback) => {
if (value === '') {
callback(new Error('请再次输入密码'))
} else if (value !== this.form.password) {
callback(new Error('两次输入密码不一致!'))
} else {
callback()
}
}
return {
form: {
realname: '',
username: '',
password: '',
confirmPassword: '',
email: '',
userGroup: '',
remark: '',
isDisabled: false
},
rules: {
realname: [
{ required: true, message: '请输入真实姓名', trigger: 'blur' }
],
username: [
{ required: true, message: '请输入用户名', trigger: 'blur' }
],
password: [
{ required: true, validator: validatePassword, trigger: 'blur' }
],
confirmPassword: [
{ required: true, validator: validateConfirmPassword, trigger: 'blur' }
],
email: [
{ required: true, message: '请输入邮箱', trigger: 'blur' },
{ type: 'email', message: '请输入正确的邮箱地址', trigger: 'blur' }
]
},
userGroupOptions: [
{ value: 'admin', label: '管理员' },
{ value: 'user', label: '普通用户' }
],
allSelected: false,
searchRole: '',
roles: [
{ id: 1, name: '系统管理员', selected: false },
{ id: 2, name: '2222', selected: false }
],
selectedRoles: [],
allPermissionsSelected: false,
permissionList: [
{
id: 1,
name: '管理首页',
selected: false,
expanded: false,
indeterminate: false
},
{
id: 2,
name: '项目管理',
selected: false,
expanded: false
},
{
id: 3,
name: '规则管理',
selected: false,
children: [
{ id: '3-1', name: '规则管理子项1', selected: false },
{ id: '3-2', name: '规则管理子项2', selected: false }
]
},
{
id: 4,
name: '资产库',
selected: false
},
{
id: 5,
name: '系统设置',
selected: false,
children: [
{ id: '5-1', name: '设置子项1', selected: false },
{ id: '5-2', name: '设置子项2', selected: false }
]
},
{
id: 6,
name: '用户管理',
selected: false,
children: [
{ id: '6-1', name: '用户管理子项1', selected: false },
{ id: '6-2', name: '用户管理子项2', selected: false }
]
}
]
}
},
computed: {
filteredRoles() {
return this.roles.filter(role =>
role.name.toLowerCase().includes(this.searchRole.toLowerCase())
)
}
},
methods: {
handleClose() {
this.$emit('update:visible', false)
this.$refs.formRef?.resetFields()
this.form = {
realname: '',
username: '',
password: '',
confirmPassword: '',
email: '',
userGroup: '',
remark: '',
isDisabled: false
}
},
handleSubmit() {
this.$refs.formRef.validate((valid) => {
if (valid) {
// 提交表单逻辑
const params = { ...this.form }
// 如果是编辑模式且没有修改密码,则不提交密码字段
if (this.formData && !params.password) {
delete params.password
delete params.confirmPassword
}
console.log('submit form', params)
// 调用接口保存数据
this.$emit('success')
this.handleClose()
}
})
},
handleSelectAll(val) {
this.roles.forEach(role => {
role.selected = val
})
},
handleRoleSelect(role, val) {
role.selected = val
this.allSelected = this.roles.every(role => role.selected)
},
addSelected() {
const selectedRoles = this.roles.filter(role => role.selected)
this.selectedRoles = [...new Set([...this.selectedRoles, ...selectedRoles])]
this.roles = this.roles.filter(role => !role.selected)
this.allSelected = false
},
removeSelected() {
this.roles = [...this.roles, ...this.selectedRoles]
this.selectedRoles = []
},
clearSelected() {
this.roles = [...this.roles, ...this.selectedRoles]
this.selectedRoles = []
},
// 权限相关方法
handleAllPermissionsChange(val) {
// 处理全选
this.permissionList.forEach(item => {
item.selected = val
if (item.children) {
item.children.forEach(child => {
child.selected = val
})
}
})
},
handlePermissionChange(item, val) {
// 处理父级权限选择
item.selected = val
item.indeterminate = false // 清除半选状态
if (item.children) {
item.children.forEach(child => {
child.selected = val
})
}
this.checkAllPermissionsStatus()
},
handleSubPermissionChange(parent, child, val) {
// 处理子级权限选择
child.selected = val
// 检查父级状态
if (parent.children) {
// 如果所有子项都选中,父级完全选中
const allSelected = parent.children.every(c => c.selected)
// 如果部分子项选中,父级半选
const someSelected = parent.children.some(c => c.selected)
parent.selected = allSelected
parent.indeterminate = !allSelected && someSelected
}
this.checkAllPermissionsStatus()
},
checkAllPermissionsStatus() {
// 检查是否全部选中
this.allPermissionsSelected = this.permissionList.every(item => {
if (item.children) {
return item.selected && item.children.every(child => child.selected)
}
return item.selected
})
},
toggleExpand(item) {
// 展开/收起子菜单
item.expanded = !item.expanded
}
}
}
</script>
<style lang="scss" scoped>
.role-transfer {
display: flex;
align-items: flex-start;
gap: 10px;
.transfer-list {
flex: 1;
border: 1px solid #dcdfe6;
border-radius: 4px;
height: 300px;
display: flex;
flex-direction: column;
.transfer-header {
padding: 8px 12px;
border-bottom: 1px solid #dcdfe6;
display: flex;
justify-content: space-between;
align-items: center;
background-color: #f5f7fa;
}
.role-list, .selected-list {
flex: 1;
overflow-y: auto;
padding: 6px 0;
}
.role-item {
padding: 6px 12px;
cursor: pointer;
&:hover {
background-color: #f5f7fa;
}
}
}
.transfer-operation {
display: flex;
flex-direction: column;
gap: 10px;
padding: 10px 0;
}
}
.permission-area {
border: 1px solid #dcdfe6;
border-radius: 4px;
width: 100%;
display: flex;
flex-direction: column;
.all-select {
padding: 8px 12px;
background-color: #f5f7fa;
border-bottom: 1px solid #dcdfe6;
}
.permission-list {
padding: 12px;
.permission-item {
border-bottom: 1px solid #ebeef5;
&:last-child {
border-bottom: none;
}
.permission-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px 0;
cursor: pointer;
.left {
display: flex;
align-items: center;
gap: 8px;
.expand-icon {
transition: transform 0.3s;
font-size: 12px;
color: #909399;
&.expanded {
transform: rotate(90deg);
}
}
}
}
.sub-permissions {
padding: 8px 0 8px 32px;
display: flex;
flex-direction: column;
gap: 12px;
background-color: #f8f9fb;
border-top: 1px solid #ebeef5;
}
}
}
}
:deep(.el-transfer-panel) {
width: 100%;
}
.user-edit-dialog {
:deep(.el-dialog) {
display: flex;
flex-direction: column;
margin: 0 auto !important;
max-height: 90vh;
position: relative;
.el-dialog__body {
flex: 1;
overflow: hidden;
padding: 0;
}
.dialog-content {
height: 100%;
overflow-y: auto;
padding: 20px;
padding-bottom: 80px;
}
}
}
.dialog-footer {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
padding: 20px;
background-color: #fff;
border-top: 1px solid #dcdfe6;
z-index: 9999;
.footer-buttons {
display: flex;
gap: 10px;
justify-content: flex-end;
}
}
</style>
<template>
<div class="user-config">
<!-- 标题 -->
<div class="title">
<el-icon><User /></el-icon>
用户
</div>
<!-- 搜索和操作区域 -->
<div class="search-area">
<el-form :inline="true" :model="searchForm" class="search-form">
<div class="left-area">
<el-form-item label="姓名:">
<el-input v-model="searchForm.name" placeholder="请输入姓名"></el-input>
</el-form-item>
<el-form-item label="用户名:">
<el-input v-model="searchForm.username" placeholder="请输入用户名"></el-input>
</el-form-item>
<el-form-item label="备注:">
<el-input v-model="searchForm.remark" placeholder="请输入备注"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleSearch">搜索</el-button>
</el-form-item>
</div>
<div class="right-area">
<el-button type="primary" icon="Plus" @click="handleAdd">新增用户</el-button>
</div>
</el-form>
</div>
<!-- 用户列表 -->
<div class="user-list">
<div class="user-grid">
<div v-for="(user, index) in userList" :key="index" class="user-card">
<div class="user-info">
<div class="avatar">
<el-avatar :size="50" icon="User"></el-avatar>
</div>
<div class="info">
<div class="name">{{ user.realname }}</div>
<div class="username">用户名: {{ user.username }}</div>
<div class="remark">备注: {{ user.remark }}</div>
</div>
<!-- 遮罩层和操作按钮 -->
<div class="hover-mask">
<div class="operation-buttons">
<div class="operation-btn" @click="handleDelete(user)">
<i class="el-icon-delete"></i>
<span>删除</span>
</div>
<div class="operation-btn" @click="handleEdit(user)">
<i class="el-icon-edit"></i>
<span>编辑</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 分页 -->
<div class="pagination">
<div class="pagination-info">共有记录 1条,每页显示 8条,共 1页</div>
<el-pagination
background
layout="prev, pager, next, jumper"
:total="total"
:current-page.sync="currentPage"
:page-size="pageSize"
@current-change="handlePageChange">
</el-pagination>
</div>
<!-- 编辑弹窗 -->
<user-edit
v-model:visible="editVisible"
:form-data="editData"
@success="handleEditSuccess"
/>
</div>
</template>
<script>
import UserEdit from './edit.vue'
export default {
name: 'UserConfig',
components: {
UserEdit
},
data() {
return {
searchForm: {
name: '',
username: '',
remark: ''
},
userList: [
{
realname: 'admin',
username: 'admin',
remark: ''
}
],
total: 1,
currentPage: 1,
pageSize: 8,
editVisible: false,
editData: null
}
},
methods: {
handleSearch() {
// 实现搜索逻辑
},
handleAdd() {
// 打开新增用户弹窗
this.editData = null
this.editVisible = true
},
handlePageChange(page) {
// 实现分页逻辑
},
handleDelete(row) {
// 实现删除用户逻辑
this.$confirm('确认删除该用户吗?', '提示', {
type: 'warning'
}).then(() => {
// 调用删除接口
console.log('删除用户', row)
}).catch(() => {})
},
handleEdit(row) {
// 打开编辑用户弹窗
this.editData = { ...row }
this.editVisible = true
},
handleEditSuccess() {
// 编辑成功后的回调
this.editVisible = false
// 刷新列表数据
this.getList()
},
getList() {
// 获取用户列表数据
}
}
}
</script>
<style lang="scss" scoped>
.user-config {
padding: 20px;
.title {
font-size: 18px;
color: #333;
margin-bottom: 20px;
display: flex;
align-items: center;
i {
color: #409EFF;
margin-right: 8px;
font-size: 20px;
}
}
.search-area {
background: #fff;
padding: 20px;
border-radius: 4px;
margin-bottom: 20px;
.search-form {
display: flex;
justify-content: space-between;
align-items: center;
.left-area {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.right-area {
margin-left: 20px;
}
}
.el-form-item {
margin-bottom: 0;
}
}
.user-list {
margin-bottom: 20px;
.user-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 20px;
}
.user-card {
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
overflow: hidden;
}
.user-info {
display: flex;
align-items: center;
padding: 20px;
position: relative;
cursor: pointer;
height: 100%;
.avatar {
margin-right: 15px;
}
.info {
flex: 1;
.name {
font-size: 16px;
font-weight: bold;
margin-bottom: 8px;
color: #333;
}
.username, .remark {
color: #666;
font-size: 14px;
margin-bottom: 5px;
}
}
.hover-mask {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.6);
display: none;
justify-content: center;
align-items: center;
.operation-buttons {
display: flex;
gap: 30px;
.operation-btn {
display: flex;
flex-direction: column;
align-items: center;
color: white;
cursor: pointer;
i {
font-size: 24px;
margin-bottom: 8px;
}
span {
font-size: 14px;
}
&:hover {
color: #409EFF;
}
}
}
}
&:hover {
.hover-mask {
display: flex;
}
}
}
.operation-time {
color: #666;
i {
margin-right: 5px;
}
}
}
.pagination {
background: #fff;
padding: 15px 20px;
border-radius: 4px;
display: flex;
justify-content: space-between;
align-items: center;
.pagination-info {
color: #666;
font-size: 14px;
}
}
}
</style>
# 用户维护
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论