Files
makemd/docs/ARCH/backend.md
wurenzhi 2b86715c09 refactor: 优化代码结构并修复类型问题
- 移除未使用的TabPane组件
- 修复类型定义和导入方式
- 优化mock数据源的环境变量判断逻辑
- 更新文档结构并归档旧文件
- 添加新的UI组件和Memo组件
- 调整API路径和响应处理
2026-03-23 12:41:35 +08:00

287 lines
7.1 KiB
Markdown

# 后端架构
> **入口**: [_index.md](_index.md)
---
## 1. 技术栈
| 技术 | 版本 | 用途 |
|------|------|------|
| Node.js | 18.x | 运行时 |
| Express | 4.x | Web框架 |
| TypeScript | 5.x | 类型系统 |
| Knex.js | 3.x | 数据库ORM |
| Redis | 6.x | 缓存/队列 |
| BullMQ | 4.x | 任务队列 |
---
## 2. 目录结构
```
server/src/
├── api/ # API层
│ ├── routes/ # 路由定义
│ ├── controllers/ # 控制器
│ └── middlewares/ # 中间件
├── services/ # 服务层
│ ├── ProductService.ts
│ ├── OrderService.ts
│ └── ...
├── models/ # 数据模型
├── repositories/ # 数据访问层
├── core/ # 核心模块
│ ├── connectors/ # 平台连接器
│ └── orchestrator/ # 编排器
├── utils/ # 工具函数
├── types/ # 类型定义
└── config/ # 配置文件
```
---
## 3. 分层架构
```
┌─────────────────────────────────────────────────────────────┐
│ API层 (Controller) │
│ - 请求处理 │
│ - 参数校验 │
│ - 权限检查 │
└─────────────────────────┬───────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ 服务层 (Service) │
│ - 业务逻辑 │
│ - 事务管理 │
│ - 状态流转 │
└─────────────────────────┬───────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ 数据访问层 (Repository) │
│ - 数据库操作 │
│ - 缓存操作 │
│ - 外部API调用 │
└─────────────────────────────────────────────────────────────┘
```
---
## 4. 服务层设计
### 4.1 服务模板
```typescript
/**
* [BE-P001] 商品服务
* @description 商品主数据管理
*/
export class ProductService {
private static TABLE_NAME = 'cf_product';
static async list(params: ListParams): Promise<Product[]> {
const query = db(this.TABLE_NAME)
.where('tenant_id', params.tenantId);
if (params.status) {
query.where('status', params.status);
}
return query;
}
static async get(id: string): Promise<Product | null> {
return db(this.TABLE_NAME).where({ id }).first();
}
static async create(data: CreateProductRequest): Promise<Product> {
const [product] = await db(this.TABLE_NAME)
.insert({
...data,
id: generateId(),
created_at: new Date(),
updated_at: new Date(),
})
.returning('*');
return product;
}
static async update(id: string, data: UpdateProductRequest): Promise<Product> {
const [product] = await db(this.TABLE_NAME)
.where({ id })
.update({
...data,
updated_at: new Date(),
})
.returning('*');
return product;
}
}
```
### 4.2 服务命名规范
| 后缀 | 说明 | 示例 |
|------|------|------|
| Service | 业务服务 | ProductService |
| Repository | 数据访问 | ProductRepository |
| Connector | 平台连接 | ShopifyConnector |
| Orchestrator | 编排器 | PublishOrchestrator |
---
## 5. 中间件
### 5.1 权限中间件
```typescript
export const authorize = (permission: string) => {
return async (ctx: Context, next: Next) => {
const { user } = ctx.state;
if (!user) {
throw new UnauthorizedError('未登录');
}
const hasPermission = await checkPermission(user, permission);
if (!hasPermission) {
throw new ForbiddenError('无权限');
}
await next();
};
};
```
### 5.2 使用方式
```typescript
router.get(
'/api/v1/products',
authorize('product:read'),
ProductController.list
);
```
---
## 6. 任务队列
### 6.1 队列定义
```typescript
import { Queue, Worker } from 'bullmq';
export const collectionQueue = new Queue('collection', {
connection: redis,
});
export const collectionWorker = new Worker(
'collection',
async (job) => {
const { platform, shopId, type } = job.data;
// 执行采集任务
const result = await CollectionAdapterService.executeCollectionTask(
platform,
shopId,
type
);
return result;
},
{ connection: redis, concurrency: 10 }
);
```
### 6.2 任务添加
```typescript
await collectionQueue.add('collect-products', {
platform: 'SHOPIFY',
shopId: 'shop-001',
type: 'product',
});
```
---
## 7. 错误处理
### 7.1 错误类型
```typescript
export class AppError extends Error {
constructor(
public code: string,
public message: string,
public statusCode: number = 500
) {
super(message);
}
}
export class ValidationError extends AppError {
constructor(message: string) {
super('VAL_INVALID_PARAM', message, 400);
}
}
export class UnauthorizedError extends AppError {
constructor(message: string) {
super('AUTH_UNAUTHORIZED', message, 401);
}
}
export class ForbiddenError extends AppError {
constructor(message: string) {
super('AUTH_FORBIDDEN', message, 403);
}
}
export class NotFoundError extends AppError {
constructor(message: string) {
super('BIZ_NOT_FOUND', message, 404);
}
}
```
### 7.2 错误处理中间件
```typescript
export const errorHandler = async (ctx: Context, next: Next) => {
try {
await next();
} catch (error) {
if (error instanceof AppError) {
ctx.status = error.statusCode;
ctx.body = {
success: false,
error: {
code: error.code,
message: error.message,
},
};
} else {
ctx.status = 500;
ctx.body = {
success: false,
error: {
code: 'SYS_INTERNAL_ERROR',
message: '内部服务器错误',
},
};
}
}
};
```
---
*最后更新: 2026-03-22*