343 lines
8.2 KiB
Vue
343 lines
8.2 KiB
Vue
<template>
|
|
<div class="container-box">
|
|
<div class="header-bar">
|
|
<h2>用户管理</h2>
|
|
<div class="header-actions">
|
|
<el-button type="primary" @click="handleAddUser">
|
|
<el-icon><Plus /></el-icon>
|
|
添加用户
|
|
</el-button>
|
|
<el-button @click="refresh">
|
|
<el-icon><Refresh /></el-icon>
|
|
刷新
|
|
</el-button>
|
|
</div>
|
|
</div>
|
|
|
|
<el-divider></el-divider>
|
|
|
|
<!-- 用户列表表格 -->
|
|
<el-table :data="users" style="width: 100%" v-loading="loading">
|
|
<el-table-column
|
|
prop="id"
|
|
label="ID"
|
|
align="center"
|
|
fixed="left"
|
|
/>
|
|
<el-table-column prop="account" label="账号" align="center" />
|
|
<el-table-column
|
|
prop="name"
|
|
label="姓名"
|
|
align="center"
|
|
>
|
|
<template #default="scope">
|
|
<span class="name-link" @click="handlePreview(scope.row)">{{ scope.row.name }}</span>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column prop="group_id" label="角色" align="center">
|
|
<template #default="scope">
|
|
<el-tag
|
|
:type="getRoleTagType(scope.row.group_id)"
|
|
size="small"
|
|
>
|
|
{{ getRoleTagText(roles, scope.row.group_id) }}
|
|
</el-tag>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column
|
|
prop="phone"
|
|
label="手机号"
|
|
align="center"
|
|
/>
|
|
<el-table-column prop="qq" label="QQ" align="center" />
|
|
<el-table-column
|
|
prop="last_login_ip"
|
|
label="最后登录IP"
|
|
width="120"
|
|
align="center"
|
|
/>
|
|
<el-table-column
|
|
prop="login_count"
|
|
label="登陆次数"
|
|
width="120"
|
|
align="center"
|
|
/>
|
|
<el-table-column prop="status" label="状态" width="80" align="center">
|
|
<template #default="scope">
|
|
<el-tag :type="scope.row.status === 1 ? 'success' : 'danger'">{{
|
|
scope.row.status === 1 ? "启用" : "禁用"
|
|
}}</el-tag>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column label="操作" width="240" align="center" fixed="right">
|
|
<template #default="scope">
|
|
<el-button size="small" @click="handleEdit(scope.row)"
|
|
>编辑</el-button
|
|
>
|
|
<el-button
|
|
size="small"
|
|
type="warning"
|
|
@click="handleChangePassword(scope.row)"
|
|
>
|
|
修改密码
|
|
</el-button>
|
|
<el-button
|
|
v-if="scope.row.username !== 'admin' && scope.row.id !== 1"
|
|
size="small"
|
|
type="danger"
|
|
@click="handleDelete(scope.row)"
|
|
>删除</el-button
|
|
>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
|
|
<!-- 分页 -->
|
|
<div class="pagination-bar">
|
|
<el-pagination
|
|
:current-page="page"
|
|
:page-size="pageSize"
|
|
:total="total"
|
|
@current-change="handlePageChange"
|
|
layout="total, prev, pager, next"
|
|
/>
|
|
</div>
|
|
|
|
<!-- 编辑用户对话框组件 -->
|
|
<UserEditDialog
|
|
ref="userEditRef"
|
|
:modelValue="editDialogVisible"
|
|
@update:modelValue="editDialogVisible = $event"
|
|
:is-edit="isEdit"
|
|
@submit="handleEditSuccess"
|
|
@close="editDialogVisible = false"
|
|
/>
|
|
|
|
<!-- 修改密码对话框组件 -->
|
|
<ChangePasswordDialog
|
|
ref="changePasswordRef"
|
|
:modelValue="passwordDialogVisible"
|
|
@update:modelValue="passwordDialogVisible = $event"
|
|
:user-id="currentUserId"
|
|
@submit="handlePasswordChangeSuccess"
|
|
@close="passwordDialogVisible = false"
|
|
/>
|
|
|
|
<!-- 预览用户对话框组件 -->
|
|
<PreviewDialog
|
|
ref="previewDialogRef"
|
|
:modelValue="previewDialogVisible"
|
|
@update:modelValue="previewDialogVisible = $event"
|
|
:user="currentUser"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, onMounted } from "vue";
|
|
import { ElMessage, ElMessageBox } from "element-plus";
|
|
import { Plus, Refresh } from "@element-plus/icons-vue";
|
|
import { getAllUsers, deleteUser } from "@/api/user";
|
|
import { getAllRoles } from "@/api/role";
|
|
import UserEditDialog from "./components/userEdit.vue";
|
|
import ChangePasswordDialog from "./components/changePassword.vue";
|
|
import PreviewDialog from "./components/preview.vue";
|
|
|
|
interface User {
|
|
id: number;
|
|
account: string;
|
|
name: string;
|
|
phone: string;
|
|
qq: string;
|
|
sex: number;
|
|
group_id: number;
|
|
status: number;
|
|
last_login_ip: string;
|
|
login_count: number;
|
|
create_time: string;
|
|
update_time: string;
|
|
}
|
|
|
|
interface Role {
|
|
id: number;
|
|
name: string;
|
|
status?: number;
|
|
rights?: string;
|
|
create_time?: string;
|
|
update_time?: string;
|
|
}
|
|
|
|
const page = ref(1);
|
|
const pageSize = ref(10);
|
|
const total = ref(0);
|
|
|
|
const users = ref<User[]>([]);
|
|
const roles = ref<Role[]>([]);
|
|
const loading = ref(false);
|
|
|
|
// 组件引用
|
|
const userEditRef = ref();
|
|
const changePasswordRef = ref();
|
|
const previewDialogRef = ref();
|
|
|
|
// 编辑/密码对话框状态
|
|
const editDialogVisible = ref(false);
|
|
const passwordDialogVisible = ref(false);
|
|
const previewDialogVisible = ref(false);
|
|
const editDialogTitle = ref("添加用户");
|
|
const isEdit = ref(false);
|
|
const currentUserId = ref<number | undefined>(undefined);
|
|
const currentUser = ref<User | undefined>(undefined);
|
|
|
|
//刷新
|
|
const refresh = async () => {
|
|
await fetchUsers();
|
|
};
|
|
|
|
// 获取角色列表
|
|
const fetchRoles = async () => {
|
|
try {
|
|
const res = await getAllRoles();
|
|
roles.value = res.data || [];
|
|
} catch (e) {
|
|
roles.value = [];
|
|
}
|
|
};
|
|
|
|
// 获取角色tag状态
|
|
function getRoleTagType(group_id: number): string {
|
|
const typeMap: Record<number, string> = {
|
|
1: "primary",
|
|
2: "success",
|
|
3: "warning",
|
|
4: "danger",
|
|
};
|
|
return typeMap[group_id] || "primary";
|
|
}
|
|
|
|
// 获取角色tag文本
|
|
function getRoleTagText(roles: Role[] | undefined, group_id: number): string {
|
|
if (!roles || !Array.isArray(roles)) {
|
|
return "未知";
|
|
}
|
|
return roles.find((role) => role.id === group_id)?.name || "未知";
|
|
}
|
|
|
|
// 获取用户列表
|
|
const fetchUsers = async () => {
|
|
loading.value = true;
|
|
try {
|
|
const res = await getAllUsers();
|
|
users.value = res.data.list;
|
|
} catch (e) {
|
|
users.value = [];
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
};
|
|
|
|
// 添加用户
|
|
const handleAddUser = () => {
|
|
isEdit.value = false;
|
|
editDialogVisible.value = true;
|
|
if (userEditRef.value) {
|
|
userEditRef.value.open();
|
|
}
|
|
};
|
|
|
|
// 编辑用户
|
|
const handleEdit = (user: User) => {
|
|
isEdit.value = true;
|
|
editDialogVisible.value = true;
|
|
if (userEditRef.value) {
|
|
userEditRef.value.open(user);
|
|
}
|
|
};
|
|
|
|
// 预览用户
|
|
const handlePreview = (user: User) => {
|
|
currentUser.value = user;
|
|
previewDialogVisible.value = true;
|
|
if (previewDialogRef.value) {
|
|
previewDialogRef.value.open(user);
|
|
}
|
|
};
|
|
|
|
//修改密码
|
|
const handleChangePassword = async (user: User) => {
|
|
changePasswordRef.value.open(user.id, user.account);
|
|
passwordDialogVisible.value = true;
|
|
currentUserId.value = user.id;
|
|
};
|
|
|
|
// 编辑成功回调
|
|
const handleEditSuccess = () => {
|
|
editDialogVisible.value = false;
|
|
ElMessage.success(isEdit.value ? "编辑成功" : "添加成功");
|
|
fetchUsers();
|
|
};
|
|
|
|
// 密码修改成功回调
|
|
const handlePasswordChangeSuccess = () => {
|
|
passwordDialogVisible.value = false;
|
|
ElMessage.success("密码修改成功");
|
|
};
|
|
|
|
// 分页改变
|
|
const handlePageChange = (val: number) => {
|
|
page.value = val;
|
|
fetchUsers();
|
|
};
|
|
|
|
// 删除用户
|
|
const handleDelete = async (user: User) => {
|
|
ElMessageBox.confirm("确认删除该用户?", "提示", {
|
|
confirmButtonText: "确定",
|
|
cancelButtonText: "取消",
|
|
type: "warning",
|
|
}).then(async () => {
|
|
try {
|
|
await deleteUser(user.id);
|
|
ElMessage.success("删除成功");
|
|
fetchUsers();
|
|
} catch (e) {
|
|
ElMessage.error("删除失败");
|
|
}
|
|
});
|
|
};
|
|
|
|
onMounted(async () => {
|
|
fetchUsers();
|
|
fetchRoles();
|
|
});
|
|
</script>
|
|
|
|
<style lang="less" scoped>
|
|
.card-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
|
|
span {
|
|
font-size: 1.4rem;
|
|
font-weight: 700;
|
|
}
|
|
}
|
|
|
|
:deep(.el-alert__title) {
|
|
color: #f56c6c !important;
|
|
}
|
|
|
|
.name-link {
|
|
color: #3973ff;
|
|
cursor: pointer;
|
|
text-decoration: none;
|
|
transition: color 0.3s;
|
|
|
|
&:hover {
|
|
color: #66b1ff;
|
|
text-decoration: underline;
|
|
}
|
|
}
|
|
</style>
|