# 保护Mock版本的完整实施方案
## 方案目标
在对接后端API的同时,**永久保护当前的Mock版本UI代码**,确保:
1. ✅ Mock版本UI代码不被修改
2. ✅ 可随时切换Mock模式和API模式
3. ✅ 支持独立演示Mock版本
4. ✅ 便于团队协作开发
---
## 一、保护策略总览
### 1.1 多层保护机制
```
┌─────────────────────────────────────────┐
│ 第一层:Git分支隔离 │
│ - main分支:永久保存Mock版本 │
│ - feature/api分支:API对接开发 │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ 第二层:配置开关控制 │
│ - dataMode: 'mock' | 'api' │
│ - 运行时动态切换数据源 │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ 第三层:代码架构分离 │
│ - Mock数据独立目录 │
│ - API调用独立目录 │
│ - 业务逻辑层统一适配 │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ 第四层:文档备份 │
│ - 完整的Mock版本文档存档 │
│ - 代码快照保存 │
└─────────────────────────────────────────┘
```
---
## 二、Git分支管理方案(第一层保护)
### 2.1 分支结构设计
```
main (Mock版本,永久保护)
│
├─ feature/api-integration (API对接开发)
│ │
│ ├─ feature/api-login (登录接口)
│ ├─ feature/api-score (评分接口)
│ └─ feature/api-admin (裁判长功能)
│
├─ release/v1.0-mock (Mock版本发布)
└─ release/v2.0-api (API版本发布)
```
### 2.2 实施步骤
#### 步骤1:保存当前Mock版本
```bash
# 1. 确保所有更改已提交
git add .
git commit -m "✅ Mock版本完成 - UI冻结版本"
# 2. 打标签标记Mock版本
git tag -a v1.0-mock -m "Mock原型版本 - 完整UI展示"
# 3. 推送到远程
git push origin main
git push origin v1.0-mock
```
#### 步骤2:创建API对接分支
```bash
# 1. 基于main创建API分支
git checkout -b feature/api-integration
# 2. 推送到远程
git push -u origin feature/api-integration
```
#### 步骤3:开发过程中的保护
```bash
# ❌ 禁止:直接在main分支修改
git checkout main
# ... 修改代码 (错误操作!)
# ✅ 正确:始终在feature分支工作
git checkout feature/api-integration
# ... 修改代码
git add .
git commit -m "feat: 添加登录API对接"
git push
```
#### 步骤4:快速切换版本
```bash
# 切换到Mock版本(演示UI)
git checkout main
# 切换到API版本(开发/测试)
git checkout feature/api-integration
# 切换到特定标签
git checkout v1.0-mock
```
### 2.3 .gitignore 配置
```bash
# .gitignore
node_modules/
dist/
unpackage/
.DS_Store
*.log
# 开发环境配置(不提交)
.env.development.local
# 构建产物
*.zip
```
---
## 三、配置开关控制方案(第二层保护)
### 3.1 环境配置文件
#### 创建 `config/env.config.js`
```javascript
/**
* 环境配置
* 控制应用的数据源模式
*/
const ENV_CONFIG = {
// 开发环境
development: {
// 数据模式: 'mock' | 'api'
dataMode: 'mock',
// API基础路径
apiBaseURL: 'http://localhost:8080',
// 是否开启调试
debug: true,
// 请求超时时间(毫秒)
timeout: 30000
},
// 测试环境
test: {
dataMode: 'api',
apiBaseURL: 'http://test-api.yourdomain.com',
debug: true,
timeout: 30000
},
// 生产环境
production: {
dataMode: 'api',
apiBaseURL: 'https://api.yourdomain.com',
debug: false,
timeout: 30000
}
}
// 获取当前环境
const env = process.env.NODE_ENV || 'development'
// 导出配置
export default {
...ENV_CONFIG[env],
env
}
/**
* 使用说明:
*
* 1. Mock模式(UI演示):
* 设置 dataMode: 'mock'
*
* 2. API模式(真实对接):
* 设置 dataMode: 'api'
*
* 3. 动态切换:
* import config from '@/config/env.config.js'
* if (config.dataMode === 'mock') { ... }
*/
```
### 3.2 数据源适配器
#### 创建 `utils/dataAdapter.js`
```javascript
/**
* 数据源适配器
* 根据配置动态选择Mock数据或API数据
*/
import config from '@/config/env.config.js'
import mockData from '@/mock/index.js'
import apiService from '@/api/index.js'
class DataAdapter {
constructor() {
this.mode = config.dataMode
this.debug = config.debug
}
/**
* 统一数据获取接口
* @param {String} resource - 资源名称
* @param {Object} params - 请求参数
* @returns {Promise}
*/
async getData(resource, params = {}) {
if (this.mode === 'mock') {
return this._getMockData(resource, params)
} else {
return this._getApiData(resource, params)
}
}
/**
* 获取Mock数据
*/
async _getMockData(resource, params) {
if (this.debug) {
console.log(`[Mock数据] 请求: ${resource}`, params)
}
// 模拟网络延迟
await this._delay(300)
const data = mockData[resource](params)
if (this.debug) {
console.log(`[Mock数据] 响应: ${resource}`, data)
}
return {
code: 200,
message: '成功',
data
}
}
/**
* 获取API数据
*/
async _getApiData(resource, params) {
if (this.debug) {
console.log(`[API请求] 请求: ${resource}`, params)
}
const response = await apiService[resource](params)
if (this.debug) {
console.log(`[API请求] 响应: ${resource}`, response)
}
return response
}
/**
* 延迟函数(模拟网络请求)
*/
_delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
/**
* 切换数据模式
*/
switchMode(mode) {
if (mode === 'mock' || mode === 'api') {
this.mode = mode
console.log(`数据模式已切换为: ${mode}`)
} else {
console.error('无效的数据模式,只能是 "mock" 或 "api"')
}
}
/**
* 获取当前模式
*/
getMode() {
return this.mode
}
}
// 导出单例
export default new DataAdapter()
```
### 3.3 页面使用示例
#### 修改 `pages/login/login.vue`
```vue
```
---
## 四、代码架构分离(第三层保护)
### 4.1 目录结构设计
```
martial-admin-mini/
├── config/
│ ├── env.config.js # 环境配置
│ └── api.config.js # API配置
│
├── mock/ # 🔥 Mock数据目录(独立)
│ ├── index.js # Mock数据入口
│ ├── login.js # 登录Mock数据
│ ├── athlete.js # 选手Mock数据
│ ├── score.js # 评分Mock数据
│ └── README.md # Mock数据说明
│
├── api/ # 🔥 API调用目录(独立)
│ ├── index.js # API入口
│ ├── auth.js # 认证API
│ ├── athlete.js # 选手API
│ ├── score.js # 评分API
│ └── README.md # API说明
│
├── utils/
│ ├── request.js # 网络请求封装
│ ├── dataAdapter.js # 🔥 数据适配器(核心)
│ └── storage.js # 本地存储工具
│
├── pages/
│ ├── login/
│ │ └── login.vue # ✅ UI代码不变
│ ├── score-list/
│ │ └── score-list.vue # ✅ UI代码不变
│ └── ...
│
└── doc/
├── Mock版本快照.md # Mock版本文档备份
└── 数据可行性分析报告.md
```
### 4.2 Mock数据模块
#### 创建 `mock/index.js`
```javascript
/**
* Mock数据中心
* 所有Mock数据的统一入口
*/
import loginMock from './login.js'
import athleteMock from './athlete.js'
import scoreMock from './score.js'
export default {
// 登录
login: loginMock.login,
// 选手列表
getMyAthletes: athleteMock.getMyAthletes,
getAthletesForAdmin: athleteMock.getAthletesForAdmin,
// 评分
submitScore: scoreMock.submitScore,
getScoreDetail: scoreMock.getScoreDetail,
modifyScore: scoreMock.modifyScore,
// 扣分项
getDeductions: scoreMock.getDeductions
}
```
#### 创建 `mock/login.js`
```javascript
/**
* 登录相关Mock数据
*/
export default {
/**
* 登录
*/
login(params) {
const { matchCode, inviteCode } = params
const role = inviteCode.toLowerCase()
// 模拟验证
if (role !== 'pub' && role !== 'admin') {
throw new Error('邀请码错误')
}
// 返回Mock数据
return {
token: 'mock_token_' + Date.now(),
userRole: role,
matchId: '123',
matchName: '2025年全国武术散打锦标赛暨第十七届世界武术锦标赛选拔赛',
matchTime: '2025年6月25日 9:00',
judgeId: '456',
judgeName: '欧阳丽娜',
venueId: role === 'pub' ? '1' : null,
venueName: role === 'pub' ? '第一场地' : null,
projects: ['女子组长拳', '男子组陈氏太极拳']
}
}
}
```
#### 创建 `mock/athlete.js`
```javascript
/**
* 选手相关Mock数据
*/
export default {
/**
* 获取我的选手列表(普通评委)
*/
getMyAthletes(params) {
return [
{
athleteId: '1',
name: '张三',
idCard: '123456789000000000',
team: '少林寺武术大学院',
number: '123-4567898275',
myScore: 8.906,
totalScore: 8.907,
scored: true,
scoreTime: '2025-06-25 09:15:00'
},
{
athleteId: '2',
name: '李四',
idCard: '123456789000000001',
team: '武当山武术学院',
number: '123-4567898276',
myScore: null,
totalScore: null,
scored: false,
scoreTime: null
},
// ... 更多Mock数据
]
},
/**
* 获取选手列表(裁判长)
*/
getAthletesForAdmin(params) {
return [
{
athleteId: '1',
name: '张三',
idCard: '123456789000000000',
team: '少林寺武术大学院',
number: '123-4567898275',
totalScore: 8.907,
judgeCount: 6,
totalJudges: 6,
canModify: true
},
// ... 更多Mock数据
]
}
}
```
### 4.3 API调用模块
#### 创建 `api/index.js`
```javascript
/**
* API调用中心
* 所有API调用的统一入口
*/
import authApi from './auth.js'
import athleteApi from './athlete.js'
import scoreApi from './score.js'
export default {
// 登录
login: authApi.login,
// 选手列表
getMyAthletes: athleteApi.getMyAthletes,
getAthletesForAdmin: athleteApi.getAthletesForAdmin,
// 评分
submitScore: scoreApi.submitScore,
getScoreDetail: scoreApi.getScoreDetail,
modifyScore: scoreApi.modifyScore,
// 扣分项
getDeductions: scoreApi.getDeductions
}
```
#### 创建 `api/auth.js`
```javascript
/**
* 认证相关API
*/
import request from '@/utils/request.js'
export default {
/**
* 登录
*/
login(data) {
return request({
url: '/mini/login',
method: 'POST',
data
})
},
/**
* 退出登录
*/
logout() {
return request({
url: '/mini/logout',
method: 'POST'
})
},
/**
* Token验证
*/
verifyToken() {
return request({
url: '/mini/verify',
method: 'GET'
})
}
}
```
---
## 五、文档备份(第四层保护)
### 5.1 Mock版本快照文档
#### 创建 `doc/Mock版本快照.md`
```markdown
# Mock版本快照文档
## 版本信息
- **版本号**: v1.0-mock
- **创建时间**: 2025-12-11
- **Git标签**: v1.0-mock
- **Git提交**: c2f3313
- **分支**: main
## 页面列表
### 1. 登录页 (`pages/login/login.vue`)
- **功能**: 比赛编码 + 邀请码登录
- **角色**: pub(普通评委), admin(裁判长)
- **数据**: 完全Mock,无API依赖
### 2. 评分列表页 (`pages/score-list/score-list.vue`)
- **功能**: 选手列表展示,评分状态显示
- **数据**: 3个Mock选手数据
### 3. 评分详情页 (`pages/score-detail/score-detail.vue`)
- **功能**: 评分操作(0.001精度),扣分项选择
- **数据**: 8个扣分项Mock数据
### 4. 多场地列表页 (`pages/score-list-multi/score-list-multi.vue`)
- **功能**: 5个场地 + 8个项目切换
- **数据**: 场地和项目Mock数据
### 5. 修改评分页 (`pages/modify-score/modify-score.vue`)
- **功能**: 查看评委评分,修改总分
- **数据**: 6位评委评分Mock数据
## Mock数据说明
所有Mock数据硬编码在组件的 `data()` 中,无外部依赖。
## 恢复Mock版本
```bash
git checkout v1.0-mock
```
或
```bash
git checkout main
```
## 运行Mock版本
```bash
# 确保在main分支
git checkout main
# 运行
npm run dev:mp-weixin
# 或
npm run dev:h5
```
```
### 5.2 代码备份策略
```bash
# 1. 创建压缩包备份
cd D:\workspace\31.比赛项目\project\
tar -czf martial-admin-mini-mock-v1.0-$(date +%Y%m%d).tar.gz martial-admin-mini/
# 2. 创建Git存档
cd martial-admin-mini
git archive --format=zip --output=../martial-admin-mini-mock-v1.0.zip v1.0-mock
# 3. 导出完整提交历史
git log --pretty=format:"%h - %an, %ar : %s" > ../git-history.txt
```
---
## 六、实施操作指南
### 6.1 初始化保护(首次执行)
```bash
# ========== 步骤1:提交当前代码 ==========
cd D:\workspace\31.比赛项目\project\martial-admin-mini
git add .
git commit -m "✅ Mock版本完成 - 冻结UI代码"
# ========== 步骤2:打标签 ==========
git tag -a v1.0-mock -m "Mock原型版本 - 完整UI展示"
# ========== 步骤3:创建API分支 ==========
git checkout -b feature/api-integration
git push -u origin feature/api-integration
# ========== 步骤4:创建目录结构 ==========
mkdir -p config mock api
# ========== 步骤5:创建配置文件 ==========
# 创建 config/env.config.js
# 创建 utils/dataAdapter.js
# 创建 mock/index.js
# ... (根据上面的代码创建)
# ========== 步骤6:测试Mock模式 ==========
# 设置 config/env.config.js 中 dataMode: 'mock'
npm run dev:mp-weixin
# ========== 步骤7:提交保护机制 ==========
git add .
git commit -m "feat: 添加Mock版本保护机制"
git push
```
### 6.2 日常开发流程
```bash
# ========== API开发时 ==========
git checkout feature/api-integration
# 修改代码...
git add .
git commit -m "feat: 添加登录API对接"
git push
# ========== 演示Mock版本时 ==========
git checkout main
npm run dev:mp-weixin
# ========== 测试API版本时 ==========
git checkout feature/api-integration
# 修改 config/env.config.js: dataMode: 'api'
npm run dev:mp-weixin
```
### 6.3 紧急恢复流程
```bash
# ========== 如果API分支出错,立即恢复Mock版本 ==========
git checkout main
# ========== 如果main分支被误修改 ==========
git reset --hard v1.0-mock
# ========== 如果本地代码全部丢失 ==========
git clone
git checkout v1.0-mock
```
---
## 七、团队协作规范
### 7.1 分支保护规则
**main分支保护**:
- ❌ 禁止直接push
- ❌ 禁止force push
- ✅ 只允许通过PR合并
- ✅ 需要代码审查
**feature分支规范**:
- ✅ 可以自由提交
- ✅ 定期合并main分支
- ✅ 完成后提PR到main
### 7.2 提交信息规范
```bash
# Mock版本相关
git commit -m "✅ Mock版本: 修复样式问题"
git commit -m "✅ Mock版本: 更新文档"
# API对接相关
git commit -m "feat: 添加登录API对接"
git commit -m "feat: 实现评分提交接口"
git commit -m "fix: 修复Token过期问题"
# 配置相关
git commit -m "config: 切换到Mock模式"
git commit -m "config: 更新API地址"
```
### 7.3 代码审查清单
**合并到main分支前检查**:
- [ ] UI代码是否被修改?(应该没有)
- [ ] Mock数据是否完整?
- [ ] 配置文件是否正确?
- [ ] 文档是否更新?
- [ ] 版本号是否更新?
---
## 八、配置开关使用指南
### 8.1 切换到Mock模式
```javascript
// config/env.config.js
const ENV_CONFIG = {
development: {
dataMode: 'mock', // ✅ 修改这里
apiBaseURL: 'http://localhost:8080',
debug: true,
timeout: 30000
}
}
```
**场景**:
- UI演示
- 前端独立开发
- 离线开发
- 快速原型展示
### 8.2 切换到API模式
```javascript
// config/env.config.js
const ENV_CONFIG = {
development: {
dataMode: 'api', // ✅ 修改这里
apiBaseURL: 'http://localhost:8080',
debug: true,
timeout: 30000
}
}
```
**场景**:
- 后端联调
- 真实数据测试
- 生产环境
- 集成测试
### 8.3 动态切换(高级)
```javascript
// 在代码中动态切换
import dataAdapter from '@/utils/dataAdapter.js'
// 切换到Mock模式
dataAdapter.switchMode('mock')
// 切换到API模式
dataAdapter.switchMode('api')
// 查看当前模式
console.log(dataAdapter.getMode())
```
---
## 九、验证清单
### 9.1 Mock版本验证
- [ ] 切换到main分支
- [ ] 设置 `dataMode: 'mock'`
- [ ] 运行项目
- [ ] 登录功能正常
- [ ] 所有页面正常显示
- [ ] Mock数据正常加载
- [ ] UI样式无变化
### 9.2 API版本验证
- [ ] 切换到feature分支
- [ ] 设置 `dataMode: 'api'`
- [ ] 确认后端服务已启动
- [ ] 运行项目
- [ ] API登录成功
- [ ] 数据正常加载
- [ ] Token正常传递
### 9.3 切换验证
- [ ] Mock → API 切换成功
- [ ] API → Mock 切换成功
- [ ] 配置文件生效
- [ ] 数据适配器正常工作
- [ ] 无报错
---
## 十、常见问题
### Q1: 如果不小心在main分支修改了代码怎么办?
```bash
# 方案1:撤销未提交的修改
git checkout -- .
# 方案2:回退到上一次提交
git reset --hard HEAD
# 方案3:回退到Mock版本标签
git reset --hard v1.0-mock
```
### Q2: 如何查看当前使用的数据模式?
```javascript
// 方法1:查看配置文件
import config from '@/config/env.config.js'
console.log(config.dataMode)
# 方法2:查看数据适配器
import dataAdapter from '@/utils/dataAdapter.js'
console.log(dataAdapter.getMode())
```
### Q3: Mock数据和API数据格式不一致怎么办?
**方案**: 在数据适配器中统一格式
```javascript
// utils/dataAdapter.js
async _getApiData(resource, params) {
const response = await apiService[resource](params)
// 🔥 统一数据格式
return {
code: response.code,
message: response.msg || response.message,
data: this._transformData(response.data)
}
}
_transformData(data) {
// 根据需要转换数据格式
// 例如: Long → String, BigDecimal → Number
return data
}
```
### Q4: 如何给其他人演示Mock版本?
```bash
# 方案1:发送压缩包
git archive --format=zip --output=martial-admin-mini-mock.zip main
# 方案2:提供Git地址和分支
git clone
git checkout main
# 确保 config/env.config.js 中 dataMode: 'mock'
npm install
npm run dev:mp-weixin
```
---
## 十一、总结
### ✅ 保护机制优势
1. **安全性**: 4层保护机制,Mock版本不会被破坏
2. **灵活性**: 随时切换Mock/API模式
3. **可维护性**: 代码结构清晰,易于维护
4. **可扩展性**: 便于添加新的数据源
5. **团队协作**: 分支隔离,互不干扰
### 📊 实施成本
| 项目 | 预计时间 | 难度 |
|------|---------|------|
| Git分支设置 | 10分钟 | 简单 |
| 创建配置文件 | 30分钟 | 简单 |
| 创建数据适配器 | 1小时 | 中等 |
| Mock数据整理 | 2小时 | 简单 |
| 文档编写 | 1小时 | 简单 |
| **总计** | **约5小时** | **中等** |
### 🎯 最终效果
```
✅ Mock版本:永久保护,随时演示
✅ API版本:独立开发,不影响Mock
✅ 一键切换:配置文件控制
✅ 零UI改动:完全兼容现有代码
```
---
**文档版本**: v1.0
**创建时间**: 2025-12-11
**适用项目**: martial-admin-mini
**维护人员**: 开发团队