299 lines
11 KiB
Markdown
299 lines
11 KiB
Markdown
# 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)
|