feat(admin): 添加用户管理相关文件
添加用户管理视图、API和状态管理文件
This commit is contained in:
@@ -0,0 +1,155 @@
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
export interface TestResult {
|
||||
testId: string;
|
||||
testName: string;
|
||||
status: 'passed' | 'failed' | 'skipped';
|
||||
duration: number;
|
||||
error?: string;
|
||||
stackTrace?: string;
|
||||
retries: number;
|
||||
timestamp: string;
|
||||
}
|
||||
|
||||
export interface TestSuite {
|
||||
suiteId: string;
|
||||
suiteName: string;
|
||||
tests: TestResult[];
|
||||
duration: number;
|
||||
passed: number;
|
||||
failed: number;
|
||||
skipped: number;
|
||||
timestamp: string;
|
||||
}
|
||||
|
||||
export interface TestReport {
|
||||
reportId: string;
|
||||
reportName: string;
|
||||
testSuites: TestSuite[];
|
||||
totalTests: number;
|
||||
totalPassed: number;
|
||||
totalFailed: number;
|
||||
totalSkipped: number;
|
||||
totalDuration: number;
|
||||
passRate: number;
|
||||
timestamp: string;
|
||||
environment: {
|
||||
node: string;
|
||||
platform: string;
|
||||
ci: boolean;
|
||||
};
|
||||
metadata?: Record<string, any>;
|
||||
}
|
||||
|
||||
export interface TrendData {
|
||||
date: string;
|
||||
totalTests: number;
|
||||
passed: number;
|
||||
failed: number;
|
||||
skipped: number;
|
||||
passRate: number;
|
||||
duration: number;
|
||||
}
|
||||
|
||||
export interface ReportGeneratorOptions {
|
||||
outputDir: string;
|
||||
reportName: string;
|
||||
includeTrend?: boolean;
|
||||
trendDataDays?: number;
|
||||
}
|
||||
|
||||
export abstract class BaseReportGenerator {
|
||||
protected outputDir: string;
|
||||
protected reportName: string;
|
||||
|
||||
constructor(options: ReportGeneratorOptions) {
|
||||
this.outputDir = options.outputDir;
|
||||
this.reportName = options.reportName;
|
||||
this.ensureOutputDir();
|
||||
}
|
||||
|
||||
protected ensureOutputDir(): void {
|
||||
if (!fs.existsSync(this.outputDir)) {
|
||||
fs.mkdirSync(this.outputDir, { recursive: true });
|
||||
}
|
||||
}
|
||||
|
||||
abstract generate(report: TestReport): string;
|
||||
|
||||
abstract getExtension(): string;
|
||||
|
||||
protected getOutputPath(): string {
|
||||
return path.join(this.outputDir, `${this.reportName}.${this.getExtension()}`);
|
||||
}
|
||||
|
||||
protected writeToFile(content: string): string {
|
||||
const outputPath = this.getOutputPath();
|
||||
fs.writeFileSync(outputPath, content, 'utf-8');
|
||||
return outputPath;
|
||||
}
|
||||
|
||||
protected formatDuration(ms: number): string {
|
||||
if (ms < 1000) {
|
||||
return `${ms}ms`;
|
||||
} else if (ms < 60000) {
|
||||
return `${(ms / 1000).toFixed(2)}s`;
|
||||
} else {
|
||||
const minutes = Math.floor(ms / 60000);
|
||||
const seconds = ((ms % 60000) / 1000).toFixed(0);
|
||||
return `${minutes}m ${seconds}s`;
|
||||
}
|
||||
}
|
||||
|
||||
protected formatTimestamp(timestamp: string): string {
|
||||
const date = new Date(timestamp);
|
||||
return date.toLocaleString('zh-CN', {
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit',
|
||||
});
|
||||
}
|
||||
|
||||
protected calculatePassRate(passed: number, total: number): number {
|
||||
if (total === 0) return 0;
|
||||
return Math.round((passed / total) * 100 * 100) / 100;
|
||||
}
|
||||
|
||||
protected getStatusIcon(status: string): string {
|
||||
switch (status) {
|
||||
case 'passed':
|
||||
return '✅';
|
||||
case 'failed':
|
||||
return '❌';
|
||||
case 'skipped':
|
||||
return '⏭️';
|
||||
default:
|
||||
return '❓';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class ReportGeneratorFactory {
|
||||
static create(
|
||||
type: 'html' | 'json' | 'junit',
|
||||
options: ReportGeneratorOptions
|
||||
): BaseReportGenerator {
|
||||
switch (type) {
|
||||
case 'html':
|
||||
return new HTMLReportGenerator(options);
|
||||
case 'json':
|
||||
return new JSONReportGenerator(options);
|
||||
case 'junit':
|
||||
return new JUnitReportGenerator(options);
|
||||
default:
|
||||
throw new Error(`Unsupported report type: ${type}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
import { HTMLReportGenerator } from './html-report-generator';
|
||||
import { JSONReportGenerator } from './json-report-generator';
|
||||
import { JUnitReportGenerator } from './junit-report-generator';
|
||||
Reference in New Issue
Block a user