# 健身房管理系统基础设施重构实现计划

> **面向 AI 代理的工作者：** 必需子技能：使用 superpowers:subagent-driven-development（推荐）或 superpowers:executing-plans 逐任务实现此计划。步骤使用复选框（`- [ ]`）语法来跟踪进度。

**目标：** 将通用后台管理系统重构为健身房管理系统，包括项目重命名、包名修改、测试迁移和移动端项目创建

**架构：** 采用分阶段渐进重构策略，共 5 个阶段：后端重构 → 前端重构 → 测试迁移 → UniApp 创建 → 根目录整理

**技术栈：** Java 21 + Spring Boot 3.5.13 + Maven (后端) | Vue 3 + TypeScript + Vite (前端) | UniApp + Vue 3 (移动端) | Playwright (E2E 测试)

---

## 文件结构

### 阶段 1：后端项目重构（gym-manage-api）

**重命名的目录：**
- `novalon-manage-api/` → `gym-manage-api/`

**修改的文件：**
- `gym-manage-api/pom.xml` - Maven 父 POM 配置
- `gym-manage-api/manage-app/pom.xml` - 主应用模块配置
- `gym-manage-api/manage-gateway/pom.xml` - 网关模块配置
- `gym-manage-api/manage-sys/pom.xml` - 系统模块配置
- `gym-manage-api/manage-db/pom.xml` - 数据库模块配置
- `gym-manage-api/manage-common/pom.xml` - 公共模块配置
- `gym-manage-api/manage-audit/pom.xml` - 审计模块配置
- `gym-manage-api/manage-notify/pom.xml` - 通知模块配置
- `gym-manage-api/manage-file/pom.xml` - 文件模块配置
- `gym-manage-api/manage-app/src/main/resources/application.yml` - 应用配置
- `gym-manage-api/manage-app/src/main/resources/application-dev.yml` - 开发环境配置
- `gym-manage-api/manage-app/src/main/resources/application-prod.yml` - 生产环境配置
- `gym-manage-api/manage-gateway/src/main/resources/application.yml` - 网关配置
- 所有 Java 文件 - 包名和 import 语句

**重命名的包目录：**
- `gym-manage-api/*/src/main/java/cn/novalon/manage/` → `gym-manage-api/*/src/main/java/cn/novalon/gym/manage/`
- `gym-manage-api/*/src/test/java/cn/novalon/manage/` → `gym-manage-api/*/src/test/java/cn/novalon/gym/manage/`

### 阶段 2：前端项目重构（gym-manage-web）

**重命名的目录：**
- `novalon-manage-web/` → `gym-manage-web/`

**修改的文件：**
- `gym-manage-web/package.json` - NPM 项目配置
- `gym-manage-web/index.html` - HTML 入口文件
- `gym-manage-web/vite.config.ts` - Vite 构建配置

### 阶段 3：测试文件迁移（e2e-tests）

**创建的目录：**
- `e2e-tests/` - 独立测试项目根目录
- `e2e-tests/e2e/` - 测试用例目录
- `e2e-tests/playwright/` - Playwright 配置目录
- `e2e-tests/scripts/` - 测试脚本目录

**迁移的文件：**
- `gym-manage-web/e2e/*` → `e2e-tests/e2e/`
- `gym-manage-web/playwright/*` → `e2e-tests/playwright/`
- `gym-manage-web/scripts/*` → `e2e-tests/scripts/`
- `gym-manage-web/playwright.config.ts` → `e2e-tests/playwright.config.ts`
- `gym-manage-web/playwright-complete.config.ts` → `e2e-tests/playwright-complete.config.ts`
- `gym-manage-web/playwright-simple.config.ts` → `e2e-tests/playwright-simple.config.ts`

**创建的文件：**
- `e2e-tests/package.json` - 测试项目依赖配置

**删除的文件：**
- `package.json` (根目录) - 测试依赖已迁移

**修改的文件：**
- `e2e-tests/playwright.config.ts` - 更新测试路径配置

### 阶段 4：创建 UniApp 项目（gym-manage-uniapp）

**创建的目录：**
- `gym-manage-uniapp/` - 移动端项目根目录
- `gym-manage-uniapp/src/` - 源代码目录
- `gym-manage-uniapp/src/pages/` - 页面目录
- `gym-manage-uniapp/src/pages/index/` - 首页目录
- `gym-manage-uniapp/src/pages/login/` - 登录页目录
- `gym-manage-uniapp/src/components/` - 组件目录
- `gym-manage-uniapp/src/api/` - API 接口目录
- `gym-manage-uniapp/src/store/` - 状态管理目录
- `gym-manage-uniapp/src/utils/` - 工具函数目录
- `gym-manage-uniapp/src/static/` - 静态资源目录

**创建的文件：**
- `gym-manage-uniapp/package.json` - NPM 项目配置
- `gym-manage-uniapp/tsconfig.json` - TypeScript 配置
- `gym-manage-uniapp/vite.config.ts` - Vite 构建配置
- `gym-manage-uniapp/src/manifest.json` - UniApp 应用配置
- `gym-manage-uniapp/src/pages.json` - UniApp 页面配置
- `gym-manage-uniapp/src/main.ts` - 应用入口
- `gym-manage-uniapp/src/App.vue` - 应用根组件
- `gym-manage-uniapp/src/pages/index/index.vue` - 首页组件
- `gym-manage-uniapp/src/pages/login/index.vue` - 登录页组件
- `gym-manage-uniapp/src/api/request.ts` - 请求封装
- `gym-manage-uniapp/src/store/index.ts` - Pinia 配置
- `gym-manage-uniapp/src/store/user.ts` - 用户状态管理

