# 保护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 **维护人员**: 开发团队