feat(admin): 添加用户管理相关文件

添加用户管理视图、API和状态管理文件
This commit is contained in:
张翔
2026-03-28 14:37:29 +08:00
commit 08ea5fbe98
1643 changed files with 255646 additions and 0 deletions
@@ -0,0 +1,45 @@
/**
* 全局测试设置
* 在所有测试开始前执行
*/
import { FullConfig } from '@playwright/test';
import { testConfig } from './test-config';
import * as fs from 'fs';
import * as path from 'path';
async function globalSetup(config: FullConfig) {
console.log('\n========== E2E测试开始 ==========');
console.log(`环境: ${testConfig.getEnvironmentName()}`);
console.log(`Admin URL: ${testConfig.getConfig().baseURL}`);
console.log(`Uniapp URL: ${testConfig.getConfig().uniappBaseURL}`);
console.log(`Mock模式: ${testConfig.isMockEnabled() ? '开启' : '关闭'}`);
console.log('================================\n');
// 创建测试目录
const dirs = [
'test-results',
'test-results/screenshots',
'test-results/videos',
'test-results/traces',
'test-results/integration',
];
dirs.forEach(dir => {
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
});
// 清理旧的测试结果
try {
const files = fs.readdirSync('test-results/artifacts');
files.forEach(file => {
fs.unlinkSync(path.join('test-results/artifacts', file));
});
} catch (e) {
// 忽略清理错误
}
}
export default globalSetup;
@@ -0,0 +1,21 @@
/**
* 全局测试清理
* 在所有测试结束后执行
*/
import { FullConfig } from '@playwright/test';
async function globalTeardown(config: FullConfig) {
console.log('\n========== E2E测试结束 ==========');
// 打印报告位置
console.log('\n测试报告位置:');
console.log(' - HTML报告: test-results/html-report/index.html');
console.log(' - JSON报告: test-results/e2e-results.json');
console.log(' - JUnit报告: test-results/junit-report.xml');
console.log('\n查看HTML报告命令:');
console.log(' npx playwright show-report test-results/html-report');
console.log('================================\n');
}
export default globalTeardown;
@@ -0,0 +1,144 @@
/**
* 统一测试配置管理
* 支持多环境配置:local、dev、test、prod
*/
export interface EnvironmentConfig {
name: string;
baseURL: string;
apiBaseURL: string;
uniappBaseURL: string;
timeout: {
default: number;
navigation: number;
action: number;
};
mock: {
enabled: boolean;
mode: 'full' | 'partial' | 'none';
delay: number;
};
retry: {
count: number;
delay: number;
};
}
const environments: Record<string, EnvironmentConfig> = {
local: {
name: 'local',
baseURL: process.env.ADMIN_BASE_URL || 'http://localhost:5174',
apiBaseURL: process.env.API_BASE_URL || 'http://localhost:8080',
uniappBaseURL: process.env.UNIAPP_BASE_URL || 'http://localhost:8081',
timeout: {
default: 30000,
navigation: 30000,
action: 10000,
},
mock: {
enabled: process.env.E2E_MOCK_ENABLED === 'true',
mode: (process.env.E2E_MOCK_MODE as 'full' | 'partial' | 'none') || 'none',
delay: 0,
},
retry: {
count: process.env.CI ? 2 : 0,
delay: 1000,
},
},
dev: {
name: 'dev',
baseURL: process.env.ADMIN_BASE_URL || 'http://dev-admin.example.com',
apiBaseURL: process.env.API_BASE_URL || 'http://dev-api.example.com',
uniappBaseURL: process.env.UNIAPP_BASE_URL || 'http://dev-uniapp.example.com',
timeout: {
default: 30000,
navigation: 30000,
action: 10000,
},
mock: {
enabled: false,
mode: 'none',
delay: 0,
},
retry: {
count: 2,
delay: 1000,
},
},
test: {
name: 'test',
baseURL: process.env.ADMIN_BASE_URL || 'http://test-admin.example.com',
apiBaseURL: process.env.API_BASE_URL || 'http://test-api.example.com',
uniappBaseURL: process.env.UNIAPP_BASE_URL || 'http://test-uniapp.example.com',
timeout: {
default: 30000,
navigation: 30000,
action: 10000,
},
mock: {
enabled: false,
mode: 'none',
delay: 0,
},
retry: {
count: 2,
delay: 1000,
},
},
ci: {
name: 'ci',
baseURL: process.env.ADMIN_BASE_URL || 'http://localhost:5174',
apiBaseURL: process.env.API_BASE_URL || 'http://localhost:8080',
uniappBaseURL: process.env.UNIAPP_BASE_URL || 'http://localhost:8081',
timeout: {
default: 60000,
navigation: 60000,
action: 15000,
},
mock: {
enabled: true,
mode: 'full',
delay: 100,
},
retry: {
count: 2,
delay: 1000,
},
},
};
class TestConfigManager {
private currentEnv: string = 'local';
setEnvironment(env: string): void {
if (!environments[env]) {
throw new Error(`Unknown environment: ${env}. Available: ${Object.keys(environments).join(', ')}`);
}
this.currentEnv = env;
}
getConfig(): EnvironmentConfig {
return environments[this.currentEnv];
}
getEnvironmentName(): string {
return this.currentEnv;
}
isMockEnabled(): boolean {
return this.getConfig().mock.enabled;
}
getTimeout(type: keyof EnvironmentConfig['timeout'] = 'default'): number {
return this.getConfig().timeout[type];
}
}
export const testConfig = new TestConfigManager();
// 自动根据环境变量设置环境
if (process.env.CI) {
testConfig.setEnvironment('ci');
} else if (process.env.E2E_ENV && environments[process.env.E2E_ENV]) {
testConfig.setEnvironment(process.env.E2E_ENV);
}