### 阶段 5：根目录整理与文档更新

**修改的文件：**
- `docker-compose.yml` - Docker 编排配置
- `Jenkinsfile` - CI/CD 配置
- `README.md` - 项目文档

---

## 阶段 1：后端项目重构（gym-manage-api）

### 任务 1.1：重命名后端项目目录

**文件：**
- 重命名：`novalon-manage-api/` → `gym-manage-api/`

- [ ] **步骤 1：使用 Git 重命名项目目录**

```bash
git mv novalon-manage-api gym-manage-api
```

- [ ] **步骤 2：验证重命名结果**

运行：`ls -la | grep gym-manage-api`
预期：显示 `gym-manage-api` 目录

---

### 任务 1.2：修改 Maven 父 POM 配置

**文件：**
- 修改：`gym-manage-api/pom.xml`

- [ ] **步骤 1：更新 Maven 父 POM 的 groupId**

修改 `gym-manage-api/pom.xml` 第 21 行：

```xml
<groupId>cn.novalon.gym.manage</groupId>
```

- [ ] **步骤 2：更新 Maven 父 POM 的 artifactId**

修改 `gym-manage-api/pom.xml` 第 22 行：

```xml
<artifactId>gym-manage-api</artifactId>
```

- [ ] **步骤 3：更新 Maven 父 POM 的 name**

修改 `gym-manage-api/pom.xml` 第 26 行：

```xml
<name>Gym Manage API</name>
```

- [ ] **步骤 4：更新 Maven 父 POM 的 description**

修改 `gym-manage-api/pom.xml` 第 27 行：

```xml
<description>Gym Management System API</description>
```

---

### 任务 1.3：修改 manage-app 模块 POM 配置

**文件：**
- 修改：`gym-manage-api/manage-app/pom.xml`

- [ ] **步骤 1：更新 parent 引用的 groupId**

修改 `gym-manage-api/manage-app/pom.xml`：

```xml
<parent>
    <groupId>cn.novalon.gym.manage</groupId>
    <artifactId>gym-manage-api</artifactId>
    <version>1.0.0</version>
</parent>
```

- [ ] **步骤 2：更新模块的 groupId**

```xml
<groupId>cn.novalon.gym.manage</groupId>
```

- [ ] **步骤 3：更新模块的 artifactId**

```xml
<artifactId>manage-app</artifactId>
```

---

### 任务 1.4：修改 manage-gateway 模块 POM 配置

**文件：**
- 修改：`gym-manage-api/manage-gateway/pom.xml`

- [ ] **步骤 1：更新 parent 引用的 groupId**

修改 `gym-manage-api/manage-gateway/pom.xml`：

```xml
<parent>
    <groupId>cn.novalon.gym.manage</groupId>
    <artifactId>gym-manage-api</artifactId>
    <version>1.0.0</version>
</parent>
```

- [ ] **步骤 2：更新模块的 groupId**

```xml
<groupId>cn.novalon.gym.manage</groupId>
```

---

### 任务 1.5：修改 manage-sys 模块 POM 配置

**文件：**
- 修改：`gym-manage-api/manage-sys/pom.xml`

- [ ] **步骤 1：更新 parent 引用的 groupId**

修改 `gym-manage-api/manage-sys/pom.xml`：

```xml
<parent>
    <groupId>cn.novalon.gym.manage</groupId>
    <artifactId>gym-manage-api</artifactId>
    <version>1.0.0</version>
</parent>
```

- [ ] **步骤 2：更新模块的 groupId**

```xml
<groupId>cn.novalon.gym.manage</groupId>
```

---

### 任务 1.6：修改 manage-db 模块 POM 配置

**文件：**
- 修改：`gym-manage-api/manage-db/pom.xml`

- [ ] **步骤 1：更新 parent 引用的 groupId**

修改 `gym-manage-api/manage-db/pom.xml`：

```xml
<parent>
    <groupId>cn.novalon.gym.manage</groupId>
    <artifactId>gym-manage-api</artifactId>
    <version>1.0.0</version>
</parent>
```

- [ ] **步骤 2：更新模块的 groupId**

```xml
<groupId>cn.novalon.gym.manage</groupId>
```

---

### 任务 1.7：修改 manage-common 模块 POM 配置

**文件：**
- 修改：`gym-manage-api/manage-common/pom.xml`

- [ ] **步骤 1：更新 parent 引用的 groupId**

修改 `gym-manage-api/manage-common/pom.xml`：

```xml
<parent>
    <groupId>cn.novalon.gym.manage</groupId>
    <artifactId>gym-manage-api</artifactId>
    <version>1.0.0</version>
</parent>
```

- [ ] **步骤 2：更新模块的 groupId**

```xml
<groupId>cn.novalon.gym.manage</groupId>
```

---

### 任务 1.8：修改 manage-audit 模块 POM 配置

**文件：**
- 修改：`gym-manage-api/manage-audit/pom.xml`

- [ ] **步骤 1：更新 parent 引用的 groupId**

修改 `gym-manage-api/manage-audit/pom.xml`：

```xml
<parent>
    <groupId>cn.novalon.gym.manage</groupId>
    <artifactId>gym-manage-api</artifactId>
    <version>1.0.0</version>
</parent>
```

- [ ] **步骤 2：更新模块的 groupId**

```xml
<groupId>cn.novalon.gym.manage</groupId>
```

---

### 任务 1.9：修改 manage-notify 模块 POM 配置

**文件：**
- 修改：`gym-manage-api/manage-notify/pom.xml`

- [ ] **步骤 1：更新 parent 引用的 groupId**

修改 `gym-manage-api/manage-notify/pom.xml`：

