2026-03-19 01:39:34 +08:00
|
|
|
|
# 低侵入 Mock 架构设计
|
|
|
|
|
|
|
|
|
|
|
|
> 文档创建时间: 2026-03-19 (北京时间)
|
|
|
|
|
|
> 适用项目: Crawlful Hub
|
|
|
|
|
|
> 目标: 实现"不污染代码、AI上下文安全"的Mock方案
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 📋 目录
|
|
|
|
|
|
|
|
|
|
|
|
1. [核心原则](#核心原则)
|
|
|
|
|
|
2. [架构概览](#架构概览)
|
|
|
|
|
|
3. [前端Mock方案](#前端mock方案)
|
|
|
|
|
|
4. [后端/BFF Mock方案](#后端bff-mock方案)
|
|
|
|
|
|
5. [目录规范](#目录规范)
|
|
|
|
|
|
6. [AI协作规范](#ai协作规范)
|
|
|
|
|
|
7. [实施任务](#实施任务)
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 核心原则
|
|
|
|
|
|
|
|
|
|
|
|
### 1. Mock ≠ 写死数据
|
|
|
|
|
|
|
|
|
|
|
|
❌ **错误做法**: 在组件中直接写死数据
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
const data = [{ id: 1, name: 'Mock商品' }]
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
✅ **正确做法**: 通过数据源抽象层获取
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
const data = await productDataSource.list()
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 2. Mock 必须"可插拔"
|
|
|
|
|
|
|
|
|
|
|
|
Mock 应该是:
|
|
|
|
|
|
- ✅ 可开启 / 可关闭
|
|
|
|
|
|
- ✅ 可替换 / 可隔离
|
|
|
|
|
|
- ✅ 环境变量控制
|
|
|
|
|
|
|
|
|
|
|
|
### 3. Mock 属于"数据源层",不是"业务层"
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
业务代码 → DataSource抽象层 → (Mock/真实API)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 架构概览
|
|
|
|
|
|
|
|
|
|
|
|
### 三层数据架构
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
|
|
|
|
│ 前端 (React + Umi) │
|
|
|
|
|
|
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
|
|
|
|
|
│ │ 业务组件 │ → │ DataSource │ → │ API/Mock │ │
|
|
|
|
|
|
│ │ │ │ 抽象层 │ │ │ │
|
|
|
|
|
|
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
|
|
|
|
|
└─────────────────────────────────────────────────────────────┘
|
|
|
|
|
|
↓
|
|
|
|
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
|
|
|
|
│ BFF 层 (服务编排层) │
|
|
|
|
|
|
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
|
|
|
|
|
│ │ Service │ → │ Mock切换 │ → │ 真实/Mock │ │
|
|
|
|
|
|
│ │ │ │ │ │ 服务 │ │
|
|
|
|
|
|
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
|
|
|
|
|
└─────────────────────────────────────────────────────────────┘
|
|
|
|
|
|
↓
|
|
|
|
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
|
|
|
|
│ 后端微服务层 │
|
|
|
|
|
|
└─────────────────────────────────────────────────────────────┘
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### Mock 分布策略
|
|
|
|
|
|
|
|
|
|
|
|
| 层级 | 是否Mock | 说明 |
|
|
|
|
|
|
|------|---------|------|
|
|
|
|
|
|
| 前端 | ⚠️ 可选 | 推荐用MSW,保持业务代码纯净 |
|
|
|
|
|
|
| DataSource | ✅ 可切换 | 控制入口,环境变量驱动 |
|
|
|
|
|
|
| BFF | ✅ 主力Mock | 最真实,前端无感知 |
|
|
|
|
|
|
| 后端 | ❌ 不建议 | 除非联调测试 |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 前端Mock方案
|
|
|
|
|
|
|
2026-03-19 14:19:01 +08:00
|
|
|
|
### 项目实际采用的两种Mock方式
|
|
|
|
|
|
|
|
|
|
|
|
本项目采用**两种Mock方式并存**的策略,根据不同模块的特点选择合适的方案:
|
|
|
|
|
|
|
|
|
|
|
|
#### 方式一:DataSource内联Mock(推荐用于简单模块)
|
|
|
|
|
|
|
|
|
|
|
|
**特点**:Mock数据直接写在DataSource文件中,通过环境变量切换
|
|
|
|
|
|
|
|
|
|
|
|
**适用场景**:
|
|
|
|
|
|
- ✅ 数据结构简单,不需要复杂的网络拦截
|
|
|
|
|
|
- ✅ 快速原型开发,无需配置MSW
|
|
|
|
|
|
- ✅ Mock逻辑简单,不需要模拟网络延迟和错误
|
|
|
|
|
|
|
|
|
|
|
|
**实现示例**:
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// /dashboard/src/services/productDataSource.ts
|
|
|
|
|
|
|
|
|
|
|
|
class MockProductDataSource implements IProductDataSource {
|
|
|
|
|
|
async fetchProducts(): Promise<Product[]> {
|
|
|
|
|
|
// Mock数据直接内联
|
|
|
|
|
|
return [
|
|
|
|
|
|
{ id: '1', name: '商品A', price: 99.99 },
|
|
|
|
|
|
{ id: '2', name: '商品B', price: 199.99 },
|
|
|
|
|
|
];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class ApiProductDataSource implements IProductDataSource {
|
|
|
|
|
|
async fetchProducts(): Promise<Product[]> {
|
|
|
|
|
|
const res = await fetch('/api/products');
|
|
|
|
|
|
return res.json();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const useMock = process.env.REACT_APP_USE_MOCK === 'true';
|
|
|
|
|
|
export const productDataSource = useMock ? new MockProductDataSource() : new ApiProductDataSource();
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**已实现的模块**:
|
|
|
|
|
|
- 产品模块 (productDataSource.ts)
|
|
|
|
|
|
- 订单模块 (orderDataSource.ts)
|
|
|
|
|
|
- 库存模块 (inventoryDataSource.ts)
|
|
|
|
|
|
- 商户模块 (merchantDataSource.ts)
|
|
|
|
|
|
- 供应商模块 (suppliersDataSource.ts)
|
|
|
|
|
|
- 物流模块 (logisticsDataSource.ts)
|
|
|
|
|
|
- 营销模块 (marketingDataSource.ts)
|
|
|
|
|
|
- 财务模块 (financeDataSource.ts)
|
|
|
|
|
|
- 报表模块 (reportsDataSource.ts)
|
|
|
|
|
|
- 设置模块 (settingsDataSource.ts)
|
|
|
|
|
|
- 售后模块 (afterSalesDataSource.ts)
|
|
|
|
|
|
- 返回模块 (returnDataSource.ts)
|
|
|
|
|
|
- 用户资产模块 (userAssetDataSource.ts)
|
|
|
|
|
|
- 任务中心模块 (taskCenterDataSource.ts)
|
|
|
|
|
|
- 分析模块 (analyticsDataSource.ts)
|
|
|
|
|
|
- B2B贸易模块 (b2bTradeDataSource.ts)
|
|
|
|
|
|
- 排行榜模块 (leaderboardDataSource.ts)
|
|
|
|
|
|
- 动态定价模块 (dynamicPricingDataSource.ts)
|
|
|
|
|
|
- 套利模块 (arbitrageDataSource.ts)
|
|
|
|
|
|
- 店铺报表模块 (shopReportDataSource.ts)
|
|
|
|
|
|
- 自动执行模块 (autoExecutionDataSource.ts)
|
|
|
|
|
|
- 广告优化模块 (adOptimizationDataSource.ts)
|
|
|
|
|
|
- AB测试模块 (abTestDataSource.ts)
|
|
|
|
|
|
- 黑名单模块 (blacklistDataSource.ts)
|
|
|
|
|
|
- 独立站点模块 (independentSiteDataSource.ts)
|
|
|
|
|
|
|
|
|
|
|
|
#### 方式二:MSW网络层Mock(推荐用于复杂模块)
|
|
|
|
|
|
|
|
|
|
|
|
**特点**:使用MSW拦截HTTP请求,Mock数据独立在 `/mock/data/` 目录
|
|
|
|
|
|
|
|
|
|
|
|
**适用场景**:
|
|
|
|
|
|
- ✅ 需要模拟真实的网络请求和响应
|
|
|
|
|
|
- ✅ 需要模拟网络延迟、错误状态
|
|
|
|
|
|
- ✅ 需要支持复杂的查询参数和分页
|
|
|
|
|
|
- ✅ 需要多个组件共享同一Mock数据
|
|
|
|
|
|
|
|
|
|
|
|
**实现示例**:
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// /dashboard/src/mock/data/certificate.mock.ts
|
|
|
|
|
|
export const mockCertificates = [...];
|
|
|
|
|
|
|
|
|
|
|
|
// /dashboard/src/mock/msw.ts
|
|
|
|
|
|
export const handlers = [
|
|
|
|
|
|
rest.get('/api/v1/certificate/certificates', (req, res, ctx) => {
|
|
|
|
|
|
return res(
|
|
|
|
|
|
ctx.delay(300), // 模拟网络延迟
|
|
|
|
|
|
ctx.json({ success: true, data: mockCertificates })
|
|
|
|
|
|
);
|
|
|
|
|
|
}),
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
// /dashboard/src/app.ts
|
|
|
|
|
|
if (process.env.REACT_APP_USE_MOCK === 'true') {
|
|
|
|
|
|
const { worker } = await import('./mock/browser');
|
|
|
|
|
|
await worker.start();
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**已实现的模块**:
|
|
|
|
|
|
- 证书模块 (certificateDataSource.ts + msw.ts)
|
|
|
|
|
|
- 自动选品模块 (productSelectionDataSource.ts + msw.ts)
|
|
|
|
|
|
|
2026-03-19 01:39:34 +08:00
|
|
|
|
### 方案对比
|
|
|
|
|
|
|
|
|
|
|
|
| 方案 | 侵入性 | 推荐度 | 适用场景 |
|
|
|
|
|
|
|------|--------|--------|----------|
|
2026-03-19 14:19:01 +08:00
|
|
|
|
| DataSource内联Mock | ⭐⭐ 低 | 🥈 推荐 | 简单模块、快速原型 |
|
|
|
|
|
|
| MSW网络层Mock | ⭐ 最低 | 🥇 最推荐 | 复杂模块、UI测试 |
|
2026-03-19 01:39:34 +08:00
|
|
|
|
| 本地Mock Server | ⭐⭐⭐ 中 | 🥉 可选 | 团队共享Mock |
|
|
|
|
|
|
| 硬编码 | ❌ 高 | 🚫 不推荐 | 绝对禁止 |
|
|
|
|
|
|
|
2026-03-19 14:19:01 +08:00
|
|
|
|
### 推荐方案:根据模块复杂度选择
|
2026-03-19 01:39:34 +08:00
|
|
|
|
|
|
|
|
|
|
#### 1. 目录结构
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
/dashboard/src
|
2026-03-19 14:19:01 +08:00
|
|
|
|
/api ← 真实API封装(可选)
|
|
|
|
|
|
*.ts
|
|
|
|
|
|
/mock ← MSW Mock数据和拦截器
|
|
|
|
|
|
/data ← Mock数据文件(仅MSW方式使用)
|
2026-03-19 01:39:34 +08:00
|
|
|
|
certificate.mock.ts
|
2026-03-19 14:19:01 +08:00
|
|
|
|
productSelection.mock.ts
|
2026-03-19 01:39:34 +08:00
|
|
|
|
msw.ts ← MSW初始化配置
|
|
|
|
|
|
browser.ts ← 浏览器环境启动
|
2026-03-19 14:19:01 +08:00
|
|
|
|
README.md ← Mock使用说明
|
|
|
|
|
|
/services ← 数据源抽象层(所有模块)
|
|
|
|
|
|
*DataSource.ts ← 包含Mock和API两种实现
|
2026-03-19 01:39:34 +08:00
|
|
|
|
/types ← 类型定义
|
|
|
|
|
|
datasource.ts ← DataSource接口定义
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 2. DataSource接口定义
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// /dashboard/src/types/datasource.ts
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* [MOCK-001] DataSource抽象接口
|
|
|
|
|
|
* 所有数据源必须实现此接口
|
|
|
|
|
|
* AI注意: 这是抽象层,不涉及具体实现
|
|
|
|
|
|
*/
|
|
|
|
|
|
export interface IDataSource<T, QueryParams = any> {
|
|
|
|
|
|
list(params?: QueryParams): Promise<T[]>;
|
|
|
|
|
|
detail(id: string): Promise<T | null>;
|
|
|
|
|
|
create(data: Partial<T>): Promise<T>;
|
|
|
|
|
|
update(id: string, data: Partial<T>): Promise<T>;
|
|
|
|
|
|
delete(id: string): Promise<void>;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export interface ProductQueryParams {
|
|
|
|
|
|
keyword?: string;
|
|
|
|
|
|
category?: string;
|
|
|
|
|
|
status?: string;
|
|
|
|
|
|
page?: number;
|
|
|
|
|
|
pageSize?: number;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export interface CertificateQueryParams {
|
|
|
|
|
|
status?: string;
|
|
|
|
|
|
type?: string;
|
|
|
|
|
|
page?: number;
|
|
|
|
|
|
pageSize?: number;
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 3. DataSource抽象层实现
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// /dashboard/src/services/certificateDataSource.ts
|
|
|
|
|
|
|
|
|
|
|
|
import { Certificate } from '@/types/certificate';
|
|
|
|
|
|
import { IDataSource, CertificateQueryParams } from '@/types/datasource';
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* [MOCK-002] 证书数据源抽象层
|
|
|
|
|
|
* 通过环境变量自动切换Mock/真实API
|
|
|
|
|
|
* AI注意: 这是唯一入口,业务代码必须调用此层
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
// 真实API实现
|
|
|
|
|
|
class ApiCertificateDataSource implements IDataSource<Certificate, CertificateQueryParams> {
|
|
|
|
|
|
async list(params?: CertificateQueryParams): Promise<Certificate[]> {
|
|
|
|
|
|
const query = new URLSearchParams(params as any).toString();
|
|
|
|
|
|
const response = await fetch(`/api/v1/certificate/certificates?${query}`);
|
|
|
|
|
|
const result = await response.json();
|
|
|
|
|
|
return result.data || [];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async detail(id: string): Promise<Certificate | null> {
|
|
|
|
|
|
const response = await fetch(`/api/v1/certificate/certificates/${id}`);
|
|
|
|
|
|
const result = await response.json();
|
|
|
|
|
|
return result.data || null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async create(data: Partial<Certificate>): Promise<Certificate> {
|
|
|
|
|
|
const response = await fetch('/api/v1/certificate/certificates', {
|
|
|
|
|
|
method: 'POST',
|
|
|
|
|
|
headers: { 'Content-Type': 'application/json' },
|
|
|
|
|
|
body: JSON.stringify(data),
|
|
|
|
|
|
});
|
|
|
|
|
|
const result = await response.json();
|
|
|
|
|
|
return result.data;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async update(id: string, data: Partial<Certificate>): Promise<Certificate> {
|
|
|
|
|
|
const response = await fetch(`/api/v1/certificate/certificates/${id}`, {
|
|
|
|
|
|
method: 'PUT',
|
|
|
|
|
|
headers: { 'Content-Type': 'application/json' },
|
|
|
|
|
|
body: JSON.stringify(data),
|
|
|
|
|
|
});
|
|
|
|
|
|
const result = await response.json();
|
|
|
|
|
|
return result.data;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async delete(id: string): Promise<void> {
|
|
|
|
|
|
await fetch(`/api/v1/certificate/certificates/${id}`, {
|
|
|
|
|
|
method: 'DELETE',
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Mock实现 (完全独立文件)
|
|
|
|
|
|
class MockCertificateDataSource implements IDataSource<Certificate, CertificateQueryParams> {
|
|
|
|
|
|
private mockData: Certificate[] = [
|
|
|
|
|
|
{
|
|
|
|
|
|
id: '1',
|
|
|
|
|
|
name: 'CE认证证书',
|
|
|
|
|
|
type: 'PRODUCT_CERT',
|
|
|
|
|
|
status: 'APPROVED',
|
|
|
|
|
|
fileUrl: '/files/ce-cert.pdf',
|
|
|
|
|
|
fileName: 'CE-Certificate-2026.pdf',
|
|
|
|
|
|
uploadDate: '2026-03-15',
|
|
|
|
|
|
expiryDate: '2027-03-15',
|
|
|
|
|
|
approvedBy: 'admin',
|
|
|
|
|
|
approvedDate: '2026-03-16',
|
|
|
|
|
|
productId: 'P001',
|
|
|
|
|
|
productName: '工业温度传感器',
|
|
|
|
|
|
notes: '欧盟市场准入认证',
|
|
|
|
|
|
},
|
|
|
|
|
|
// ... 更多Mock数据
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
async list(params?: CertificateQueryParams): Promise<Certificate[]> {
|
|
|
|
|
|
// 模拟网络延迟
|
|
|
|
|
|
await new Promise(resolve => setTimeout(resolve, 300));
|
|
|
|
|
|
|
|
|
|
|
|
let result = [...this.mockData];
|
|
|
|
|
|
|
|
|
|
|
|
if (params?.status) {
|
|
|
|
|
|
result = result.filter(item => item.status === params.status);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (params?.type) {
|
|
|
|
|
|
result = result.filter(item => item.type === params.type);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async detail(id: string): Promise<Certificate | null> {
|
|
|
|
|
|
await new Promise(resolve => setTimeout(resolve, 200));
|
|
|
|
|
|
return this.mockData.find(item => item.id === id) || null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async create(data: Partial<Certificate>): Promise<Certificate> {
|
|
|
|
|
|
await new Promise(resolve => setTimeout(resolve, 500));
|
|
|
|
|
|
const newCert: Certificate = {
|
|
|
|
|
|
id: `${Date.now()}`,
|
|
|
|
|
|
...data as Certificate,
|
|
|
|
|
|
status: 'PENDING',
|
|
|
|
|
|
uploadDate: new Date().toISOString().split('T')[0],
|
|
|
|
|
|
};
|
|
|
|
|
|
this.mockData.unshift(newCert);
|
|
|
|
|
|
return newCert;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async update(id: string, data: Partial<Certificate>): Promise<Certificate> {
|
|
|
|
|
|
await new Promise(resolve => setTimeout(resolve, 300));
|
|
|
|
|
|
const index = this.mockData.findIndex(item => item.id === id);
|
|
|
|
|
|
if (index === -1) throw new Error('Certificate not found');
|
|
|
|
|
|
this.mockData[index] = { ...this.mockData[index], ...data };
|
|
|
|
|
|
return this.mockData[index];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async delete(id: string): Promise<void> {
|
|
|
|
|
|
await new Promise(resolve => setTimeout(resolve, 200));
|
|
|
|
|
|
this.mockData = this.mockData.filter(item => item.id !== id);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 导出数据源实例 (环境变量控制)
|
|
|
|
|
|
const useMock = process.env.REACT_APP_USE_MOCK === 'true';
|
|
|
|
|
|
|
|
|
|
|
|
export const certificateDataSource: IDataSource<Certificate, CertificateQueryParams> = useMock
|
|
|
|
|
|
? new MockCertificateDataSource()
|
|
|
|
|
|
: new ApiCertificateDataSource();
|
|
|
|
|
|
|
|
|
|
|
|
// 标记Mock状态 (用于调试)
|
|
|
|
|
|
export const __MOCK__ = useMock;
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 4. MSW配置
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// /dashboard/src/mock/msw.ts
|
|
|
|
|
|
|
|
|
|
|
|
import { setupWorker, rest } from 'msw';
|
|
|
|
|
|
import { mockCertificates } from './data/certificate.mock';
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* [MOCK-003] MSW Mock配置
|
|
|
|
|
|
* 拦截HTTP请求,返回Mock数据
|
|
|
|
|
|
* AI注意: 这是网络层拦截,业务代码完全无感知
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
export const worker = setupWorker(
|
|
|
|
|
|
// 证书列表
|
|
|
|
|
|
rest.get('/api/v1/certificate/certificates', (req, res, ctx) => {
|
|
|
|
|
|
const status = req.url.searchParams.get('status');
|
|
|
|
|
|
const type = req.url.searchParams.get('type');
|
|
|
|
|
|
|
|
|
|
|
|
let data = [...mockCertificates];
|
|
|
|
|
|
if (status) data = data.filter(item => item.status === status);
|
|
|
|
|
|
if (type) data = data.filter(item => item.type === type);
|
|
|
|
|
|
|
|
|
|
|
|
return res(
|
|
|
|
|
|
ctx.delay(300),
|
|
|
|
|
|
ctx.json({
|
|
|
|
|
|
success: true,
|
|
|
|
|
|
data,
|
|
|
|
|
|
total: data.length,
|
|
|
|
|
|
})
|
|
|
|
|
|
);
|
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
|
|
// 证书详情
|
|
|
|
|
|
rest.get('/api/v1/certificate/certificates/:id', (req, res, ctx) => {
|
|
|
|
|
|
const { id } = req.params;
|
|
|
|
|
|
const cert = mockCertificates.find(item => item.id === id);
|
|
|
|
|
|
|
|
|
|
|
|
if (!cert) {
|
|
|
|
|
|
return res(
|
|
|
|
|
|
ctx.status(404),
|
|
|
|
|
|
ctx.json({ success: false, error: '证书不存在' })
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return res(
|
|
|
|
|
|
ctx.delay(200),
|
|
|
|
|
|
ctx.json({ success: true, data: cert })
|
|
|
|
|
|
);
|
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
|
|
// 创建证书
|
|
|
|
|
|
rest.post('/api/v1/certificate/certificates', async (req, res, ctx) => {
|
|
|
|
|
|
const body = await req.json();
|
|
|
|
|
|
const newCert = {
|
|
|
|
|
|
id: `${Date.now()}`,
|
|
|
|
|
|
...body,
|
|
|
|
|
|
status: 'PENDING',
|
|
|
|
|
|
uploadDate: new Date().toISOString().split('T')[0],
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return res(
|
|
|
|
|
|
ctx.delay(500),
|
|
|
|
|
|
ctx.json({ success: true, data: { id: newCert.id } })
|
|
|
|
|
|
);
|
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
|
|
// 更新证书状态
|
|
|
|
|
|
rest.put('/api/v1/certificate/certificates/:id/status', async (req, res, ctx) => {
|
|
|
|
|
|
const { id } = req.params;
|
|
|
|
|
|
const { status, approvedBy } = await req.json();
|
|
|
|
|
|
|
|
|
|
|
|
return res(
|
|
|
|
|
|
ctx.delay(300),
|
|
|
|
|
|
ctx.json({ success: true })
|
|
|
|
|
|
);
|
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
|
|
// 删除证书
|
|
|
|
|
|
rest.delete('/api/v1/certificate/certificates/:id', (req, res, ctx) => {
|
|
|
|
|
|
return res(
|
|
|
|
|
|
ctx.delay(200),
|
|
|
|
|
|
ctx.json({ success: true })
|
|
|
|
|
|
);
|
|
|
|
|
|
})
|
|
|
|
|
|
);
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// /dashboard/src/mock/browser.ts
|
|
|
|
|
|
import { worker } from './msw';
|
|
|
|
|
|
export { worker };
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// /dashboard/src/index.tsx (入口文件)
|
|
|
|
|
|
|
|
|
|
|
|
import React from 'react';
|
|
|
|
|
|
import ReactDOM from 'react-dom/client';
|
|
|
|
|
|
import App from './App';
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* [MOCK-004] MSW启动配置
|
|
|
|
|
|
* 仅在REACT_APP_USE_MOCK=true时启用
|
|
|
|
|
|
*/
|
|
|
|
|
|
async function enableMocking() {
|
|
|
|
|
|
if (process.env.REACT_APP_USE_MOCK !== 'true') {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const { worker } = await import('./mock/browser');
|
|
|
|
|
|
return worker.start({
|
|
|
|
|
|
onUnhandledRequest: 'bypass', // 未拦截的请求直接透传
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
enableMocking().then(() => {
|
|
|
|
|
|
const root = ReactDOM.createRoot(document.getElementById('root')!);
|
|
|
|
|
|
root.render(
|
|
|
|
|
|
<React.StrictMode>
|
|
|
|
|
|
<App />
|
|
|
|
|
|
</React.StrictMode>
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 5. 业务组件使用示例
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// /dashboard/src/pages/Compliance/index.tsx
|
|
|
|
|
|
|
|
|
|
|
|
import { certificateDataSource } from '@/services/certificateDataSource';
|
|
|
|
|
|
|
|
|
|
|
|
const ComplianceManagement: React.FC = () => {
|
|
|
|
|
|
const fetchData = useCallback(async () => {
|
|
|
|
|
|
setLoading(true);
|
|
|
|
|
|
try {
|
|
|
|
|
|
// 调用DataSource层,完全无感知是Mock还是真实API
|
|
|
|
|
|
const data = await certificateDataSource.list({
|
|
|
|
|
|
status: activeStatus,
|
|
|
|
|
|
type: activeType,
|
|
|
|
|
|
});
|
|
|
|
|
|
setCertificates(data);
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
message.error('获取证书列表失败');
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
setLoading(false);
|
|
|
|
|
|
}
|
|
|
|
|
|
}, [activeStatus, activeType]);
|
|
|
|
|
|
|
|
|
|
|
|
const handleUploadSubmit = async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const values = await uploadForm.validateFields();
|
|
|
|
|
|
await certificateDataSource.create({
|
|
|
|
|
|
name: values.name,
|
|
|
|
|
|
type: values.type,
|
|
|
|
|
|
expiryDate: values.expiryDate.format('YYYY-MM-DD'),
|
|
|
|
|
|
productId: values.productId,
|
|
|
|
|
|
productName: values.productName,
|
|
|
|
|
|
notes: values.notes,
|
|
|
|
|
|
});
|
|
|
|
|
|
message.success('证书上传成功');
|
|
|
|
|
|
fetchData();
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
message.error('上传失败');
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// ... 其他逻辑
|
|
|
|
|
|
};
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 后端/BFF Mock方案
|
|
|
|
|
|
|
|
|
|
|
|
### 架构设计
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
BFF层
|
|
|
|
|
|
├─ Service (业务逻辑)
|
|
|
|
|
|
├─ Mock切换器 (环境变量控制)
|
|
|
|
|
|
├─ 真实API客户端
|
|
|
|
|
|
└─ Mock服务
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 实现示例
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// /server/src/bff/services/certificateService.ts
|
|
|
|
|
|
|
|
|
|
|
|
import { CertificateService as RealCertificateService } from '../../services/CertificateService';
|
|
|
|
|
|
import { MockCertificateService } from '../mock/certificateMock';
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* [MOCK-005] BFF层证书服务
|
|
|
|
|
|
* 通过环境变量自动切换Mock/真实服务
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
const useMock = process.env.USE_MOCK === 'true';
|
|
|
|
|
|
|
|
|
|
|
|
export const certificateService = useMock
|
|
|
|
|
|
? new MockCertificateService()
|
|
|
|
|
|
: new RealCertificateService();
|
|
|
|
|
|
|
|
|
|
|
|
// 类型导出,确保调用方类型安全
|
|
|
|
|
|
export type ICertificateService = typeof certificateService;
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// /server/src/bff/mock/certificateMock.ts
|
|
|
|
|
|
|
|
|
|
|
|
import { ICertificateService } from '../services/certificateService';
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* [MOCK-006] BFF层Mock服务
|
|
|
|
|
|
* 完全独立的Mock实现
|
|
|
|
|
|
* AI注意: 这是Mock实现,不是真实业务逻辑
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
export class MockCertificateService implements ICertificateService {
|
|
|
|
|
|
private mockData = [
|
|
|
|
|
|
// ... Mock数据
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
async query(options: any) {
|
|
|
|
|
|
await this.delay(300);
|
|
|
|
|
|
return {
|
|
|
|
|
|
items: this.mockData,
|
|
|
|
|
|
total: this.mockData.length,
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async getById(id: string, tenantId: string, shopId: string) {
|
|
|
|
|
|
await this.delay(200);
|
|
|
|
|
|
return this.mockData.find(item => item.id === id) || null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async create(input: any) {
|
|
|
|
|
|
await this.delay(500);
|
|
|
|
|
|
const id = `mock-${Date.now()}`;
|
|
|
|
|
|
// ... 创建逻辑
|
|
|
|
|
|
return id;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private delay(ms: number) {
|
|
|
|
|
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 目录规范
|
|
|
|
|
|
|
|
|
|
|
|
### 前端目录规范
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
/dashboard/src
|
|
|
|
|
|
/mock ← 所有Mock相关
|
|
|
|
|
|
/data ← Mock数据定义
|
|
|
|
|
|
*.mock.ts
|
|
|
|
|
|
msw.ts ← MSW配置
|
|
|
|
|
|
browser.ts ← 浏览器入口
|
|
|
|
|
|
server.ts ← Node/测试入口
|
|
|
|
|
|
README.md ← Mock使用说明
|
|
|
|
|
|
/services ← DataSource抽象层
|
|
|
|
|
|
*DataSource.ts
|
|
|
|
|
|
/api ← 真实API封装
|
|
|
|
|
|
*.ts
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 后端目录规范
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
/server/src
|
|
|
|
|
|
/bff ← BFF层
|
|
|
|
|
|
/mock ← Mock服务
|
|
|
|
|
|
*.ts
|
|
|
|
|
|
/services ← 服务层
|
|
|
|
|
|
*.ts
|
|
|
|
|
|
/api ← API客户端
|
|
|
|
|
|
*.ts
|
|
|
|
|
|
/services ← 真实服务
|
|
|
|
|
|
*.ts
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 标记规范
|
|
|
|
|
|
|
|
|
|
|
|
所有Mock文件必须包含以下标记:
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
/**
|
|
|
|
|
|
* [MOCK-XXX] 功能描述
|
|
|
|
|
|
* AI注意: 这是Mock实现,不是真实业务逻辑
|
|
|
|
|
|
* 仅在USE_MOCK=true时启用
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
// 或者
|
|
|
|
|
|
|
|
|
|
|
|
// [MOCK] 此文件为Mock数据,AI请勿当作真实业务逻辑
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## AI协作规范
|
|
|
|
|
|
|
|
|
|
|
|
### 1. Mock文件识别规则
|
|
|
|
|
|
|
|
|
|
|
|
AI在分析代码时:
|
|
|
|
|
|
- ✅ 忽略 `/mock` 目录下所有文件
|
|
|
|
|
|
- ✅ 忽略包含 `[MOCK]` 标记的文件
|
|
|
|
|
|
- ✅ 忽略 `__MOCK__` 变量为真的代码路径
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 业务代码规范
|
|
|
|
|
|
|
|
|
|
|
|
AI生成业务代码时必须:
|
|
|
|
|
|
- ✅ 调用 DataSource 抽象层
|
|
|
|
|
|
- ✅ 不直接调用 API 或 Mock
|
|
|
|
|
|
- ✅ 不硬编码任何数据
|
|
|
|
|
|
|
|
|
|
|
|
### 3. 文档声明
|
|
|
|
|
|
|
|
|
|
|
|
```markdown
|
|
|
|
|
|
## Mock使用规范
|
|
|
|
|
|
|
2026-03-19 14:19:01 +08:00
|
|
|
|
1. DataSource层是唯一业务入口,所有业务代码必须通过DataSource获取数据
|
|
|
|
|
|
2. Mock数据有两种存放方式:
|
|
|
|
|
|
- 简单模块:直接写在DataSource文件中的Mock类
|
|
|
|
|
|
- 复杂模块:独立在 `/mock/data/` 目录,通过MSW拦截
|
|
|
|
|
|
3. `REACT_APP_USE_MOCK=true` 时才启用Mock
|
2026-03-19 01:39:34 +08:00
|
|
|
|
4. AI不得将Mock数据当作真实业务逻辑
|
|
|
|
|
|
5. Mock不代表真实接口结构,仅用于UI开发
|
2026-03-19 14:19:01 +08:00
|
|
|
|
6. 新增模块时,根据复杂度选择合适的Mock方式
|
2026-03-19 01:39:34 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 实施任务
|
|
|
|
|
|
|
|
|
|
|
|
### 任务清单
|
|
|
|
|
|
|
|
|
|
|
|
| 任务ID | 任务描述 | 涉及文件 | 优先级 | 状态 |
|
|
|
|
|
|
|--------|----------|----------|--------|------|
|
2026-03-19 14:19:01 +08:00
|
|
|
|
| MOCK-001 | 创建DataSource接口定义 | `/dashboard/src/types/datasource.ts` | P0 | ✅ 已完成 |
|
|
|
|
|
|
| MOCK-002 | 实现证书DataSource | `/dashboard/src/services/certificateDataSource.ts` | P0 | ✅ 已完成 |
|
|
|
|
|
|
| MOCK-003 | 配置MSW拦截器 | `/dashboard/src/mock/msw.ts` | P0 | ✅ 已完成 |
|
|
|
|
|
|
| MOCK-004 | 入口文件MSW启动 | `/dashboard/src/app.ts` | P0 | ✅ 已完成 |
|
|
|
|
|
|
| MOCK-005 | BFF层Mock切换器 | `/server/src/bff/services/certificateService.ts` | P0 | ✅ 已完成 |
|
|
|
|
|
|
| MOCK-006 | BFF层Mock服务 | `/server/src/bff/mock/certificateMock.ts` | P0 | ✅ 已完成 |
|
|
|
|
|
|
| MOCK-007 | 产品模块DataSource | `/dashboard/src/services/productDataSource.ts` | P1 | ✅ 已完成 |
|
|
|
|
|
|
| MOCK-008 | 订单模块DataSource | `/dashboard/src/services/orderDataSource.ts` | P1 | ✅ 已完成 |
|
2026-03-19 01:39:34 +08:00
|
|
|
|
| MOCK-009 | 用户模块DataSource | `/dashboard/src/services/userDataSource.ts` | P1 | ⏳ 待实现 |
|
2026-03-19 14:19:01 +08:00
|
|
|
|
| MOCK-010 | 库存模块DataSource | `/dashboard/src/services/inventoryDataSource.ts` | P1 | ✅ 已完成 |
|
|
|
|
|
|
| MOCK-016 | 商户模块DataSource | `/dashboard/src/services/merchantDataSource.ts` | P1 | ✅ 已完成 |
|
|
|
|
|
|
| MOCK-017 | 供应商模块DataSource | `/dashboard/src/services/suppliersDataSource.ts` | P1 | ✅ 已完成 |
|
|
|
|
|
|
| MOCK-018 | 物流模块DataSource | `/dashboard/src/services/logisticsDataSource.ts` | P1 | ✅ 已完成 |
|
|
|
|
|
|
| MOCK-019 | 营销模块DataSource | `/dashboard/src/services/marketingDataSource.ts` | P1 | ✅ 已完成 |
|
|
|
|
|
|
| MOCK-020 | 财务模块DataSource | `/dashboard/src/services/financeDataSource.ts` | P1 | ✅ 已完成 |
|
|
|
|
|
|
| MOCK-021 | 报表模块DataSource | `/dashboard/src/services/reportsDataSource.ts` | P1 | ✅ 已完成 |
|
|
|
|
|
|
| MOCK-022 | 设置模块DataSource | `/dashboard/src/services/settingsDataSource.ts` | P1 | ✅ 已完成 |
|
|
|
|
|
|
| MOCK-023 | 售后模块DataSource | `/dashboard/src/services/afterSalesDataSource.ts` | P1 | ✅ 已完成 |
|
|
|
|
|
|
| MOCK-024 | 返回模块DataSource | `/dashboard/src/services/returnDataSource.ts` | P1 | ✅ 已完成 |
|
|
|
|
|
|
| MOCK-025 | 用户资产模块DataSource | `/dashboard/src/services/userAssetDataSource.ts` | P1 | ✅ 已完成 |
|
|
|
|
|
|
| MOCK-026 | 任务中心模块DataSource | `/dashboard/src/services/taskCenterDataSource.ts` | P1 | ✅ 已完成 |
|
|
|
|
|
|
| MOCK-027 | 分析模块DataSource | `/dashboard/src/services/analyticsDataSource.ts` | P1 | ✅ 已完成 |
|
|
|
|
|
|
| MOCK-028 | B2B贸易模块DataSource | `/dashboard/src/services/b2bTradeDataSource.ts` | P1 | ✅ 已完成 |
|
|
|
|
|
|
| MOCK-029 | 排行榜模块DataSource | `/dashboard/src/services/leaderboardDataSource.ts` | P1 | ✅ 已完成 |
|
|
|
|
|
|
| MOCK-030 | 动态定价模块DataSource | `/dashboard/src/services/dynamicPricingDataSource.ts` | P1 | ✅ 已完成 |
|
|
|
|
|
|
| MOCK-031 | 套利模块DataSource | `/dashboard/src/services/arbitrageDataSource.ts` | P1 | ✅ 已完成 |
|
|
|
|
|
|
| MOCK-032 | 店铺报表模块DataSource | `/dashboard/src/services/shopReportDataSource.ts` | P1 | ✅ 已完成 |
|
|
|
|
|
|
| MOCK-033 | 自动执行模块DataSource | `/dashboard/src/services/autoExecutionDataSource.ts` | P1 | ✅ 已完成 |
|
|
|
|
|
|
| MOCK-034 | 广告优化模块DataSource | `/dashboard/src/services/adOptimizationDataSource.ts` | P1 | ✅ 已完成 |
|
|
|
|
|
|
| MOCK-035 | AB测试模块DataSource | `/dashboard/src/services/abTestDataSource.ts` | P1 | ✅ 已完成 |
|
|
|
|
|
|
| MOCK-036 | 黑名单模块DataSource | `/dashboard/src/services/blacklistDataSource.ts` | P1 | ✅ 已完成 |
|
|
|
|
|
|
| MOCK-037 | 独立站点模块DataSource | `/dashboard/src/services/independentSiteDataSource.ts` | P1 | ✅ 已完成 |
|
|
|
|
|
|
| MOCK-011 | 环境变量配置 | `.env.development`, `.env.production` | P0 | ✅ 已完成 |
|
2026-03-19 01:39:34 +08:00
|
|
|
|
| MOCK-012 | 文档完善 | `docs/01_Architecture/Mock_Architecture.md` | P0 | ✅ 已完成 |
|
|
|
|
|
|
| MOCK-013 | 自动选品模块Mock数据 | `/dashboard/src/mock/data/productSelection.mock.ts` | P0 | ✅ 已完成 |
|
|
|
|
|
|
| MOCK-014 | 自动选品DataSource | `/dashboard/src/services/productSelectionDataSource.ts` | P0 | ✅ 已完成 |
|
|
|
|
|
|
| MOCK-015 | 自动选品页面Mock集成 | `/dashboard/src/pages/AutoProductSelection/index.tsx` | P0 | ✅ 已完成 |
|
|
|
|
|
|
|
|
|
|
|
|
### 环境变量配置
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# .env.development (开发环境)
|
|
|
|
|
|
REACT_APP_USE_MOCK=true # 前端启用Mock
|
|
|
|
|
|
USE_MOCK=true # 后端启用Mock
|
|
|
|
|
|
|
|
|
|
|
|
# .env.production (生产环境)
|
|
|
|
|
|
REACT_APP_USE_MOCK=false # 前端禁用Mock
|
|
|
|
|
|
USE_MOCK=false # 后端禁用Mock
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 快速启动命令
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 开发模式 (带Mock)
|
|
|
|
|
|
npm run dev:mock
|
|
|
|
|
|
|
|
|
|
|
|
# 开发模式 (真实API)
|
|
|
|
|
|
npm run dev
|
|
|
|
|
|
|
|
|
|
|
|
# 生产构建
|
|
|
|
|
|
npm run build
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 优势总结
|
|
|
|
|
|
|
|
|
|
|
|
| 特性 | 描述 |
|
|
|
|
|
|
|------|------|
|
|
|
|
|
|
| 🎯 零侵入 | 业务层完全不感知Mock |
|
|
|
|
|
|
| 🔄 可切换 | 环境变量一键切换Mock/真实API |
|
|
|
|
|
|
| 🤖 AI安全 | Mock独立文件 + 文档规范 |
|
|
|
|
|
|
| 📦 可扩展 | 支持MSW、BFF Mock、本地Mock Server |
|
|
|
|
|
|
| 🧪 可测试 | 统一接口便于单元测试 |
|
|
|
|
|
|
| 📝 可维护 | 目录清晰,职责分离 |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 附录
|
|
|
|
|
|
|
|
|
|
|
|
### 相关文档
|
|
|
|
|
|
|
|
|
|
|
|
- [项目特定规则](../.trae/rules/project-specific-rules.md)
|
|
|
|
|
|
- [AI协作协议](../.trae/rules/project-specific-rules.md#7-ai-协作协议)
|
|
|
|
|
|
- [Task_Overview](../00_Business/Task_Overview.md)
|
|
|
|
|
|
|
|
|
|
|
|
### 更新记录
|
|
|
|
|
|
|
|
|
|
|
|
| 时间 | 版本 | 更新内容 |
|
|
|
|
|
|
|------|------|----------|
|
|
|
|
|
|
| 2026-03-19 | v1.0 | 初始版本,创建完整Mock架构设计 |
|
2026-03-19 14:19:01 +08:00
|
|
|
|
| 2026-03-19 | v1.1 | 更新为两种Mock方式并存策略,完善任务状态,添加27个模块Mock实现 |
|
2026-03-19 01:39:34 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
*本文档遵循 Crawlful Hub 项目规范,所有Mock实现必须遵守"低侵入、AI安全"原则。*
|