diff --git a/backend/database/roles_init.sql b/backend/database/roles_init.sql
new file mode 100644
index 0000000..c83e94a
--- /dev/null
+++ b/backend/database/roles_init.sql
@@ -0,0 +1,123 @@
+-- ============================================
+-- 梦幻西游一站式运营管理平台 - 角色表初始化脚本
+-- MySQL 8.4 兼容版本
+-- 创建日期:2026-01-04
+-- ============================================
+
+-- 使用数据库
+USE mhxy_web_vue;
+
+-- 设置字符集
+SET NAMES utf8mb4;
+SET FOREIGN_KEY_CHECKS = 0;
+
+-- ============================================
+-- 表:admin_roles(管理员角色表)
+-- ============================================
+DROP TABLE IF EXISTS `admin_roles`;
+CREATE TABLE `admin_roles` (
+ `id` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `role_name` VARCHAR(50) NOT NULL COMMENT '角色名称',
+ `role_code` VARCHAR(50) NOT NULL COMMENT '角色编码',
+ `description` VARCHAR(255) NULL COMMENT '角色描述',
+ `status` TINYINT NOT NULL DEFAULT 1 COMMENT '状态(1:正常, 0:禁用)',
+ `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ PRIMARY KEY (`id`),
+ UNIQUE INDEX `idx_role_code` (`role_code`),
+ INDEX `idx_status` (`status`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='管理员角色表';
+
+-- ============================================
+-- 插入默认角色数据
+-- ============================================
+INSERT INTO `admin_roles` (`role_name`, `role_code`, `description`, `status`)
+VALUES
+ ('超级管理员', 'super_admin', '拥有系统所有权限', 1),
+ ('系统管理员', 'system_admin', '管理系统配置和用户', 1),
+ ('运营管理员', 'operation_admin', '负责运营相关功能', 1),
+ ('数据管理员', 'data_admin', '负责数据查询和导出', 1);
+
+-- ============================================
+-- 修改 admin_users 表的 role_id 字段类型为 INT UNSIGNED
+-- ============================================
+ALTER TABLE `admin_users`
+MODIFY COLUMN `role_id` INT UNSIGNED NOT NULL DEFAULT 1 COMMENT '角色ID(1:超级管理员)';
+
+-- ============================================
+-- 删除 admin_users 表上的外键约束(如果存在)
+-- ============================================
+-- 创建存储过程来删除外键
+DROP PROCEDURE IF EXISTS drop_foreign_key_if_exists;
+
+DELIMITER $$
+CREATE PROCEDURE drop_foreign_key_if_exists()
+BEGIN
+ DECLARE fk_name VARCHAR(64);
+
+ -- 查询外键名称
+ SELECT CONSTRAINT_NAME INTO fk_name
+ FROM information_schema.KEY_COLUMN_USAGE
+ WHERE TABLE_SCHEMA = 'mhxy_web_vue'
+ AND TABLE_NAME = 'admin_users'
+ AND CONSTRAINT_NAME = 'fk_admin_users_role_id'
+ AND REFERENCED_TABLE_NAME = 'admin_roles';
+
+ -- 如果外键存在,则删除
+ IF fk_name IS NOT NULL THEN
+ SET @sql = CONCAT('ALTER TABLE `admin_users` DROP FOREIGN KEY `', fk_name, '`');
+ PREPARE stmt FROM @sql;
+ EXECUTE stmt;
+ DEALLOCATE PREPARE stmt;
+ END IF;
+END$$
+DELIMITER ;
+
+-- 执行存储过程
+CALL drop_foreign_key_if_exists();
+
+-- 删除存储过程
+DROP PROCEDURE IF EXISTS drop_foreign_key_if_exists;
+
+-- ============================================
+-- 添加外键约束
+-- ============================================
+ALTER TABLE `admin_users`
+ADD CONSTRAINT `fk_admin_users_role_id`
+FOREIGN KEY (`role_id`) REFERENCES `admin_roles` (`id`)
+ON DELETE RESTRICT
+ON UPDATE CASCADE;
+
+-- ============================================
+-- 更新现有管理员账号的角色ID
+-- ============================================
+UPDATE `admin_users`
+SET `role_id` = 1
+WHERE `username` = 'admin';
+
+-- ============================================
+-- 验证数据
+-- ============================================
+SELECT
+ id,
+ role_name,
+ role_code,
+ description,
+ status,
+ created_at
+FROM admin_roles;
+
+SELECT
+ au.id,
+ au.username,
+ au.real_name,
+ au.role_id,
+ ar.role_name,
+ au.status,
+ au.created_at
+FROM admin_users au
+LEFT JOIN admin_roles ar ON au.role_id = ar.id;
+
+SET FOREIGN_KEY_CHECKS = 1;
+
+-- 初始化完成
diff --git a/backend/src/controllers/adminRoleController.ts b/backend/src/controllers/adminRoleController.ts
new file mode 100644
index 0000000..550c3e8
--- /dev/null
+++ b/backend/src/controllers/adminRoleController.ts
@@ -0,0 +1,257 @@
+// 导入Express的Request和Response类型
+import { Request, Response } from 'express';
+// 导入数据源配置
+import { AppDataSource } from '../config/database';
+// 导入角色模型
+import { AdminRole } from '../models/AdminRole';
+
+/**
+ * 角色控制器
+ * 处理角色管理相关的操作,包括角色列表查询、创建、编辑、删除等
+ */
+export class AdminRoleController {
+ /**
+ * 获取角色列表
+ * 获取所有角色列表,支持按状态筛选
+ * @param req - Express请求对象,包含查询参数
+ * @param res - Express响应对象
+ */
+ async getRoleList(req: Request, res: Response) {
+ try {
+ // 从查询参数中获取状态筛选条件
+ const { status } = req.query;
+
+ // 获取角色仓库
+ const roleRepository = AppDataSource.getRepository(AdminRole);
+
+ // 构建查询条件
+ const queryBuilder = roleRepository.createQueryBuilder('role');
+
+ // 按状态筛选
+ if (status !== undefined && status !== null && status !== '') {
+ queryBuilder.andWhere('role.status = :status', { status: Number(status) });
+ }
+
+ // 查询角色列表
+ const roles = await queryBuilder.orderBy('role.id', 'ASC').getMany();
+
+ // 组装返回数据
+ const roleList = roles.map(role => ({
+ id: role.id,
+ roleName: role.roleName,
+ description: role.description,
+ status: role.status,
+ createdAt: role.createdAt,
+ updatedAt: role.updatedAt
+ }));
+
+ // 返回角色列表
+ return res.json({
+ success: true,
+ data: roleList
+ });
+ } catch (error) {
+ console.error('获取角色列表失败:', error);
+ return res.status(500).json({
+ success: false,
+ message: '服务器内部错误'
+ });
+ }
+ }
+
+ /**
+ * 创建角色
+ * 创建新的角色
+ * @param req - Express请求对象,包含角色信息
+ * @param res - Express响应对象
+ */
+ async createRole(req: Request, res: Response) {
+ try {
+ // 从请求体中获取角色信息
+ const { roleName, description } = req.body;
+
+ // 验证必填字段
+ if (!roleName) {
+ return res.status(400).json({
+ success: false,
+ message: '角色名称不能为空'
+ });
+ }
+
+ // 获取角色仓库
+ const roleRepository = AppDataSource.getRepository(AdminRole);
+
+ // 检查角色名称是否已存在
+ const existingRole = await roleRepository.findOne({
+ where: { roleName }
+ });
+
+ if (existingRole) {
+ return res.status(400).json({
+ success: false,
+ message: '角色名称已存在'
+ });
+ }
+
+ // 创建新角色
+ const newRole = roleRepository.create({
+ roleName,
+ description,
+ status: 1 // 默认启用
+ });
+
+ // 保存角色
+ await roleRepository.save(newRole);
+
+ // 返回创建成功响应
+ return res.json({
+ success: true,
+ message: '创建角色成功',
+ data: {
+ id: newRole.id,
+ roleName: newRole.roleName
+ }
+ });
+ } catch (error) {
+ console.error('创建角色失败:', error);
+ return res.status(500).json({
+ success: false,
+ message: '服务器内部错误'
+ });
+ }
+ }
+
+ /**
+ * 编辑角色
+ * 更新角色信息
+ * @param req - Express请求对象,包含角色ID和更新信息
+ * @param res - Express响应对象
+ */
+ async updateRole(req: Request, res: Response) {
+ try {
+ // 从请求参数中获取角色ID
+ const { id } = req.params;
+ // 从请求体中获取更新信息
+ const { roleName, description, status } = req.body;
+
+ // 验证必填字段
+ if (!roleName) {
+ return res.status(400).json({
+ success: false,
+ message: '角色名称不能为空'
+ });
+ }
+
+ // 获取角色仓库
+ const roleRepository = AppDataSource.getRepository(AdminRole);
+
+ // 查找角色
+ const role = await roleRepository.findOne({
+ where: { id: Number(id) }
+ });
+
+ if (!role) {
+ return res.status(404).json({
+ success: false,
+ message: '角色不存在'
+ });
+ }
+
+ // 检查角色名称是否与其他角色重复
+ const existingRole = await roleRepository.findOne({
+ where: { roleName }
+ });
+
+ if (existingRole && existingRole.id !== role.id) {
+ return res.status(400).json({
+ success: false,
+ message: '角色名称已存在'
+ });
+ }
+
+ // 更新角色信息
+ role.roleName = roleName;
+ role.description = description;
+ role.status = status !== undefined ? Number(status) : role.status;
+
+ // 保存更新
+ await roleRepository.save(role);
+
+ // 返回更新成功响应
+ return res.json({
+ success: true,
+ message: '更新角色成功',
+ data: {
+ id: role.id,
+ roleName: role.roleName
+ }
+ });
+ } catch (error) {
+ console.error('更新角色失败:', error);
+ return res.status(500).json({
+ success: false,
+ message: '服务器内部错误'
+ });
+ }
+ }
+
+ /**
+ * 删除角色
+ * 删除指定的角色
+ * 禁止删除默认的超级管理员角色(ID=1)
+ * @param req - Express请求对象,包含角色ID
+ * @param res - Express响应对象
+ */
+ async deleteRole(req: Request, res: Response) {
+ try {
+ // 从请求参数中获取角色ID
+ const { id } = req.params;
+
+ // 验证角色ID
+ if (!id) {
+ return res.status(400).json({
+ success: false,
+ message: '角色ID不能为空'
+ });
+ }
+
+ // 禁止删除默认的超级管理员角色(ID=1)
+ if (Number(id) === 1) {
+ return res.status(403).json({
+ success: false,
+ message: '禁止删除默认的超级管理员角色'
+ });
+ }
+
+ // 获取角色仓库
+ const roleRepository = AppDataSource.getRepository(AdminRole);
+
+ // 查找角色
+ const role = await roleRepository.findOne({
+ where: { id: Number(id) }
+ });
+
+ if (!role) {
+ return res.status(404).json({
+ success: false,
+ message: '角色不存在'
+ });
+ }
+
+ // 删除角色
+ await roleRepository.remove(role);
+
+ // 返回删除成功响应
+ return res.json({
+ success: true,
+ message: '删除角色成功'
+ });
+ } catch (error) {
+ console.error('删除角色失败:', error);
+ return res.status(500).json({
+ success: false,
+ message: '服务器内部错误'
+ });
+ }
+ }
+}
diff --git a/backend/src/controllers/adminUserController.ts b/backend/src/controllers/adminUserController.ts
new file mode 100644
index 0000000..9a8b94f
--- /dev/null
+++ b/backend/src/controllers/adminUserController.ts
@@ -0,0 +1,336 @@
+// 导入Express的Request和Response类型
+import { Request, Response } from 'express';
+// 导入bcrypt用于密码加密
+import bcrypt from 'bcrypt';
+// 导入数据源配置
+import { AppDataSource } from '../config/database';
+// 导入管理员用户模型
+import { AdminUser } from '../models/AdminUser';
+// 导入角色模型
+import { AdminRole } from '../models/AdminRole';
+
+/**
+ * 管理员用户控制器
+ * 处理用户管理相关的操作,包括用户列表查询、创建、编辑、删除等
+ */
+export class AdminUserController {
+ /**
+ * 获取用户列表
+ * 支持按用户名、角色ID、状态进行筛选,支持分页
+ * @param req - Express请求对象,包含查询参数
+ * @param res - Express响应对象
+ */
+ async getUserList(req: Request, res: Response) {
+ try {
+ // 从查询参数中获取筛选条件和分页参数
+ const { username, roleId, status, page = 1, pageSize = 20 } = req.query;
+
+ // 获取管理员用户仓库
+ const adminUserRepository = AppDataSource.getRepository(AdminUser);
+ // 获取角色仓库
+ const roleRepository = AppDataSource.getRepository(AdminRole);
+
+ // 构建查询条件
+ const queryBuilder = adminUserRepository.createQueryBuilder('user');
+
+ // 按用户名筛选(模糊查询)
+ if (username) {
+ queryBuilder.andWhere('user.username LIKE :username', { username: `%${username}%` });
+ }
+
+ // 按角色ID筛选
+ if (roleId) {
+ queryBuilder.andWhere('user.roleId = :roleId', { roleId: Number(roleId) });
+ }
+
+ // 按状态筛选
+ if (status !== undefined && status !== null && status !== '') {
+ queryBuilder.andWhere('user.status = :status', { status: Number(status) });
+ }
+
+ // 计算总数
+ const total = await queryBuilder.getCount();
+
+ // 分页查询
+ const users = await queryBuilder
+ .orderBy('user.id', 'DESC')
+ .skip((Number(page) - 1) * Number(pageSize))
+ .take(Number(pageSize))
+ .getMany();
+
+ // 获取所有角色信息(用于显示角色名称)
+ const roles = await roleRepository.find();
+
+ // 构建角色ID到角色名称的映射
+ const roleMap = new Map(roles.map(role => [role.id, role.roleName]));
+
+ // 组装返回数据
+ const userList = users.map(user => ({
+ id: user.id,
+ username: user.username,
+ realName: user.realName,
+ roleId: user.roleId,
+ roleName: roleMap.get(user.roleId) || '未知角色',
+ status: user.status,
+ createdAt: user.createdAt,
+ updatedAt: user.updatedAt
+ }));
+
+ // 返回用户列表
+ return res.json({
+ success: true,
+ data: {
+ list: userList,
+ total,
+ page: Number(page),
+ pageSize: Number(pageSize)
+ }
+ });
+ } catch (error) {
+ console.error('获取用户列表失败:', error);
+ return res.status(500).json({
+ success: false,
+ message: '服务器内部错误'
+ });
+ }
+ }
+
+ /**
+ * 创建用户
+ * 创建新的管理员用户
+ * @param req - Express请求对象,包含用户信息
+ * @param res - Express响应对象
+ */
+ async createUser(req: Request, res: Response) {
+ try {
+ // 从请求体中获取用户信息
+ const { username, password, roleId } = req.body;
+
+ // 验证必填字段
+ if (!username || !password || !roleId) {
+ return res.status(400).json({
+ success: false,
+ message: '用户名、密码和角色组不能为空'
+ });
+ }
+
+ // 获取管理员用户仓库
+ const adminUserRepository = AppDataSource.getRepository(AdminUser);
+
+ // 检查用户名是否已存在
+ const existingUser = await adminUserRepository.findOne({
+ where: { username }
+ });
+
+ if (existingUser) {
+ return res.status(400).json({
+ success: false,
+ message: '用户名已存在'
+ });
+ }
+
+ // 密码加密
+ const passwordHash = await bcrypt.hash(password, 10);
+
+ // 创建新用户
+ const newUser = adminUserRepository.create({
+ username,
+ passwordHash,
+ roleId: Number(roleId),
+ status: 1 // 默认启用
+ });
+
+ // 保存用户
+ await adminUserRepository.save(newUser);
+
+ // 返回创建成功响应
+ return res.json({
+ success: true,
+ message: '创建用户成功',
+ data: {
+ id: newUser.id,
+ username: newUser.username,
+ roleId: newUser.roleId
+ }
+ });
+ } catch (error) {
+ console.error('创建用户失败:', error);
+ return res.status(500).json({
+ success: false,
+ message: '服务器内部错误'
+ });
+ }
+ }
+
+ /**
+ * 编辑用户
+ * 更新用户信息(密码和角色)
+ * @param req - Express请求对象,包含用户ID和更新信息
+ * @param res - Express响应对象
+ */
+ async updateUser(req: Request, res: Response) {
+ try {
+ // 从请求参数中获取用户ID
+ const { id } = req.params;
+ // 从请求体中获取更新信息
+ const { password, roleId } = req.body;
+
+ // 验证必填字段
+ if (!roleId) {
+ return res.status(400).json({
+ success: false,
+ message: '角色组不能为空'
+ });
+ }
+
+ // 获取管理员用户仓库
+ const adminUserRepository = AppDataSource.getRepository(AdminUser);
+
+ // 查找用户
+ const user = await adminUserRepository.findOne({
+ where: { id: Number(id) }
+ });
+
+ if (!user) {
+ return res.status(404).json({
+ success: false,
+ message: '用户不存在'
+ });
+ }
+
+ // 更新角色
+ user.roleId = Number(roleId);
+
+ // 如果提供了新密码,则更新密码
+ if (password) {
+ user.passwordHash = await bcrypt.hash(password, 10);
+ }
+
+ // 保存更新
+ await adminUserRepository.save(user);
+
+ // 返回更新成功响应
+ return res.json({
+ success: true,
+ message: '更新用户成功',
+ data: {
+ id: user.id,
+ username: user.username,
+ roleId: user.roleId
+ }
+ });
+ } catch (error) {
+ console.error('更新用户失败:', error);
+ return res.status(500).json({
+ success: false,
+ message: '服务器内部错误'
+ });
+ }
+ }
+
+ /**
+ * 删除用户
+ * 删除指定的管理员用户
+ * 禁止删除当前登录的管理员账号和默认的超级管理员账号(ID=1)
+ * @param req - Express请求对象,包含用户ID和当前登录用户信息
+ * @param res - Express响应对象
+ */
+ async deleteUser(req: any, res: Response) {
+ try {
+ // 从请求参数中获取用户ID
+ const { id } = req.params;
+
+ // 验证用户ID
+ if (!id) {
+ return res.status(400).json({
+ success: false,
+ message: '用户ID不能为空'
+ });
+ }
+
+ // 禁止删除默认的超级管理员账号(ID=1)
+ if (Number(id) === 1) {
+ return res.status(403).json({
+ success: false,
+ message: '禁止删除默认的超级管理员账号'
+ });
+ }
+
+ // 禁止删除当前登录的管理员账号
+ if (Number(id) === req.admin.id) {
+ return res.status(403).json({
+ success: false,
+ message: '禁止删除当前登录的账号'
+ });
+ }
+
+ // 获取管理员用户仓库
+ const adminUserRepository = AppDataSource.getRepository(AdminUser);
+
+ // 查找用户
+ const user = await adminUserRepository.findOne({
+ where: { id: Number(id) }
+ });
+
+ if (!user) {
+ return res.status(404).json({
+ success: false,
+ message: '用户不存在'
+ });
+ }
+
+ // 删除用户
+ await adminUserRepository.remove(user);
+
+ // 返回删除成功响应
+ return res.json({
+ success: true,
+ message: '删除用户成功'
+ });
+ } catch (error) {
+ console.error('删除用户失败:', error);
+ return res.status(500).json({
+ success: false,
+ message: '服务器内部错误'
+ });
+ }
+ }
+
+ /**
+ * 获取角色列表
+ * 获取所有启用的角色列表,用于下拉选择
+ * @param req - Express请求对象
+ * @param res - Express响应对象
+ */
+ async getRoleList(req: Request, res: Response) {
+ try {
+ // 获取角色仓库
+ const roleRepository = AppDataSource.getRepository(AdminRole);
+
+ // 查询所有启用的角色
+ const roles = await roleRepository.find({
+ where: { status: 1 },
+ order: { id: 'ASC' }
+ });
+
+ // 组装返回数据
+ const roleList = roles.map(role => ({
+ id: role.id,
+ roleName: role.roleName,
+ description: role.description
+ }));
+
+ // 返回角色列表
+ return res.json({
+ success: true,
+ data: roleList
+ });
+ } catch (error) {
+ console.error('获取角色列表失败:', error);
+ return res.status(500).json({
+ success: false,
+ message: '服务器内部错误'
+ });
+ }
+ }
+}
diff --git a/backend/src/index.ts b/backend/src/index.ts
index f2599d4..e7a0b77 100644
--- a/backend/src/index.ts
+++ b/backend/src/index.ts
@@ -11,7 +11,7 @@ const app: Express = express();
const PORT = process.env.PORT || 3000;
app.use(cors({
- origin: process.env.CORS_ORIGIN || 'http://localhost:5173',
+ origin: ['http://localhost:5173', 'http://localhost:5174'],
credentials: true
}));
diff --git a/backend/src/models/AdminRole.ts b/backend/src/models/AdminRole.ts
new file mode 100644
index 0000000..b0f3eb6
--- /dev/null
+++ b/backend/src/models/AdminRole.ts
@@ -0,0 +1,23 @@
+import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn } from 'typeorm';
+
+// 角色实体模型
+@Entity('admin_roles')
+export class AdminRole {
+ @PrimaryGeneratedColumn('increment')
+ id: number;
+
+ @Column({ type: 'varchar', length: 50, unique: true, name: 'role_name' })
+ roleName: string;
+
+ @Column({ type: 'varchar', length: 255, nullable: true })
+ description: string;
+
+ @Column({ type: 'tinyint', default: 1 })
+ status: number;
+
+ @CreateDateColumn({ name: 'created_at' })
+ createdAt: Date;
+
+ @UpdateDateColumn({ name: 'updated_at' })
+ updatedAt: Date;
+}
diff --git a/backend/src/routes/adminRoutes.ts b/backend/src/routes/adminRoutes.ts
index 4630f55..ee07466 100644
--- a/backend/src/routes/adminRoutes.ts
+++ b/backend/src/routes/adminRoutes.ts
@@ -1,14 +1,30 @@
import { Router } from 'express';
import { AdminAuthController } from '../controllers/adminAuthController';
+import { AdminUserController } from '../controllers/adminUserController';
+import { AdminRoleController } from '../controllers/adminRoleController';
import { adminAuthMiddleware, AuthRequest } from '../middleware/adminAuth';
const router = Router();
const adminAuthController = new AdminAuthController();
+const adminUserController = new AdminUserController();
+const adminRoleController = new AdminRoleController();
+// 认证相关路由
router.post('/login', (req, res) => adminAuthController.login(req, res));
-
router.post('/logout', (req, res) => adminAuthController.logout(req, res));
-
router.get('/me', adminAuthMiddleware, (req: AuthRequest, res) => adminAuthController.getCurrentUser(req, res));
+// 用户管理路由(需要认证)
+router.get('/users', adminAuthMiddleware, (req: AuthRequest, res) => adminUserController.getUserList(req, res));
+router.post('/users', adminAuthMiddleware, (req: AuthRequest, res) => adminUserController.createUser(req, res));
+router.put('/users/:id', adminAuthMiddleware, (req: AuthRequest, res) => adminUserController.updateUser(req, res));
+router.delete('/users/:id', adminAuthMiddleware, (req: AuthRequest, res) => adminUserController.deleteUser(req, res));
+router.get('/roles/list', adminAuthMiddleware, (req: AuthRequest, res) => adminUserController.getRoleList(req, res));
+
+// 角色管理路由(需要认证)
+router.get('/roles', adminAuthMiddleware, (req: AuthRequest, res) => adminRoleController.getRoleList(req, res));
+router.post('/roles', adminAuthMiddleware, (req: AuthRequest, res) => adminRoleController.createRole(req, res));
+router.put('/roles/:id', adminAuthMiddleware, (req: AuthRequest, res) => adminRoleController.updateRole(req, res));
+router.delete('/roles/:id', adminAuthMiddleware, (req: AuthRequest, res) => adminRoleController.deleteRole(req, res));
+
export default router;
diff --git a/frontend/src/App.vue b/frontend/src/App.vue
index bb6cee8..6fbc901 100644
--- a/frontend/src/App.vue
+++ b/frontend/src/App.vue
@@ -1,13 +1,15 @@
-
+
+
+
+
+
diff --git a/frontend/src/views/admin/components/UserFormModal.vue b/frontend/src/views/admin/components/UserFormModal.vue
new file mode 100644
index 0000000..5c5a8ab
--- /dev/null
+++ b/frontend/src/views/admin/components/UserFormModal.vue
@@ -0,0 +1,199 @@
+
+
+
+
+
+
+
+
+
+
+
+ 生成随机密码
+
+
+
+
+
+
+
+
+
+
+
+ 取消
+
+ 确定
+
+
+
+
+
+
+
+
+
diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts
index 98b82d1..70b9b1d 100644
--- a/frontend/vite.config.ts
+++ b/frontend/vite.config.ts
@@ -9,5 +9,13 @@ export default defineConfig({
alias: {
'@': path.resolve(__dirname, './src')
}
+ },
+ server: {
+ proxy: {
+ '/api': {
+ target: 'http://localhost:3000',
+ changeOrigin: true
+ }
+ }
}
})