```xml
<parent>
    <groupId>cn.novalon.gym.manage</groupId>
    <artifactId>gym-manage-api</artifactId>
    <version>1.0.0</version>
</parent>
```

- [ ] **步骤 2：更新模块的 groupId**

```xml
<groupId>cn.novalon.gym.manage</groupId>
```

---

### 任务 1.10：修改 manage-file 模块 POM 配置

**文件：**
- 修改：`gym-manage-api/manage-file/pom.xml`

- [ ] **步骤 1：更新 parent 引用的 groupId**

修改 `gym-manage-api/manage-file/pom.xml`：

```xml
<parent>
    <groupId>cn.novalon.gym.manage</groupId>
    <artifactId>gym-manage-api</artifactId>
    <version>1.0.0</version>
</parent>
```

- [ ] **步骤 2：更新模块的 groupId**

```xml
<groupId>cn.novalon.gym.manage</groupId>
```

---

### 任务 1.11：重命名 Java 包目录结构

**文件：**
- 重命名：所有模块的 Java 包目录

- [ ] **步骤 1：重命名 manage-app 的主代码包目录**

```bash
cd gym-manage-api/manage-app/src/main/java/cn/novalon
git mv manage gym/manage
```

- [ ] **步骤 2：重命名 manage-app 的测试代码包目录**

```bash
cd gym-manage-api/manage-app/src/test/java/cn/novalon
git mv manage gym/manage
```

- [ ] **步骤 3：重命名 manage-gateway 的主代码包目录**

```bash
cd gym-manage-api/manage-gateway/src/main/java/cn/novalon
git mv manage gym/manage
```

- [ ] **步骤 4：重命名 manage-gateway 的测试代码包目录**

```bash
cd gym-manage-api/manage-gateway/src/test/java/cn/novalon
git mv manage gym/manage
```

- [ ] **步骤 5：重命名 manage-sys 的主代码包目录**

```bash
cd gym-manage-api/manage-sys/src/main/java/cn/novalon
git mv manage gym/manage
```

- [ ] **步骤 6：重命名 manage-sys 的测试代码包目录**

```bash
cd gym-manage-api/manage-sys/src/test/java/cn/novalon
git mv manage gym/manage
```

- [ ] **步骤 7：重命名 manage-db 的主代码包目录**

```bash
cd gym-manage-api/manage-db/src/main/java/cn/novalon
git mv manage gym/manage
```

- [ ] **步骤 8：重命名 manage-db 的测试代码包目录**

```bash
cd gym-manage-api/manage-db/src/test/java/cn/novalon
git mv manage gym/manage
```

- [ ] **步骤 9：重命名 manage-common 的主代码包目录**

```bash
cd gym-manage-api/manage-common/src/main/java/cn/novalon
git mv manage gym/manage
```

- [ ] **步骤 10：重命名 manage-common 的测试代码包目录**

```bash
cd gym-manage-api/manage-common/src/test/java/cn/novalon
git mv manage gym/manage
```

- [ ] **步骤 11：重命名 manage-audit 的主代码包目录**

```bash
cd gym-manage-api/manage-audit/src/main/java/cn/novalon
git mv manage gym/manage
```

- [ ] **步骤 12：重命名 manage-audit 的测试代码包目录**

```bash
cd gym-manage-api/manage-audit/src/test/java/cn/novalon
git mv manage gym/manage
```

- [ ] **步骤 13：重命名 manage-notify 的主代码包目录**

```bash
cd gym-manage-api/manage-notify/src/main/java/cn/novalon
git mv manage gym/manage
```

- [ ] **步骤 14：重命名 manage-notify 的测试代码包目录**

```bash
cd gym-manage-api/manage-notify/src/test/java/cn/novalon
git mv manage gym/manage
```

- [ ] **步骤 15：重命名 manage-file 的主代码包目录**

```bash
cd gym-manage-api/manage-file/src/main/java/cn/novalon
git mv manage gym/manage
```

- [ ] **步骤 16：重命名 manage-file 的测试代码包目录**

```bash
cd gym-manage-api/manage-file/src/test/java/cn/novalon
git mv manage gym/manage
```

---

### 任务 1.12：批量更新 Java 文件的 package 声明

**文件：**
- 修改：所有 Java 文件

- [ ] **步骤 1：使用 sed 批量替换 package 声明**

```bash
find gym-manage-api -type f -name "*.java" -exec sed -i '' 's/^package cn\.novalon\.manage/package cn.novalon.gym.manage/g' {} +
```

- [ ] **步骤 2：验证替换结果**

运行：`grep -r "^package cn.novalon.manage" gym-manage-api --include="*.java" | head -5`
预期：无输出（所有 package 声明已更新）

---

### 任务 1.13：批量更新 Java 文件的 import 语句

**文件：**
- 修改：所有 Java 文件

- [ ] **步骤 1：使用 sed 批量替换 import 语句**

```bash
find gym-manage-api -type f -name "*.java" -exec sed -i '' 's/import cn\.novalon\.manage/import cn.novalon.gym.manage/g' {} +
```

- [ ] **步骤 2：验证替换结果**

运行：`grep -r "import cn.novalon.manage" gym-manage-api --include="*.java" | head -5`
预期：无输出（所有 import 语句已更新）

---

### 任务 1.14：更新 Spring Boot 配置文件

**文件：**
- 修改：`gym-manage-api/manage-app/src/main/resources/application.yml`
- 修改：`gym-manage-api/manage-app/src/main/resources/application-dev.yml`
- 修改：`gym-manage-api/manage-app/src/main/resources/application-prod.yml`
- 修改：`gym-manage-api/manage-gateway/src/main/resources/application.yml`

- [ ] **步骤 1：更新 manage-app 的 application.yml**

