08ea5fbe98
添加用户管理视图、API和状态管理文件
211 lines
6.1 KiB
TypeScript
211 lines
6.1 KiB
TypeScript
import { randomBytes } from 'crypto';
|
|
|
|
export interface UserData {
|
|
username: string;
|
|
password: string;
|
|
email: string;
|
|
phone: string;
|
|
realName: string;
|
|
status: 'active' | 'inactive' | 'locked';
|
|
roleIds: number[];
|
|
}
|
|
|
|
export interface RoleData {
|
|
name: string;
|
|
code: string;
|
|
description: string;
|
|
status: 'active' | 'inactive';
|
|
permissions: string[];
|
|
}
|
|
|
|
export interface MenuData {
|
|
name: string;
|
|
code: string;
|
|
path: string;
|
|
icon: string;
|
|
parentId: number;
|
|
sortOrder: number;
|
|
status: 'active' | 'inactive';
|
|
}
|
|
|
|
export interface PermissionData {
|
|
name: string;
|
|
code: string;
|
|
description: string;
|
|
type: 'menu' | 'button' | 'api';
|
|
parentId: number;
|
|
}
|
|
|
|
class TestDataGenerator {
|
|
private static instance: TestDataGenerator;
|
|
|
|
private constructor() {}
|
|
|
|
static getInstance(): TestDataGenerator {
|
|
if (!TestDataGenerator.instance) {
|
|
TestDataGenerator.instance = new TestDataGenerator();
|
|
}
|
|
return TestDataGenerator.instance;
|
|
}
|
|
|
|
randomString(length: number = 10): string {
|
|
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
let result = '';
|
|
for (let i = 0; i < length; i++) {
|
|
result += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
randomEmail(): string {
|
|
const domains = ['example.com', 'test.com', 'demo.com'];
|
|
const username = this.randomString(8).toLowerCase();
|
|
const domain = domains[Math.floor(Math.random() * domains.length)];
|
|
return `${username}@${domain}`;
|
|
}
|
|
|
|
randomPhone(): string {
|
|
const prefix = ['138', '139', '150', '186', '188'];
|
|
const selectedPrefix = prefix[Math.floor(Math.random() * prefix.length)];
|
|
const suffix = Math.floor(Math.random() * 100000000).toString().padStart(8, '0');
|
|
return `${selectedPrefix}${suffix}`;
|
|
}
|
|
|
|
randomPassword(length: number = 12): string {
|
|
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*';
|
|
let result = '';
|
|
for (let i = 0; i < length; i++) {
|
|
result += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
randomInt(min: number, max: number): number {
|
|
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
}
|
|
|
|
randomBoolean(): boolean {
|
|
return Math.random() < 0.5;
|
|
}
|
|
|
|
randomDate(startYear: number = 2020, endYear: number = 2024): Date {
|
|
const start = new Date(startYear, 0, 1);
|
|
const end = new Date(endYear, 11, 31);
|
|
return new Date(start.getTime() + Math.random() * (end.getTime() - start.getTime()));
|
|
}
|
|
|
|
randomItem<T>(items: T[]): T {
|
|
return items[Math.floor(Math.random() * items.length)];
|
|
}
|
|
|
|
randomItems<T>(items: T[], count: number): T[] {
|
|
const shuffled = [...items].sort(() => Math.random() - 0.5);
|
|
return shuffled.slice(0, Math.min(count, items.length));
|
|
}
|
|
|
|
generateUserData(overrides: Partial<UserData> = {}): UserData {
|
|
const username = overrides.username || `user_${this.randomString(6).toLowerCase()}`;
|
|
|
|
return {
|
|
username,
|
|
password: overrides.password || 'Admin@123',
|
|
email: overrides.email || this.randomEmail(),
|
|
phone: overrides.phone || this.randomPhone(),
|
|
realName: overrides.realName || `测试用户${this.randomInt(1, 100)}`,
|
|
status: overrides.status || this.randomItem(['active', 'inactive', 'locked']),
|
|
roleIds: overrides.roleIds || [1]
|
|
};
|
|
}
|
|
|
|
generateRoleData(overrides: Partial<RoleData> = {}): RoleData {
|
|
const code = overrides.code || `role_${this.randomString(6).toLowerCase()}`;
|
|
|
|
return {
|
|
name: overrides.name || `测试角色${this.randomInt(1, 100)}`,
|
|
code,
|
|
description: overrides.description || `角色${code}的描述`,
|
|
status: overrides.status || this.randomItem(['active', 'inactive']),
|
|
permissions: overrides.permissions || ['dashboard:view']
|
|
};
|
|
}
|
|
|
|
generateMenuData(overrides: Partial<MenuData> = {}): MenuData {
|
|
const code = overrides.code || `menu_${this.randomString(6).toLowerCase()}`;
|
|
|
|
return {
|
|
name: overrides.name || `测试菜单${this.randomInt(1, 100)}`,
|
|
code,
|
|
path: overrides.path || `/${code}`,
|
|
icon: overrides.icon || 'MenuOutlined',
|
|
parentId: overrides.parentId || 0,
|
|
sortOrder: overrides.sortOrder || this.randomInt(1, 100),
|
|
status: overrides.status || this.randomItem(['active', 'inactive'])
|
|
};
|
|
}
|
|
|
|
generatePermissionData(overrides: Partial<PermissionData> = {}): PermissionData {
|
|
const code = overrides.code || `perm_${this.randomString(6).toLowerCase()}`;
|
|
|
|
return {
|
|
name: overrides.name || `测试权限${this.randomInt(1, 100)}`,
|
|
code,
|
|
description: overrides.description || `权限${code}的描述`,
|
|
type: overrides.type || this.randomItem(['menu', 'button', 'api']),
|
|
parentId: overrides.parentId || 0
|
|
};
|
|
}
|
|
|
|
generateUserList(count: number): UserData[] {
|
|
return Array.from({ length: count }, () => this.generateUserData());
|
|
}
|
|
|
|
generateRoleList(count: number): RoleData[] {
|
|
return Array.from({ length: count }, () => this.generateRoleData());
|
|
}
|
|
|
|
generateMenuList(count: number): MenuData[] {
|
|
return Array.from({ length: count }, () => this.generateMenuData());
|
|
}
|
|
|
|
generatePermissionList(count: number): PermissionData[] {
|
|
return Array.from({ length: count }, () => this.generatePermissionData());
|
|
}
|
|
|
|
generatePaginationData<T>(data: T[], page: number = 1, pageSize: number = 10) {
|
|
const start = (page - 1) * pageSize;
|
|
const end = start + pageSize;
|
|
|
|
return {
|
|
records: data.slice(start, end),
|
|
total: data.length,
|
|
page,
|
|
pageSize,
|
|
totalPages: Math.ceil(data.length / pageSize)
|
|
};
|
|
}
|
|
|
|
generateSearchQuery(keyword: string): Record<string, any> {
|
|
return {
|
|
keyword,
|
|
page: 1,
|
|
pageSize: 10
|
|
};
|
|
}
|
|
|
|
generateFormData(fields: Record<string, any>): Record<string, any> {
|
|
const formData: Record<string, any> = {};
|
|
|
|
for (const [key, value] of Object.entries(fields)) {
|
|
if (typeof value === 'function') {
|
|
formData[key] = value();
|
|
} else {
|
|
formData[key] = value;
|
|
}
|
|
}
|
|
|
|
return formData;
|
|
}
|
|
}
|
|
|
|
export const testDataGenerator = TestDataGenerator.getInstance();
|