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

8.4 KiB
Raw Blame History

Mobile Upgrade Admin - 开发指南

环境要求

工具 版本 说明
Node.js >= 18.x 运行环境
npm >= 9.x 包管理器
Git >= 2.x 版本控制

快速开始

1. 克隆项目

git clone https://git.gdzx.xyz/hailin/rwadurian.git
cd rwadurian/frontend/mobile-upgrade

2. 安装依赖

npm install

3. 配置环境变量

# 复制环境变量模板
cp .env.local.example .env.local

# 编辑配置
# NEXT_PUBLIC_API_URL=http://localhost:3000

4. 启动开发服务器

npm run dev

访问 http://localhost:3000 查看应用。

项目脚本

# 开发模式
npm run dev

# 生产构建
npm run build

# 启动生产服务
npm run start

# 代码检查
npm run lint

# 类型检查
npm run type-check

开发规范

目录结构规范

src/
├── domain/           # 领域层:纯 TypeScript无框架依赖
├── infrastructure/   # 基础设施层:外部服务交互
├── application/      # 应用层:业务逻辑和状态管理
├── presentation/     # 表示层React 组件
└── app/              # Next.js 页面路由

命名规范

类型 规范 示例
文件名 kebab-case version-card.tsx
组件名 PascalCase VersionCard
函数名 camelCase fetchVersions
常量 UPPER_SNAKE_CASE API_BASE_URL
类型/接口 PascalCase AppVersion

代码风格

项目使用 ESLint + Prettier 进行代码规范检查。

// .eslintrc.json
{
  "extends": ["next/core-web-vitals"]
}

开发流程

1. 新增功能开发流程

1. 在 Domain 层定义实体和接口
2. 在 Infrastructure 层实现 API 调用
3. 在 Application 层添加状态管理逻辑
4. 在 Presentation 层创建 UI 组件
5. 编写测试用例
6. 提交代码

2. 示例:添加新的 API 功能

Step 1: Domain 层 - 定义类型

// src/domain/entities/version.ts
export interface BatchDeleteInput {
  ids: string[]
}

Step 2: Domain 层 - 定义接口

// src/domain/repositories/version-repository.ts
export interface IVersionRepository {
  // ... 现有方法
  batchDelete(input: BatchDeleteInput): Promise<void>
}

Step 3: Infrastructure 层 - 实现接口

// src/infrastructure/repositories/version-repository-impl.ts
export class VersionRepositoryImpl implements IVersionRepository {
  // ... 现有方法

  async batchDelete(input: BatchDeleteInput): Promise<void> {
    await this.client.post('/api/v1/versions/batch-delete', input)
  }
}

Step 4: Application 层 - 添加状态管理

// src/application/stores/version-store.ts
interface VersionState {
  // ... 现有状态
  batchDeleteVersions: (ids: string[]) => Promise<void>
}

export const useVersionStore = create<VersionState>((set, get) => ({
  // ... 现有实现

  batchDeleteVersions: async (ids: string[]) => {
    set({ isLoading: true, error: null })
    try {
      await versionRepository.batchDelete({ ids })
      const { versions } = get()
      set({
        versions: versions.filter((v) => !ids.includes(v.id)),
        isLoading: false,
      })
    } catch (err) {
      set({
        error: err instanceof Error ? err.message : 'Failed to delete',
        isLoading: false,
      })
      throw err
    }
  },
}))

Step 5: Application 层 - 添加 Hook

// src/application/hooks/use-versions.ts
export function useVersionActions() {
  const { batchDeleteVersions, ... } = useVersionStore()

  return {
    batchDelete: batchDeleteVersions,
    // ... 其他方法
  }
}

Step 6: Presentation 层 - 使用