修改 `gym-manage-api/manage-app/src/main/resources/application.yml`：

```yaml
spring:
  application:
    name: gym-manage-api
```

- [ ] **步骤 2：更新 manage-gateway 的 application.yml**

修改 `gym-manage-api/manage-gateway/src/main/resources/application.yml`：

```yaml
spring:
  application:
    name: gym-manage-gateway
```

---

### 任务 1.15：验证后端项目编译

**文件：**
- 无文件修改，仅验证

- [ ] **步骤 1：清理旧的编译产物**

```bash
cd gym-manage-api
mvn clean
```

预期：`BUILD SUCCESS`

- [ ] **步骤 2：编译项目**

```bash
mvn compile
```

预期：`BUILD SUCCESS`，无编译错误

- [ ] **步骤 3：运行单元测试**

```bash
mvn test
```

预期：`BUILD SUCCESS`，所有测试通过

---

### 任务 1.16：提交阶段 1 的变更

**文件：**
- 无文件修改，仅提交

- [ ] **步骤 1：查看变更状态**

```bash
git status
```

预期：显示所有修改的文件

- [ ] **步骤 2：提交变更**

```bash
git add .
git commit -m "refactor(backend): 重命名后端项目为 gym-manage-api，修改包名为 cn.novalon.gym.manage"
```

预期：提交成功

---

## 阶段 2：前端项目重构（gym-manage-web）

### 任务 2.1：重命名前端项目目录

**文件：**
- 重命名：`novalon-manage-web/` → `gym-manage-web/`

- [ ] **步骤 1：使用 Git 重命名项目目录**

```bash
git mv novalon-manage-web gym-manage-web
```

- [ ] **步骤 2：验证重命名结果**

运行：`ls -la | grep gym-manage-web`
预期：显示 `gym-manage-web` 目录

---

### 任务 2.2：修改 package.json 配置

**文件：**
- 修改：`gym-manage-web/package.json`

- [ ] **步骤 1：更新项目名称**

修改 `gym-manage-web/package.json` 第 2 行：

```json
"name": "gym-manage-web",
```

- [ ] **步骤 2：更新项目描述**

修改 `gym-manage-web/package.json` 第 4 行：

```json
"description": "Gym Management System Frontend",
```

---

### 任务 2.3：修改 index.html 页面标题

**文件：**
- 修改：`gym-manage-web/index.html`

- [ ] **步骤 1：更新页面标题**

修改 `gym-manage-web/index.html`：

```html
<title>健身房管理系统</title>
```

---

### 任务 2.4：验证前端项目构建

**文件：**
- 无文件修改，仅验证

- [ ] **步骤 1：安装依赖**

```bash
cd gym-manage-web
npm install
```

预期：依赖安装成功，无错误

- [ ] **步骤 2：构建项目**

```bash
npm run build
```

预期：构建成功，生成 `dist/` 目录

---

### 任务 2.5：提交阶段 2 的变更

**文件：**
- 无文件修改，仅提交

- [ ] **步骤 1：查看变更状态**

```bash
git status
```

预期：显示所有修改的文件

- [ ] **步骤 2：提交变更**

```bash
git add .
git commit -m "refactor(frontend): 重命名前端项目为 gym-manage-web"
```

预期：提交成功

---

## 阶段 3：测试文件迁移（e2e-tests）

### 任务 3.1：创建 e2e-tests 目录结构

**文件：**
- 创建：`e2e-tests/` 目录

- [ ] **步骤 1：创建测试项目根目录**

```bash
mkdir -p e2e-tests
```

- [ ] **步骤 2：验证目录创建**

运行：`ls -la | grep e2e-tests`
预期：显示 `e2e-tests` 目录

---

### 任务 3.2：迁移测试用例目录

**文件：**
- 迁移：`gym-manage-web/e2e/` → `e2e-tests/e2e/`

- [ ] **步骤 1：使用 Git 迁移测试用例目录**

```bash
git mv gym-manage-web/e2e e2e-tests/e2e
```

- [ ] **步骤 2：验证迁移结果**

运行：`ls -la e2e-tests/`
预期：显示 `e2e` 目录

---

### 任务 3.3：迁移 Playwright 配置目录

**文件：**
- 迁移：`gym-manage-web/playwright/` → `e2e-tests/playwright/`

- [ ] **步骤 1：使用 Git 迁移 Playwright 配置目录**

```bash
git mv gym-manage-web/playwright e2e-tests/playwright
```

- [ ] **步骤 2：验证迁移结果**

运行：`ls -la e2e-tests/`
预期：显示 `playwright` 目录

---

### 任务 3.4：迁移测试脚本目录

**文件：**
- 迁移：`gym-manage-web/scripts/` → `e2e-tests/scripts/`

- [ ] **步骤 1：使用 Git 迁移测试脚本目录**

```bash
git mv gym-manage-web/scripts e2e-tests/scripts
```

- [ ] **步骤 2：验证迁移结果**

运行：`ls -la e2e-tests/`
预期：显示 `scripts` 目录

---

### 任务 3.5：迁移 Playwright 配置文件

**文件：**
- 迁移：`gym-manage-web/playwright.config.ts` → `e2e-tests/playwright.config.ts`
- 迁移：`gym-manage-web/playwright-complete.config.ts` → `e2e-tests/playwright-complete.config.ts`
- 迁移：`gym-manage-web/playwright-simple.config.ts` → `e2e-tests/playwright-simple.config.ts`

- [ ] **步骤 1：迁移主配置文件**

```bash
git mv gym-manage-web/playwright.config.ts e2e-tests/
```

- [ ] **步骤 2：迁移完整配置文件**

```bash
git mv gym-manage-web/playwright-complete.config.ts e2e-tests/
```

