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:
154
admin/docs/src/wwjcloud/ai/integration.md
Normal file
154
admin/docs/src/wwjcloud/ai/integration.md
Normal 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) 方案B:vendor/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 无需暴露存储端口。
|
||||
Reference in New Issue
Block a user