feat: 完成 NestJS 后端核心底座开发 (M1-M6) 和 Ant Design Vue 前端迁移

主要更新:
1. 后端核心底座完成 (M1-M6):
   - 健康检查、指标监控、分布式锁
   - 事件总线、队列系统、事务管理
   - 安全守卫、多租户隔离、存储适配器
   - 审计日志、配置管理、多语言支持

2. 前端迁移到 Ant Design Vue:
   - 从 Element Plus 迁移到 Ant Design Vue
   - 完善 system 模块 (role/menu/dept)
   - 修复依赖和配置问题

3. 文档完善:
   - AI 开发工作流文档
   - 架构约束和开发规范
   - 项目进度跟踪

4. 其他改进:
   - 修复编译错误和类型问题
   - 完善测试用例
   - 优化项目结构
This commit is contained in:
万物街
2025-08-27 11:24:22 +08:00
parent be07b9ffec
commit 1cd5d3bdef
696 changed files with 36708 additions and 16868 deletions

View File

@@ -0,0 +1,154 @@
## 基础能力集成Kafka / Redis / 队列 / 事务)
### 总览
- 目标: 将事件、任务、缓存、事务能力以统一规范接入 App/Core/Infrastructure 三层,替代“散落式调用”。
- 约束: 由 Application 发起流程Core 编排业务规则且不直接依赖外设Infrastructure 提供具体实现。
### 1) 事务TypeORM
- 发起层: Application用例级事务边界
- 使用方式:
```ts
// application/xxx.app.service.ts
constructor(private readonly dataSource: DataSource, private readonly core: XxxCoreService) {}
async runUseCase(dto: Dto) {
return await this.dataSource.transaction(async (manager) => {
// 将 manager 注入到仓储实现(通过请求域注入或方法透传)
await this.core.handle(dto); // Core 内仅调用仓储接口
});
}
```
- 规范:
- 事务只在 Application 层开启Core 不直接操作事务对象
- 多仓储参与时基于同一 `EntityManager`
### 2) 队列Bull/BullMQ 或 DB 队列)
- 发起层: Application用例结束后入队
- 接入点: `UnifiedQueueService` 或具体 Provider`BullQueueProvider`/`DatabaseQueueProvider`
```ts
// application/xxx.app.service.ts
constructor(private readonly queue: UnifiedQueueService) {}
await this.queue.addJob('media', 'generateThumbnail', { attId }, { attempts: 3, delay: 0 });
```
- 处理器建议放置:
- `infrastructure/queues/xxx.processor.ts` 或独立消费模块
- 规范:
- 入队数据为最小必要字段ID/键大对象存储DB再查
### 3) 事件Kafka / DB Outbox
- 发起层: Application领域事件在用例完成后发布
- 接入点: `DomainEventService`(绑定 `IEventBus`,默认 DB Outbox可切 Kafka
```ts
// application/xxx.app.service.ts
constructor(private readonly events: DomainEventService) {}
await this.events.publishEvent(
'system.settings.storage.updated',
String(siteId),
String(siteId),
{ storageType },
);
```
- 配置切换:
- 通过 `EventBusModule` 的 provider 切换 `DatabaseEventBusProvider``KafkaEventBusProvider`
- 规范:
- 事件名格式: `domain.aggregate.action`
- 载荷仅含必要业务字段,带上 `tenantId/siteId`
### 4) Redis缓存/限流/幂等)
- 发起层: Application流程性控制或 Infrastructure技术性实现
- 接入点: `RedisProvider``vendor/redis`
- 常见场景:
- 读多写少配置缓存:`sys_config` 读取后短缓存
- 上传限流/防刷:基于 IP/UID 的计数器
- 幂等:`SETNX` + 过期控制
### 5) 存储(本地/云)
- 发起层: Application 调用 Core 规则后,委托 Infrastructure Provider 落地
- 接入点: `infrastructure/providers/*``vendor/storage/*`(如 `LocalStorageAdapter`
- 规范:
- Provider 通过接口注入,便于切换 OSS/COS/Qiniu
### 6) 在三层中的放置原则
- Application: 事务、入队、发事件、协调多 Core 服务
- Core: 纯业务规则/策略与仓储接口;不直接依赖 Kafka/Redis/队列
- Infrastructure: 队列消费者、存储/HTTP/Redis 具体实现、TypeORM 仓储实现
### 7) 示例Upload 模块接入
- 用例: 上传完成 → 入库附件 → 入队生成缩略图
```ts
// application/upload.app.service.ts
await this.dataSource.transaction(async (manager) => {
const att = await this.core.validateAndPlan(fileMeta);
await this.attachmentRepo.withManager(manager).save(att);
});
await this.queue.addJob('media', 'generateThumbnail', { attId: att.id });
```
### 8) 示例Settings.Storage 接入
- 用例: 切换默认存储 → 写 `sys_config` → 发布事件 → 入队校验可用性
```ts
// application/storage-settings.app.service.ts
await this.dataSource.transaction(async (manager) => {
await this.core.ensureExclusiveDefault(type);
await this.sysConfigRepo.withManager(manager).setValue(key, value);
});
await this.events.publishEvent('system.settings.storage.updated', String(siteId), String(siteId), { type });
await this.queue.addJob('ops', 'validateStorage', { type, siteId });
```
### 9) 配置与健康
- 配置在 `VendorModule`/`EventBusModule` 注入;通过 `ConfigService` 读取连接信息
- 健康检查:将 Redis/队列/事件写入健康聚合输出
### 10) 方案Bvendor/storage 标准结构(平台外设)
```
vendor/storage/
├── index.ts # 统一导出(接口、Token、模块、适配器)
├── storage.module.ts # 可配置模块(选择具体实现)
├── tokens.ts # 注入Token常量(如 STORAGE_ADAPTER)
├── interfaces/
│ ├── storage-adapter.ts # 适配器接口(平台标准)
│ └── types.ts # 通用类型(上传结果、签名参数等)
├── adapters/
│ ├── local.adapter.ts # 本地实现
│ ├── aliyun-oss.adapter.ts # 阿里云实现
│ ├── qcloud-cos.adapter.ts # 腾讯云实现
│ └── qiniu.adapter.ts # 七牛云实现
├── providers/
│ ├── storage.provider.ts # 工厂: 按配置/站点解析适配器
│ └── registry.ts # 多实例注册表 Map<siteId, adapter> + TTL
├── health/storage.health.ts # 健康检查(各实现可选实现)
├── config/schema.ts # 配置Schema(必需项校验)
└── __tests__/
├── storage.contract.spec.ts # 契约测试(接口一致性)
└── adapters/*.spec.ts # 各实现最小测试
```
- Token
```ts
export const STORAGE_ADAPTER = 'STORAGE_ADAPTER';
```
- 接口
```ts
export interface StorageAdapter {
upload(params: { key: string; content: Buffer | NodeJS.ReadableStream; mime?: string }): Promise<{ url: string; key: string }>;
delete(key: string): Promise<void>;
signUpload?(params: { key: string; expiresSec?: number; mime?: string }): Promise<{ url: string; headers?: Record<string,string>; fields?: Record<string,string> }>;
healthCheck?(): Promise<boolean>;
}
```
- 按 site_id 解析(站点启用 > 跟随系统 > local 兜底)
```ts
function resolveAdapter(siteId: number): StorageAdapter {
const enabled = readSiteEnabled(siteId); // storage_xxx with is_use
const type = enabled?.type ?? readPlatformDefault();
const options = enabled?.options ?? readPlatformOptions(type) ?? {};
return registry.getOrCreate(siteId, type, options);
}
```
- 本地隔离路径:`upload/site_{siteId}/...`
- 健康检查:对活跃站点适配器定期 `healthCheck()` 并聚合到 Health
> 说明方案B 将“三方存储”视为外设,接口与实现均在 vendor业务通过 Token 注入与按站点解析工厂使用core 无需暴露存储端口。