- [ ] **步骤 3：迁移简化配置文件**

```bash
git mv gym-manage-web/playwright-simple.config.ts e2e-tests/
```

- [ ] **步骤 4：验证迁移结果**

运行：`ls -la e2e-tests/*.ts`
预期：显示三个配置文件

---

### 任务 3.6：创建 e2e-tests 的 package.json

**文件：**
- 创建：`e2e-tests/package.json`

- [ ] **步骤 1：创建 package.json 文件**

创建 `e2e-tests/package.json`：

```json
{
  "name": "gym-manage-e2e-tests",
  "version": "1.0.0",
  "description": "Gym Management System E2E Tests",
  "type": "module",
  "scripts": {
    "test:e2e": "playwright test",
    "test:e2e:smoke": "playwright test --project=smoke",
    "test:e2e:journeys": "playwright test --project=journeys",
    "test:e2e:headed": "playwright test --headed",
    "test:e2e:debug": "playwright test --debug",
    "test:e2e:perf": "node scripts/measure-e2e-performance.js",
    "test:perf": "node scripts/performance-test.js performance",
    "test:load": "node scripts/performance-test.js load",
    "test:perf:all": "node scripts/performance-test.js all"
  },
  "devDependencies": {
    "@playwright/test": "^1.40.1",
    "@types/node": "^20.10.0",
    "typescript": "^5.9.3"
  }
}
```

---

### 任务 3.7：删除根目录的 package.json

**文件：**
- 删除：`package.json`（根目录）

- [ ] **步骤 1：删除根目录的 package.json**

```bash
git rm package.json
```

- [ ] **步骤 2：验证删除结果**

运行：`ls -la | grep package.json`
预期：无输出（根目录无 package.json）

---

### 任务 3.8：更新 Playwright 配置文件路径

**文件：**
- 修改：`e2e-tests/playwright.config.ts`

- [ ] **步骤 1：检查当前配置**

运行：`head -20 e2e-tests/playwright.config.ts`
预期：查看当前配置内容

- [ ] **步骤 2：确认 baseURL 配置正确**

确保 `e2e-tests/playwright.config.ts` 中的 `baseURL` 指向前端服务：

```typescript
use: {
  baseURL: 'http://localhost:3001',
}
```

---

### 任务 3.9：验证测试运行

**文件：**
- 无文件修改，仅验证

- [ ] **步骤 1：安装测试依赖**

```bash
cd e2e-tests
npm install
```

预期：依赖安装成功

- [ ] **步骤 2：运行冒烟测试**

```bash
npm run test:e2e:smoke
```

预期：测试运行正常（可能失败，因为需要前端服务运行）

---

### 任务 3.10：提交阶段 3 的变更

**文件：**
- 无文件修改，仅提交

- [ ] **步骤 1：查看变更状态**

```bash
git status
```

预期：显示所有修改的文件

- [ ] **步骤 2：提交变更**

```bash
git add .
git commit -m "refactor(test): 创建独立的 e2e-tests 目录，迁移测试文件"
```

预期：提交成功

---

## 阶段 4：创建 UniApp 项目（gym-manage-uniapp）

### 任务 4.1：创建 UniApp 项目目录结构

**文件：**
- 创建：`gym-manage-uniapp/` 及其子目录

- [ ] **步骤 1：创建项目根目录和主要子目录**

```bash
mkdir -p gym-manage-uniapp/src/{pages/{index,login},components,api,store,utils,static}
```

- [ ] **步骤 2：验证目录创建**

运行：`tree gym-manage-uniapp -L 3`
预期：显示完整的目录结构

---

### 任务 4.2：创建 package.json

**文件：**
- 创建：`gym-manage-uniapp/package.json`

- [ ] **步骤 1：创建 package.json 文件**

创建 `gym-manage-uniapp/package.json`：

```json
{
  "name": "gym-manage-uniapp",
  "version": "1.0.0",
  "description": "Gym Management System Mobile App",
  "type": "module",
  "scripts": {
    "dev:h5": "uni -p h5",
    "build:h5": "uni build -p h5",
    "dev:mp-weixin": "uni -p mp-weixin",
    "build:mp-weixin": "uni build -p mp-weixin",
    "dev:app": "uni -p app",
    "build:app": "uni build -p app"
  },
  "dependencies": {
    "@dcloudio/uni-app": "3.0.0-4010520240507001",
    "@dcloudio/uni-app-plus": "3.0.0-4010520240507001",
    "@dcloudio/uni-components": "3.0.0-4010520240507001",
    "@dcloudio/uni-h5": "3.0.0-4010520240507001",
    "@dcloudio/uni-mp-weixin": "3.0.0-4010520240507001",
    "pinia": "^3.0.4",
    "vue": "^3.5.26"
  },
  "devDependencies": {
    "@dcloudio/types": "^3.4.8",
    "@dcloudio/uni-automator": "3.0.0-4010520240507001",
    "@dcloudio/uni-cli-shared": "3.0.0-4010520240507001",
    "@dcloudio/uni-stacktracey": "3.0.0-4010520240507001",
    "@dcloudio/vite-plugin-uni": "3.0.0-4010520240507001",
    "@types/node": "^20.10.0",
    "typescript": "^5.9.3",
    "vite": "^7.3.1"
  }
}
```

---

### 任务 4.3：创建 TypeScript 配置

**文件：**
- 创建：`gym-manage-uniapp/tsconfig.json`

- [ ] **步骤 1：创建 tsconfig.json 文件**

创建 `gym-manage-uniapp/tsconfig.json`：