// src/presentation/components/batch-actions.tsx
export function BatchActions({ selectedIds }: { selectedIds: string[] }) {
  const { batchDelete } = useVersionActions()

  const handleBatchDelete = async () => {
    try {
      await batchDelete(selectedIds)
      toast.success('批量删除成功')
    } catch (err) {
      toast.error('批量删除失败')
    }
  }

  return (
    <button onClick={handleBatchDelete}>
      批量删除 ({selectedIds.length})
    </button>
  )
}

状态管理

Zustand Store 设计

// 状态结构
interface VersionState {
  // 数据状态
  versions: AppVersion[]
  selectedVersion: AppVersion | null

  // UI 状态
  isLoading: boolean
  error: string | null

  // 筛选状态
  filter: {
    platform?: Platform
    includeDisabled: boolean
  }

  // Actions
  fetchVersions: () => Promise<void>
  setFilter: (filter: Partial<VersionState['filter']>) => void
  clearError: () => void
}

使用 Hooks

// 在组件中使用
function VersionList() {
  const { versions, isLoading, error, refetch, setFilter } = useVersions()
  const { deleteVersion, toggleVersion } = useVersionActions()

  // 筛选
  const handleFilterChange = (platform: Platform | 'all') => {
    setFilter({ platform: platform === 'all' ? undefined : platform })
  }

  // 删除
  const handleDelete = async (id: string) => {
    await deleteVersion(id)
    refetch()
  }

  return (/* JSX */)
}

组件开发

组件结构规范

'use client'

import { useState, useEffect } from 'react'
import { useVersions } from '@/application'
import { AppVersion } from '@/domain'

// Props 接口定义
interface VersionCardProps {
  version: AppVersion
  onEdit: () => void
  onDelete: () => void
}

// 组件实现
export function VersionCard({ version, onEdit, onDelete }: VersionCardProps) {
  // Hooks
  const [isExpanded, setIsExpanded] = useState(false)

  // 事件处理
  const handleToggle = () => {
    setIsExpanded(!isExpanded)
  }

  // 渲染
  return (
    <div className="card">
      {/* 组件内容 */}
    </div>
  )
}

样式规范

使用 Tailwind CSS 原子类:

// 推荐
<button className="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700">
  提交
</button>

// 复用样式定义在 globals.css
<button className="btn btn-primary">提交</button>

全局样式定义:

/* src/app/globals.css */
@layer components {
  .btn {
    @apply px-4 py-2 rounded-lg font-medium transition-colors;
  }
  .btn-primary {
    @apply bg-blue-600 text-white hover:bg-blue-700;
  }
  .card {
    @apply bg-white rounded-lg shadow-sm border p-6;
  }
  .input {
    @apply w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500;
  }
}

调试技巧

1. React DevTools

安装浏览器扩展查看组件树和状态。

2. Zustand DevTools

import { devtools } from 'zustand/middleware'

export const useVersionStore = create<VersionState>()(
  devtools(
    (set, get) => ({
      // store 实现
    }),
    { name: 'version-store' }
  )
)

3. API 请求调试

// 在 api-client.ts 添加请求日志
apiClient.interceptors.request.use((config) => {
  console.log('API Request:', config.method?.toUpperCase(), config.url)
  return config
})

apiClient.interceptors.response.use(
  (response) => {
    console.log('API Response:', response.status, response.config.url)
    return response
  },
  (error) => {
    console.error('API Error:', error.response?.status, error.config.url)
    return Promise.reject(error)
  }
)

常见问题

1. 类型错误

确保导入路径使用别名:

// 正确
import { AppVersion } from '@/domain'

// 错误
import { AppVersion } from '../../../domain/entities/version'

2. 环境变量不生效

Next.js 要求客户端环境变量以 NEXT_PUBLIC_ 开头:

# 正确 - 客户端可访问
NEXT_PUBLIC_API_URL=http://localhost:3000

# 错误 - 仅服务端可访问
API_URL=http://localhost:3000

3. 热更新不工作

# 删除 .next 缓存目录
rm -rf .next
npm run dev

相关文档