feat(admin): 添加用户管理相关文件
添加用户管理视图、API和状态管理文件
This commit is contained in:
@@ -0,0 +1,303 @@
|
||||
import { Page, Route } from '@playwright/test';
|
||||
|
||||
/**
|
||||
* Mock管理器
|
||||
* 提供统一的API Mock功能
|
||||
*/
|
||||
|
||||
export interface MockConfig {
|
||||
url: string | RegExp;
|
||||
method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
|
||||
status?: number;
|
||||
body?: unknown;
|
||||
headers?: Record<string, string>;
|
||||
delay?: number;
|
||||
}
|
||||
|
||||
export class MockManager {
|
||||
private page: Page;
|
||||
private mocks: Map<string, MockConfig> = new Map();
|
||||
private isEnabled: boolean = false;
|
||||
|
||||
constructor(page: Page) {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
/**
|
||||
* 启用Mock
|
||||
*/
|
||||
enable(): void {
|
||||
this.isEnabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 禁用Mock
|
||||
*/
|
||||
disable(): void {
|
||||
this.isEnabled = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查Mock是否启用
|
||||
*/
|
||||
isMockEnabled(): boolean {
|
||||
return this.isEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加Mock配置
|
||||
*/
|
||||
addMock(config: MockConfig): void {
|
||||
const key = this.getMockKey(config.url, config.method || 'GET');
|
||||
this.mocks.set(key, config);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除Mock配置
|
||||
*/
|
||||
removeMock(url: string | RegExp, method: string = 'GET'): void {
|
||||
const key = this.getMockKey(url, method);
|
||||
this.mocks.delete(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除所有Mock
|
||||
*/
|
||||
clearMocks(): void {
|
||||
this.mocks.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用所有Mock
|
||||
*/
|
||||
async applyMocks(): Promise<void> {
|
||||
if (!this.isEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.page.route('**/*', async (route: Route) => {
|
||||
const request = route.request();
|
||||
const url = request.url();
|
||||
const method = request.method();
|
||||
|
||||
// 查找匹配的Mock配置
|
||||
for (const config of this.mocks.values()) {
|
||||
if (this.matchesUrl(url, config.url) && method === (config.method || 'GET')) {
|
||||
// 模拟延迟
|
||||
if (config.delay) {
|
||||
await new Promise(resolve => setTimeout(resolve, config.delay));
|
||||
}
|
||||
|
||||
// 返回Mock响应
|
||||
await route.fulfill({
|
||||
status: config.status || 200,
|
||||
contentType: 'application/json',
|
||||
headers: config.headers || {},
|
||||
body: JSON.stringify(config.body || {}),
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 没有匹配的Mock,继续正常请求
|
||||
await route.continue();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock登录API
|
||||
*/
|
||||
mockLogin(success: boolean = true, delay: number = 500): void {
|
||||
this.addMock({
|
||||
url: /.*\/auth\/login/,
|
||||
method: 'POST',
|
||||
status: success ? 200 : 401,
|
||||
delay,
|
||||
body: success
|
||||
? {
|
||||
token: 'mock-token-' + Date.now(),
|
||||
refreshToken: 'mock-refresh-token',
|
||||
user: {
|
||||
id: 1,
|
||||
username: 'admin',
|
||||
realName: '管理员',
|
||||
email: 'admin@example.com',
|
||||
avatar: '',
|
||||
status: 'active',
|
||||
},
|
||||
permissions: ['*'],
|
||||
}
|
||||
: {
|
||||
message: '用户名或密码错误',
|
||||
code: 401,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock用户列表API
|
||||
*/
|
||||
mockUserList(count: number = 10, delay: number = 300): void {
|
||||
const users = Array.from({ length: count }, (_, i) => ({
|
||||
id: i + 1,
|
||||
username: `user${i + 1}`,
|
||||
realName: `用户${i + 1}`,
|
||||
email: `user${i + 1}@example.com`,
|
||||
phone: `138001380${String(i).padStart(2, '0')}`,
|
||||
status: i % 3 === 0 ? 'inactive' : 'active',
|
||||
createTime: new Date().toISOString(),
|
||||
}));
|
||||
|
||||
this.addMock({
|
||||
url: /.*\/user\/list/,
|
||||
method: 'GET',
|
||||
status: 200,
|
||||
delay,
|
||||
body: {
|
||||
data: users,
|
||||
total: count,
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock角色列表API
|
||||
*/
|
||||
mockRoleList(delay: number = 300): void {
|
||||
const roles = [
|
||||
{ id: 1, roleName: '超级管理员', roleKey: 'admin', status: 'active' },
|
||||
{ id: 2, roleName: '普通用户', roleKey: 'user', status: 'active' },
|
||||
{ id: 3, roleName: '访客', roleKey: 'guest', status: 'inactive' },
|
||||
];
|
||||
|
||||
this.addMock({
|
||||
url: /.*\/role\/list/,
|
||||
method: 'GET',
|
||||
status: 200,
|
||||
delay,
|
||||
body: {
|
||||
data: roles,
|
||||
total: roles.length,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock菜单列表API
|
||||
*/
|
||||
mockMenuList(delay: number = 300): void {
|
||||
const menus = [
|
||||
{ id: 1, menuName: '仪表盘', path: '/dashboard', icon: 'DashboardOutlined', status: 'active' },
|
||||
{ id: 2, menuName: '系统管理', path: '/sys', icon: 'SettingOutlined', status: 'active' },
|
||||
{ id: 3, menuName: '用户管理', path: '/sys/user', parentId: 2, status: 'active' },
|
||||
{ id: 4, menuName: '角色管理', path: '/sys/role', parentId: 2, status: 'active' },
|
||||
];
|
||||
|
||||
this.addMock({
|
||||
url: /.*\/menu\/list/,
|
||||
method: 'GET',
|
||||
status: 200,
|
||||
delay,
|
||||
body: {
|
||||
data: menus,
|
||||
total: menus.length,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock创建操作
|
||||
*/
|
||||
mockCreate(resource: string, delay: number = 500): void {
|
||||
this.addMock({
|
||||
url: new RegExp(`.*\\/${resource}$`),
|
||||
method: 'POST',
|
||||
status: 200,
|
||||
delay,
|
||||
body: {
|
||||
message: '创建成功',
|
||||
code: 200,
|
||||
data: { id: Date.now() },
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock更新操作
|
||||
*/
|
||||
mockUpdate(resource: string, delay: number = 500): void {
|
||||
this.addMock({
|
||||
url: new RegExp(`.*\\/${resource}\\/.*`),
|
||||
method: 'PUT',
|
||||
status: 200,
|
||||
delay,
|
||||
body: {
|
||||
message: '更新成功',
|
||||
code: 200,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock删除操作
|
||||
*/
|
||||
mockDelete(resource: string, delay: number = 500): void {
|
||||
this.addMock({
|
||||
url: new RegExp(`.*\\/${resource}\\/.*`),
|
||||
method: 'DELETE',
|
||||
status: 200,
|
||||
delay,
|
||||
body: {
|
||||
message: '删除成功',
|
||||
code: 200,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock错误响应
|
||||
*/
|
||||
mockError(url: string | RegExp, status: number = 500, message: string = '服务器错误'): void {
|
||||
this.addMock({
|
||||
url,
|
||||
method: 'GET',
|
||||
status,
|
||||
body: {
|
||||
message,
|
||||
code: status,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock网络延迟
|
||||
*/
|
||||
mockDelay(url: string | RegExp, delay: number = 2000): void {
|
||||
this.addMock({
|
||||
url,
|
||||
method: 'GET',
|
||||
delay,
|
||||
body: {},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Mock键
|
||||
*/
|
||||
private getMockKey(url: string | RegExp, method: string): string {
|
||||
const urlStr = url instanceof RegExp ? url.source : url;
|
||||
return `${method}:${urlStr}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查URL是否匹配
|
||||
*/
|
||||
private matchesUrl(actualUrl: string, configUrl: string | RegExp): boolean {
|
||||
if (configUrl instanceof RegExp) {
|
||||
return configUrl.test(actualUrl);
|
||||
}
|
||||
return actualUrl.includes(configUrl);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user