```json
{
  "compilerOptions": {
    "target": "ESNext",
    "useDefineForClassFields": true,
    "module": "ESNext",
    "moduleResolution": "Node",
    "strict": true,
    "jsx": "preserve",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "esModuleInterop": true,
    "lib": ["ESNext", "DOM"],
    "skipLibCheck": true,
    "noEmit": true,
    "paths": {
      "@/*": ["./src/*"]
    },
    "types": [
      "@dcloudio/types"
    ]
  },
  "include": [
    "src/**/*.ts",
    "src/**/*.d.ts",
    "src/**/*.tsx",
    "src/**/*.vue"
  ],
  "exclude": [
    "node_modules",
    "dist",
    "unpackage"
  ]
}
```

---

### 任务 4.4：创建 Vite 配置

**文件：**
- 创建：`gym-manage-uniapp/vite.config.ts`

- [ ] **步骤 1：创建 vite.config.ts 文件**

创建 `gym-manage-uniapp/vite.config.ts`：

```typescript
import { defineConfig } from 'vite'
import uni from '@dcloudio/vite-plugin-uni'
import { resolve } from 'path'

export default defineConfig({
  plugins: [uni()],
  resolve: {
    alias: {
      '@': resolve(__dirname, 'src')
    }
  },
  server: {
    port: 3002,
    host: '0.0.0.0',
    proxy: {
      '/api': {
        target: 'http://localhost:8084',
        changeOrigin: true
      }
    }
  }
})
```

---

### 任务 4.5：创建 UniApp 应用配置

**文件：**
- 创建：`gym-manage-uniapp/src/manifest.json`

- [ ] **步骤 1：创建 manifest.json 文件**

创建 `gym-manage-uniapp/src/manifest.json`：

```json
{
  "name": "健身房管理系统",
  "appid": "",
  "description": "健身房管理移动端应用",
  "versionName": "1.0.0",
  "versionCode": "100",
  "transformPx": false,
  "app-plus": {
    "usingComponents": true,
    "nvueStyleCompiler": "uni-app",
    "compilerVersion": 3,
    "splashscreen": {
      "alwaysShowBeforeRender": true,
      "waiting": true,
      "autoclose": true,
      "delay": 0
    },
    "modules": {},
    "distribute": {
      "android": {
        "permissions": []
      },
      "ios": {},
      "sdkConfigs": {}
    }
  },
  "quickapp": {},
  "mp-weixin": {
    "appid": "",
    "setting": {
      "urlCheck": false
    },
    "usingComponents": true
  },
  "mp-alipay": {
    "usingComponents": true
  },
  "mp-baidu": {
    "usingComponents": true
  },
  "mp-toutiao": {
    "usingComponents": true
  },
  "uniStatistics": {
    "enable": false
  },
  "h5": {
    "title": "健身房管理系统",
    "router": {
      "mode": "hash",
      "base": "./"
    }
  }
}
```

---

### 任务 4.6：创建 UniApp 页面配置

**文件：**
- 创建：`gym-manage-uniapp/src/pages.json`

- [ ] **步骤 1：创建 pages.json 文件**

创建 `gym-manage-uniapp/src/pages.json`：

```json
{
  "pages": [
    {
      "path": "pages/index/index",
      "style": {
        "navigationBarTitleText": "首页"
      }
    },
    {
      "path": "pages/login/index",
      "style": {
        "navigationBarTitleText": "登录"
      }
    }
  ],
  "globalStyle": {
    "navigationBarTextStyle": "black",
    "navigationBarTitleText": "健身房管理",
    "navigationBarBackgroundColor": "#F8F8F8",
    "backgroundColor": "#F8F8F8"
  },
  "tabBar": {
    "color": "#7A7E83",
    "selectedColor": "#007AFF",
    "borderStyle": "black",
    "backgroundColor": "#F8F8F8",
    "list": [
      {
        "pagePath": "pages/index/index",
        "text": "首页"
      }
    ]
  }
}
```

---

### 任务 4.7：创建应用入口文件

**文件：**
- 创建：`gym-manage-uniapp/src/main.ts`
- 创建：`gym-manage-uniapp/src/App.vue`

- [ ] **步骤 1：创建 main.ts 文件**

创建 `gym-manage-uniapp/src/main.ts`：

```typescript
import { createSSRApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'

export function createApp() {
  const app = createSSRApp(App)
  const pinia = createPinia()
  
  app.use(pinia)
  
  return {
    app,
    pinia
  }
}
```

- [ ] **步骤 2：创建 App.vue 文件**

创建 `gym-manage-uniapp/src/App.vue`：

```vue
<script setup lang="ts">
import { onLaunch, onShow, onHide } from '@dcloudio/uni-app'

onLaunch(() => {
  console.log('App Launch')
})

onShow(() => {
  console.log('App Show')
})

onHide(() => {
  console.log('App Hide')
})
</script>

<style>
/* 全局样式 */
page {
  background-color: #f8f8f8;
}
</style>
```

---

### 任务 4.8：创建首页组件

**文件：**
- 创建：`gym-manage-uniapp/src/pages/index/index.vue`

- [ ] **步骤 1：创建首页组件文件**

创建 `gym-manage-uniapp/src/pages/index/index.vue`：

```vue
<template>
  <view class="container">
    <view class="header">
      <text class="title">健身房管理系统</text>
      <text class="subtitle">移动端应用</text>
    </view>
    
    <view class="content">
      <text class="description">欢迎使用健身房管理系统移动端应用</text>
    </view>
  </view>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const title = ref('健身房管理系统')
</script>

<style scoped>
.container {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 40rpx;
}

.header {
  text-align: center;
  margin-bottom: 60rpx;
}

.title {
  font-size: 48rpx;
  font-weight: bold;
  color: #333;
  display: block;
  margin-bottom: 20rpx;
}

.subtitle {
  font-size: 28rpx;
  color: #666;
  display: block;
}

.content {
  text-align: center;
}

.description {
  font-size: 32rpx;
  color: #999;
}
</style>
```

