rwadurian/frontend/mobile-upgrade/docs/ARCHITECTURE.md

299 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Mobile Upgrade Admin - 架构文档
## 概述
Mobile Upgrade Admin 是一个用于管理移动应用版本升级的 Web 管理后台。本项目采用 **Clean Architecture整洁架构** 设计模式,实现了关注点分离、可测试性和可维护性。
## 技术栈
| 分类 | 技术 | 版本 | 说明 |
|------|------|------|------|
| 框架 | Next.js | 14.x | React 全栈框架App Router |
| 语言 | TypeScript | 5.x | 类型安全 |
| 状态管理 | Zustand | 4.x | 轻量级状态管理 |
| HTTP 客户端 | Axios | 1.x | API 请求 |
| 样式 | Tailwind CSS | 3.x | 原子化 CSS |
| 通知 | react-hot-toast | 2.x | Toast 通知 |
## 架构设计
### Clean Architecture 分层
```
┌─────────────────────────────────────────────────────────────┐
│ Presentation Layer │
│ (UI Components, Pages) │
├─────────────────────────────────────────────────────────────┤
│ Application Layer │
│ (Stores, Hooks, Use Cases) │
├─────────────────────────────────────────────────────────────┤
│ Domain Layer │
│ (Entities, Repository Interfaces) │
├─────────────────────────────────────────────────────────────┤
│ Infrastructure Layer │
│ (API Client, Repository Implementations) │
└─────────────────────────────────────────────────────────────┘
```
### 目录结构
```
src/
├── domain/ # 领域层 - 业务核心
│ ├── entities/
│ │ └── version.ts # 版本实体和类型定义
│ ├── repositories/
│ │ └── version-repository.ts # Repository 接口定义
│ └── index.ts # 统一导出
├── infrastructure/ # 基础设施层 - 外部依赖
│ ├── http/
│ │ └── api-client.ts # Axios 客户端配置
│ ├── repositories/
│ │ └── version-repository-impl.ts # Repository 实现
│ └── index.ts # 统一导出
├── application/ # 应用层 - 业务逻辑
│ ├── stores/
│ │ └── version-store.ts # Zustand 状态管理
│ ├── hooks/
│ │ └── use-versions.ts # React Hooks
│ └── index.ts # 统一导出
├── presentation/ # 表示层 - UI 组件
│ ├── components/
│ │ ├── version-card.tsx # 版本卡片组件
│ │ ├── upload-modal.tsx # 上传弹窗组件
│ │ └── edit-modal.tsx # 编辑弹窗组件
│ └── index.ts # 统一导出
└── app/ # Next.js App Router
├── layout.tsx # 根布局
├── page.tsx # 首页
└── globals.css # 全局样式
```
## 各层职责详解
### 1. Domain Layer领域层
**职责**:定义业务实体和接口,不依赖任何外部框架。
#### 实体定义 (`entities/version.ts`)
```typescript
// 平台类型
export type Platform = 'android' | 'ios'
// 应用版本实体
export interface AppVersion {
id: string
platform: Platform
versionCode: number
versionName: string
buildNumber: string
downloadUrl: string
fileSize: string
fileSha256: string
changelog: string
isForceUpdate: boolean
isEnabled: boolean
minOsVersion: string | null
releaseDate: string | null
createdAt: string
updatedAt: string
}
// 输入/输出 DTO
export interface CreateVersionInput { ... }
export interface UpdateVersionInput { ... }
export interface UploadVersionInput { ... }
export interface VersionListFilter { ... }
```
#### Repository 接口 (`repositories/version-repository.ts`)
```typescript
export interface IVersionRepository {
list(filter?: VersionListFilter): Promise<AppVersion[]>
getById(id: string): Promise<AppVersion>
create(input: CreateVersionInput): Promise<AppVersion>
update(id: string, input: UpdateVersionInput): Promise<AppVersion>
delete(id: string): Promise<void>
toggle(id: string, isEnabled: boolean): Promise<void>
upload(input: UploadVersionInput): Promise<AppVersion>
}
```
### 2. Infrastructure Layer基础设施层
**职责**实现与外部系统的交互API、数据库等
#### API 客户端 (`http/api-client.ts`)
```typescript
import axios from 'axios'
export const apiClient = axios.create({
baseURL: process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000',
timeout: 30000,
headers: {
'Content-Type': 'application/json',
},
})
// 响应拦截器处理错误
apiClient.interceptors.response.use(
(response) => response,
(error) => {
const message = error.response?.data?.message || '请求失败'
return Promise.reject(new Error(message))
}
)
```
#### Repository 实现 (`repositories/version-repository-impl.ts`)
```typescript
export class VersionRepositoryImpl implements IVersionRepository {
private client: AxiosInstance
constructor(client?: AxiosInstance) {
this.client = client || apiClient
}
async list(filter?: VersionListFilter): Promise<AppVersion[]> {
const response = await this.client.get<AppVersion[]>('/api/v1/versions', { params: filter })
return response.data
}
async upload(input: UploadVersionInput): Promise<AppVersion> {
const formData = new FormData()
formData.append('file', input.file)
// ... 其他字段
const response = await this.client.post<AppVersion>('/api/v1/versions/upload', formData)
return response.data
}
// ... 其他方法
}
```
### 3. Application Layer应用层
**职责**:协调业务逻辑,管理应用状态。
#### Zustand Store (`stores/version-store.ts`)
```typescript
import { create } from 'zustand'
interface VersionState {
// 状态
versions: AppVersion[]
selectedVersion: AppVersion | null
isLoading: boolean
error: string | null
filter: { platform?: Platform; includeDisabled: boolean }
// Actions
fetchVersions: () => Promise<void>
createVersion: (input: CreateVersionInput) => Promise<AppVersion>
updateVersion: (id: string, input: UpdateVersionInput) => Promise<AppVersion>
deleteVersion: (id: string) => Promise<void>
toggleVersion: (id: string, isEnabled: boolean) => Promise<void>
uploadVersion: (input: UploadVersionInput) => Promise<AppVersion>
}
export const useVersionStore = create<VersionState>((set, get) => ({
// 实现...
}))
```
#### React Hooks (`hooks/use-versions.ts`)
```typescript
// 获取版本列表
export function useVersions() {
const { versions, isLoading, error, fetchVersions, setFilter } = useVersionStore()
useEffect(() => {
fetchVersions()
}, [filter.platform])
return { versions, isLoading, error, refetch: fetchVersions, setFilter }
}
// 获取单个版本
export function useVersion(id: string | null) { ... }
// 版本操作
export function useVersionActions() { ... }
```
### 4. Presentation Layer表示层
**职责**UI 渲染和用户交互。
#### 组件结构
```
presentation/
├── components/
│ ├── version-card.tsx # 版本信息卡片
│ ├── upload-modal.tsx # 上传新版本弹窗
│ └── edit-modal.tsx # 编辑版本弹窗
```
## 数据流
```
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ User │───▶│ Presentation│───▶│ Application │───▶│Infrastructure│
│ Action │ │ Component │ │ Store │ │ Repository │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
│ │ │
│ │ ▼
│ │ ┌─────────────┐
│ │ │ Admin API │
│ │ └─────────────┘
│ │ │
│ ◀───────────────────┘
│ │
◀───────────────────┘
┌─────────────┐
│ UI Update │
└─────────────┘
```
## 依赖关系
```
Presentation ──▶ Application ──▶ Domain ◀── Infrastructure
│ │ │ │
│ │ │ │
▼ ▼ ▼ ▼
React Zustand 纯TS接口 Axios
Next.js Hooks API实现
```
**关键原则**
- Domain 层不依赖任何外部层
- Infrastructure 依赖 Domain实现接口
- Application 依赖 Domain使用接口
- Presentation 依赖 Application使用 Hooks/Store
## 设计优势
1. **可测试性**每层都可以独立测试Infrastructure 可以被 Mock
2. **可维护性**:关注点分离,修改一层不影响其他层
3. **可扩展性**:新增功能只需在相应层添加代码
4. **可替换性**:可以轻松替换技术实现(如 Axios → Fetch
## 相关文档
- [API 文档](./API.md)
- [开发指南](./DEVELOPMENT.md)
- [测试指南](./TESTING.md)
- [部署指南](./DEPLOYMENT.md)