---

### 任务 4.9：创建登录页组件

**文件：**
- 创建：`gym-manage-uniapp/src/pages/login/index.vue`

- [ ] **步骤 1：创建登录页组件文件**

创建 `gym-manage-uniapp/src/pages/login/index.vue`：

```vue
<template>
  <view class="login-container">
    <view class="login-header">
      <text class="login-title">健身房管理系统</text>
    </view>
    
    <view class="login-form">
      <view class="form-item">
        <input 
          class="input" 
          type="text" 
          v-model="username" 
          placeholder="请输入用户名"
        />
      </view>
      
      <view class="form-item">
        <input 
          class="input" 
          type="password" 
          v-model="password" 
          placeholder="请输入密码"
        />
      </view>
      
      <button class="login-btn" @click="handleLogin">登录</button>
    </view>
  </view>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const username = ref('')
const password = ref('')

const handleLogin = () => {
  console.log('登录:', username.value, password.value)
  uni.showToast({
    title: '功能待实现',
    icon: 'none'
  })
}
</script>

<style scoped>
.login-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 80rpx 40rpx;
}

.login-header {
  margin-bottom: 80rpx;
}

.login-title {
  font-size: 48rpx;
  font-weight: bold;
  color: #333;
}

.login-form {
  width: 100%;
}

.form-item {
  margin-bottom: 40rpx;
}

.input {
  width: 100%;
  height: 88rpx;
  padding: 0 30rpx;
  border: 1rpx solid #ddd;
  border-radius: 8rpx;
  font-size: 32rpx;
}

.login-btn {
  width: 100%;
  height: 88rpx;
  line-height: 88rpx;
  background-color: #007AFF;
  color: #fff;
  border: none;
  border-radius: 8rpx;
  font-size: 32rpx;
}
</style>
```

---

### 任务 4.10：创建 API 请求封装

**文件：**
- 创建：`gym-manage-uniapp/src/api/request.ts`

- [ ] **步骤 1：创建请求封装文件**

创建 `gym-manage-uniapp/src/api/request.ts`：

```typescript
const BASE_URL = 'http://localhost:8084/api'

interface RequestOptions {
  url: string
  method?: 'GET' | 'POST' | 'PUT' | 'DELETE'
  data?: any
  header?: Record<string, string>
}

interface Response<T = any> {
  code: number
  message: string
  data: T
}

export function request<T = any>(options: RequestOptions): Promise<Response<T>> {
  return new Promise((resolve, reject) => {
    uni.request({
      url: BASE_URL + options.url,
      method: options.method || 'GET',
      data: options.data,
      header: {
        'Content-Type': 'application/json',
        ...options.header
      },
      success: (res: any) => {
        if (res.statusCode === 200) {
          resolve(res.data as Response<T>)
        } else {
          reject(new Error(`请求失败: ${res.statusCode}`))
        }
      },
      fail: (err: any) => {
        reject(new Error(`网络错误: ${err.errMsg}`))
      }
    })
  })
}

export function get<T = any>(url: string, data?: any): Promise<Response<T>> {
  return request<T>({ url, method: 'GET', data })
}

export function post<T = any>(url: string, data?: any): Promise<Response<T>> {
  return request<T>({ url, method: 'POST', data })
}

export function put<T = any>(url: string, data?: any): Promise<Response<T>> {
  return request<T>({ url, method: 'PUT', data })
}

export function del<T = any>(url: string, data?: any): Promise<Response<T>> {
  return request<T>({ url, method: 'DELETE', data })
}
```

---

### 任务 4.11：创建 Pinia Store 配置

**文件：**
- 创建：`gym-manage-uniapp/src/store/index.ts`
- 创建：`gym-manage-uniapp/src/store/user.ts`

- [ ] **步骤 1：创建 store 入口文件**

创建 `gym-manage-uniapp/src/store/index.ts`：

```typescript
export * from './user'
```

- [ ] **步骤 2：创建用户状态管理文件**

创建 `gym-manage-uniapp/src/store/user.ts`：

```typescript
import { defineStore } from 'pinia'
import { ref } from 'vue'

export const useUserStore = defineStore('user', () => {
  const token = ref<string>('')
  const userInfo = ref<any>(null)
  const isLoggedIn = ref<boolean>(false)

  const setToken = (newToken: string) => {
    token.value = newToken
    isLoggedIn.value = !!newToken
    uni.setStorageSync('token', newToken)
  }

  const setUserInfo = (info: any) => {
    userInfo.value = info
    uni.setStorageSync('userInfo', info)
  }

  const logout = () => {
    token.value = ''
    userInfo.value = null
    isLoggedIn.value = false
    uni.removeStorageSync('token')
    uni.removeStorageSync('userInfo')
  }

  const init = () => {
    const savedToken = uni.getStorageSync('token')
    const savedUserInfo = uni.getStorageSync('userInfo')
    
    if (savedToken) {
      token.value = savedToken
      isLoggedIn.value = true
    }
    
    if (savedUserInfo) {
      userInfo.value = savedUserInfo
    }
  }

  return {
    token,
    userInfo,
    isLoggedIn,
    setToken,
    setUserInfo,
    logout,
    init
  }
})
```

---

### 任务 4.12：创建工具函数

**文件：**
- 创建：`gym-manage-uniapp/src/utils/storage.ts`

- [ ] **步骤 1：创建本地存储工具文件**

创建 `gym-manage-uniapp/src/utils/storage.ts`：

```typescript
export function setStorage(key: string, value: any): void {
  try {
    uni.setStorageSync(key, JSON.stringify(value))
  } catch (error) {
    console.error('存储数据失败:', error)
  }
}

export function getStorage<T = any>(key: string): T | null {
  try {
    const value = uni.getStorageSync(key)
    return value ? JSON.parse(value) : null
  } catch (error) {
    console.error('读取数据失败:', error)
    return null
  }
}

export function removeStorage(key: string): void {
  try {
    uni.removeStorageSync(key)
  } catch (error) {
    console.error('删除数据失败:', error)
  }
}

export function clearStorage(): void {
  try {
    uni.clearStorageSync()
  } catch (error) {
    console.error('清空存储失败:', error)
  }
}
```

---

### 任务 4.13：验证 UniApp 项目运行

**文件：**
- 无文件修改，仅验证

- [ ] **步骤 1：安装依赖**

```bash
cd gym-manage-uniapp
npm install
```

预期：依赖安装成功

- [ ] **步骤 2：运行 H5 开发服务器**

```bash
npm run dev:h5
```

预期：开发服务器启动成功，可在浏览器访问

---

### 任务 4.14：提交阶段 4 的变更

**文件：**
- 无文件修改，仅提交

- [ ] **步骤 1：查看变更状态**

```bash
git status
```

预期：显示所有新创建的文件

- [ ] **步骤 2：提交变更**

```bash
git add .
git commit -m "feat(mobile): 创建 gym-manage-uniapp 项目脚手架"
```

预期：提交成功

---

## 阶段 5：根目录整理与文档更新

### 任务 5.1：更新 docker-compose.yml

**文件：**
- 修改：`docker-compose.yml`

- [ ] **步骤 1：查看当前配置**

运行：`cat docker-compose.yml`
预期：查看当前 Docker Compose 配置

- [ ] **步骤 2：更新服务名称和路径**

根据实际配置，更新服务名称和卷挂载路径，确保引用新的项目目录名称。

---

### 任务 5.2：更新 Jenkinsfile

**文件：**
- 修改：`Jenkinsfile`

- [ ] **步骤 1：查看当前配置**

运行：`cat Jenkinsfile`
预期：查看当前 Jenkins 配置

- [ ] **步骤 2：更新项目路径**

根据实际配置，更新项目路径和构建命令，确保引用新的项目目录名称。

---

### 任务 5.3：更新 README.md

**文件：**
- 修改：`README.md`

- [ ] **步骤 1：更新项目名称和描述**

修改 `README.md` 开头部分：

```markdown
# 健身房管理系统

企业级健身房管理系统，包含会员管理、课程管理、教练管理、设备管理等核心功能。

## 项目结构

```
gym-manage/
├── gym-manage-api/          # 后端 API 项目
│   ├── manage-gateway/      # API 网关服务
│   ├── manage-app/          # 主应用服务
│   ├── manage-sys/          # 系统管理模块
│   ├── manage-db/           # 数据库模块
│   ├── manage-common/       # 公共模块
│   ├── manage-audit/        # 审计模块
│   ├── manage-notify/       # 通知模块
│   └── manage-file/         # 文件管理模块
├── gym-manage-web/          # 前端 Web 项目
├── gym-manage-uniapp/       # 移动端 UniApp 项目
└── e2e-tests/               # E2E 测试
```
```

- [ ] **步骤 2：更新技术栈描述**

更新技术栈部分，添加 UniApp 相关信息：

```markdown
### 移动端

- UniApp + Vue 3
- TypeScript
- Pinia (状态管理)
```

---

### 任务 5.4：最终验证

**文件：**
- 无文件修改，仅验证

- [ ] **步骤 1：验证根目录结构**

运行：`ls -la`
预期：只包含全局性文件和项目目录

- [ ] **步骤 2：验证后端服务**

```bash
cd gym-manage-api
mvn clean compile
```

预期：编译成功

- [ ] **步骤 3：验证前端构建**

```bash
cd gym-manage-web
npm run build
```

预期：构建成功

- [ ] **步骤 4：验证 UniApp 运行**

```bash
cd gym-manage-uniapp
npm run dev:h5
```

预期：开发服务器启动成功

---

### 任务 5.5：提交阶段 5 的变更

**文件：**
- 无文件修改，仅提交

- [ ] **步骤 1：查看变更状态**

```bash
git status
```

预期：显示所有修改的文件

- [ ] **步骤 2：提交变更**

```bash
git add .
git commit -m "docs: 更新项目文档和全局配置"
```

预期：提交成功

---

### 任务 5.6：推送到远程仓库

**文件：**
- 无文件修改，仅推送

- [ ] **步骤 1：查看提交历史**

```bash
git log --oneline -5
```

预期：显示最近 5 次提交

- [ ] **步骤 2：推送到远程仓库**

```bash
git push origin HEAD
```

预期：推送成功

---

## 计划自检

### 1. 规格覆盖度检查

✅ 所有规格中的需求都有对应的任务：
- 后端项目重构：任务 1.1 - 1.16
- 前端项目重构：任务 2.1 - 2.5
- 测试文件迁移：任务 3.1 - 3.10
- UniApp 项目创建：任务 4.1 - 4.14
- 根目录整理：任务 5.1 - 5.6

### 2. 占位符扫描

✅ 无占位符：
- 无"待定"、"TODO"、"后续实现"等词汇
- 所有步骤都有具体的代码或命令
- 所有文件路径都是精确的

### 3. 类型一致性

✅ 类型一致：
- 所有文件路径使用统一的命名规范
- 所有代码示例使用一致的语法
- 所有命令使用一致的格式

---

**计划已完成。**
