## 主要改动
### 1. 修复Mock数据格式问题
- 修复 mock/athlete.js 中 getProjects 函数
- 从字符串数组改为对象数组 { id, name }
- 确保Mock模式和API模式数据格式一致
### 2. 优化网络请求处理
- 优化 utils/request.js 的GET请求参数处理
- 参数自动URL编码
- 支持URL中已有查询参数的情况
- 代码逻辑更清晰
### 3. 新增完整的文档体系
- API对接说明.md - 项目根目录快速说明
- doc/API对接快速启动指南.md - 5分钟快速上手
- doc/后端接口开发清单.md - 后端开发规范(5个接口,6人天)
- doc/前端API对接指南.md - 前端联调指南
- doc/API对接准备完成报告.md - 项目状态总结
## 项目状态
✅ 前端准备完成度: 100%
- 架构设计优秀(dataAdapter适配器模式)
- 代码质量高(注释详细,结构清晰)
- Mock数据完整(可独立演示)
- API接口定义完整(9个接口)
- 页面全部接入(5个页面)
- 文档体系完善(20个文档)
⚠️ 后端待开发: 5个接口
- POST /api/mini/login
- GET /api/mini/athletes
- GET /api/mini/athletes/admin
- GET /api/mini/score/detail/{id}
- PUT /api/mini/score/modify
## 下一步
后端开发者可以参考 doc/后端接口开发清单.md 开始开发
预计工作量: 6人天(约1周)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
797 lines
16 KiB
Markdown
797 lines
16 KiB
Markdown
# 前端API对接指南
|
||
|
||
> **项目**: 武术评分系统小程序
|
||
> **前端项目**: martial-admin-mini
|
||
> **创建时间**: 2025-12-12
|
||
> **状态**: 准备就绪,等待后端接口
|
||
|
||
---
|
||
|
||
## 📊 当前状态
|
||
|
||
### ✅ 已完成的工作
|
||
|
||
1. **dataAdapter 架构** - 完成
|
||
- 支持 Mock/API 双模式无缝切换
|
||
- 页面代码零修改
|
||
|
||
2. **API接口定义** - 完成
|
||
- 9个接口函数已定义
|
||
- 路径规范统一
|
||
|
||
3. **网络请求封装** - 完成并优化
|
||
- Token自动添加(Blade-Auth格式)
|
||
- GET请求参数处理优化
|
||
- 统一错误处理
|
||
|
||
4. **页面接入** - 完成
|
||
- 5个页面全部接入 dataAdapter
|
||
- 支持一键切换数据源
|
||
|
||
5. **Mock数据** - 完成并修复
|
||
- 项目列表格式已修复为对象数组
|
||
- 与API格式保持一致
|
||
|
||
### ⚠️ 待完成的工作
|
||
|
||
1. **后端接口开发** - 5个接口待实现
|
||
2. **前后端联调** - 等待后端完成
|
||
3. **数据格式适配** - 可能需要微调
|
||
|
||
---
|
||
|
||
## 🚀 快速开始
|
||
|
||
### 1. 环境配置
|
||
|
||
当前配置文件:[config/env.config.js](../config/env.config.js)
|
||
|
||
```javascript
|
||
// 当前配置
|
||
dataMode: 'api' // 已设置为API模式
|
||
apiBaseURL: 'http://localhost:8080' // 后端地址
|
||
```
|
||
|
||
**切换到Mock模式测试**(如果后端未就绪):
|
||
```javascript
|
||
dataMode: 'mock' // 切换为Mock模式
|
||
```
|
||
|
||
### 2. 后端服务地址配置
|
||
|
||
根据不同环境修改 `apiBaseURL`:
|
||
|
||
```javascript
|
||
// 开发环境
|
||
development: {
|
||
apiBaseURL: 'http://localhost:8080'
|
||
}
|
||
|
||
// 测试环境
|
||
test: {
|
||
apiBaseURL: 'http://test-api.yourdomain.com'
|
||
}
|
||
|
||
// 生产环境
|
||
production: {
|
||
apiBaseURL: 'https://api.yourdomain.com'
|
||
}
|
||
```
|
||
|
||
### 3. 测试数据准备
|
||
|
||
联调前需要准备以下测试数据:
|
||
|
||
| 数据类型 | 说明 | 示例 |
|
||
|---------|------|------|
|
||
| **比赛编码** | 用于登录 | `123` |
|
||
| **普通评委邀请码** | pub角色 | `pub` |
|
||
| **裁判长邀请码** | admin角色 | `admin` |
|
||
| **评委ID** | 登录后获取 | `456` |
|
||
| **场地ID** | 登录后获取 | `1` |
|
||
| **项目ID** | 登录后获取 | `5` |
|
||
|
||
---
|
||
|
||
## 📋 API接口清单
|
||
|
||
### 接口映射表
|
||
|
||
| 资源名称 | 前端调用 | 后端接口 | 状态 |
|
||
|---------|---------|---------|------|
|
||
| `login` | `dataAdapter.getData('login', params)` | `POST /api/mini/login` | ⚠️ 待开发 |
|
||
| `getMyAthletes` | `dataAdapter.getData('getMyAthletes', params)` | `GET /api/mini/athletes` | ⚠️ 待开发 |
|
||
| `getAthletesForAdmin` | `dataAdapter.getData('getAthletesForAdmin', params)` | `GET /api/mini/athletes/admin` | ⚠️ 待开发 |
|
||
| `getScoreDetail` | `dataAdapter.getData('getScoreDetail', params)` | `GET /api/mini/score/detail/{id}` | ⚠️ 待开发 |
|
||
| `modifyScore` | `dataAdapter.getData('modifyScore', data)` | `PUT /api/mini/score/modify` | ⚠️ 待开发 |
|
||
| `getVenues` | `dataAdapter.getData('getVenues', params)` | `GET /martial/venue/list` | ✅ 已有 |
|
||
| `getProjects` | `dataAdapter.getData('getProjects', params)` | `GET /martial/project/list` | ✅ 已有 |
|
||
| `getDeductions` | `dataAdapter.getData('getDeductions', params)` | `GET /martial/deductionItem/list` | ✅ 已有 |
|
||
| `submitScore` | `dataAdapter.getData('submitScore', data)` | `POST /martial/score/submit` | ✅ 已有 |
|
||
|
||
---
|
||
|
||
## 🔍 接口详细说明
|
||
|
||
### 1. 登录接口
|
||
|
||
**前端调用**:
|
||
```javascript
|
||
// pages/login/login.vue:96
|
||
const response = await dataAdapter.getData('login', {
|
||
matchCode: this.matchCode,
|
||
inviteCode: this.inviteCode
|
||
})
|
||
```
|
||
|
||
**后端接口**: `POST /api/mini/login`
|
||
|
||
**请求参数**:
|
||
```json
|
||
{
|
||
"matchCode": "123",
|
||
"inviteCode": "pub"
|
||
}
|
||
```
|
||
|
||
**响应数据**:
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"success": true,
|
||
"msg": "登录成功",
|
||
"data": {
|
||
"token": "xxx",
|
||
"userRole": "pub",
|
||
"matchId": "123",
|
||
"matchName": "2025年全国武术散打锦标赛...",
|
||
"matchTime": "2025年6月25日 9:00",
|
||
"judgeId": "456",
|
||
"judgeName": "欧阳丽娜",
|
||
"venueId": "1",
|
||
"venueName": "第一场地",
|
||
"projects": ["女子组长拳", "男子组陈氏太极拳"]
|
||
}
|
||
}
|
||
```
|
||
|
||
**前端处理**:
|
||
```javascript
|
||
// 保存Token
|
||
uni.setStorageSync('token', response.data.token)
|
||
|
||
// 保存用户信息到全局
|
||
getApp().globalData = {
|
||
userRole: response.data.userRole,
|
||
matchCode: this.matchCode,
|
||
token: response.data.token,
|
||
// ... 其他信息
|
||
}
|
||
|
||
// 根据角色跳转
|
||
if (response.data.userRole === 'pub') {
|
||
uni.redirectTo({ url: '/pages/score-list/score-list' })
|
||
} else {
|
||
uni.redirectTo({ url: '/pages/score-list-multi/score-list-multi' })
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 2. 获取选手列表(普通评委)
|
||
|
||
**前端调用**:
|
||
```javascript
|
||
// pages/score-list/score-list.vue:150
|
||
const response = await dataAdapter.getData('getMyAthletes', {
|
||
judgeId: this.judgeId,
|
||
venueId: this.venueInfo.id,
|
||
projectId: this.projectInfo.id
|
||
})
|
||
```
|
||
|
||
**后端接口**: `GET /api/mini/athletes`
|
||
|
||
**请求参数**:
|
||
```
|
||
judgeId=456&venueId=1&projectId=5
|
||
```
|
||
|
||
**响应数据**:
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"success": true,
|
||
"msg": "操作成功",
|
||
"data": [
|
||
{
|
||
"athleteId": "1",
|
||
"name": "张三",
|
||
"idCard": "123456789000000000",
|
||
"team": "少林寺武术大学院",
|
||
"number": "123-4567898275",
|
||
"myScore": 8.906,
|
||
"totalScore": 8.907,
|
||
"scored": true,
|
||
"scoreTime": "2025-06-25 09:15:00"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
**前端处理**:
|
||
```javascript
|
||
this.players = response.data
|
||
this.totalCount = response.data.length
|
||
this.scoredCount = response.data.filter(p => p.scored).length
|
||
```
|
||
|
||
---
|
||
|
||
### 3. 获取选手列表(裁判长)
|
||
|
||
**前端调用**:
|
||
```javascript
|
||
// pages/score-list-multi/score-list-multi.vue:211
|
||
const response = await dataAdapter.getData('getAthletesForAdmin', {
|
||
competitionId: this.matchInfo.id,
|
||
venueId: this.selectedVenue,
|
||
projectId: this.selectedProject
|
||
})
|
||
```
|
||
|
||
**后端接口**: `GET /api/mini/athletes/admin`
|
||
|
||
**请求参数**:
|
||
```
|
||
competitionId=123&venueId=1&projectId=5
|
||
```
|
||
|
||
**响应数据**:
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"success": true,
|
||
"msg": "操作成功",
|
||
"data": [
|
||
{
|
||
"athleteId": "1",
|
||
"name": "张三",
|
||
"idCard": "123456789000000000",
|
||
"team": "少林寺武术大学院",
|
||
"number": "123-4567898275",
|
||
"totalScore": 8.907,
|
||
"judgeCount": 6,
|
||
"totalJudges": 6,
|
||
"canModify": true
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
**前端处理**:
|
||
```javascript
|
||
this.players = response.data
|
||
```
|
||
|
||
---
|
||
|
||
### 4. 获取场地列表
|
||
|
||
**前端调用**:
|
||
```javascript
|
||
// pages/score-list-multi/score-list-multi.vue:152
|
||
const venuesRes = await dataAdapter.getData('getVenues', {
|
||
competitionId: this.matchInfo.id
|
||
})
|
||
```
|
||
|
||
**后端接口**: `GET /martial/venue/list` ✅ 已有
|
||
|
||
**请求参数**:
|
||
```
|
||
competitionId=123¤t=1&size=100
|
||
```
|
||
|
||
**响应数据**:
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"success": true,
|
||
"msg": "操作成功",
|
||
"data": {
|
||
"records": [
|
||
{ "id": "1", "venueName": "第一场地" }
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
**⚠️ 注意**: 后端返回的是分页格式,需要从 `data.records` 中提取数据。
|
||
|
||
**前端适配建议**:
|
||
|
||
**方案1**: 在 `api/athlete.js` 中处理
|
||
```javascript
|
||
export function getVenues(params) {
|
||
return request({
|
||
url: '/martial/venue/list',
|
||
method: 'GET',
|
||
params: {
|
||
...params,
|
||
current: 1,
|
||
size: 100
|
||
}
|
||
}).then(res => {
|
||
// 提取 records 数据
|
||
return {
|
||
...res,
|
||
data: res.data.records.map(item => ({
|
||
id: item.id,
|
||
name: item.venueName
|
||
}))
|
||
}
|
||
})
|
||
}
|
||
```
|
||
|
||
**方案2**: 在页面中处理
|
||
```javascript
|
||
const venuesRes = await dataAdapter.getData('getVenues', {
|
||
competitionId: this.matchInfo.id
|
||
})
|
||
this.venues = venuesRes.data.records.map(item => ({
|
||
id: item.id,
|
||
name: item.venueName
|
||
}))
|
||
```
|
||
|
||
**推荐使用方案1**,保持页面代码简洁。
|
||
|
||
---
|
||
|
||
### 5. 获取项目列表
|
||
|
||
**前端调用**:
|
||
```javascript
|
||
// pages/score-list-multi/score-list-multi.vue:159
|
||
const projectsRes = await dataAdapter.getData('getProjects', {
|
||
competitionId: this.matchInfo.id
|
||
})
|
||
```
|
||
|
||
**后端接口**: `GET /martial/project/list` ✅ 已有
|
||
|
||
**响应数据**:
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"success": true,
|
||
"msg": "操作成功",
|
||
"data": {
|
||
"records": [
|
||
{ "id": "5", "projectName": "女子组长拳" }
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
**前端适配**: 同场地列表,需要从 `data.records` 中提取并映射字段。
|
||
|
||
---
|
||
|
||
### 6. 获取扣分项列表
|
||
|
||
**前端调用**:
|
||
```javascript
|
||
// pages/score-detail/score-detail.vue:165
|
||
const response = await dataAdapter.getData('getDeductions', {
|
||
projectId: this.projectInfo.id
|
||
})
|
||
```
|
||
|
||
**后端接口**: `GET /martial/deductionItem/list` ✅ 已有
|
||
|
||
**响应数据**:
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"success": true,
|
||
"msg": "操作成功",
|
||
"data": {
|
||
"records": [
|
||
{
|
||
"id": "1",
|
||
"itemName": "动作不到位",
|
||
"deductionPoint": -0.1,
|
||
"category": "动作质量"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
**前端适配**: 需要映射字段名。
|
||
|
||
---
|
||
|
||
### 7. 提交评分
|
||
|
||
**前端调用**:
|
||
```javascript
|
||
// pages/score-detail/score-detail.vue:237
|
||
const response = await dataAdapter.getData('submitScore', {
|
||
athleteId: this.athleteId,
|
||
judgeId: this.judgeId,
|
||
score: this.finalScore,
|
||
deductions: this.selectedDeductions,
|
||
note: this.note
|
||
})
|
||
```
|
||
|
||
**后端接口**: `POST /martial/score/submit` ✅ 已有
|
||
|
||
**请求参数**:
|
||
```json
|
||
{
|
||
"athleteId": "1",
|
||
"judgeId": "456",
|
||
"score": 8.907,
|
||
"deductions": [
|
||
{
|
||
"id": "1",
|
||
"text": "动作不到位",
|
||
"score": -0.1
|
||
}
|
||
],
|
||
"note": "表现优秀"
|
||
}
|
||
```
|
||
|
||
**⚠️ 注意**: 后端可能需要 `deductions` 为JSON字符串格式。
|
||
|
||
**前端适配**:
|
||
```javascript
|
||
export function submitScore(data) {
|
||
return request({
|
||
url: '/martial/score/submit',
|
||
method: 'POST',
|
||
data: {
|
||
...data,
|
||
deductionItems: JSON.stringify(data.deductions) // 转为JSON字符串
|
||
},
|
||
showLoading: true,
|
||
loadingText: '提交中...'
|
||
})
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 8. 获取评分详情(裁判长)
|
||
|
||
**前端调用**:
|
||
```javascript
|
||
// pages/modify-score/modify-score.vue:157
|
||
const response = await dataAdapter.getData('getScoreDetail', {
|
||
athleteId: this.athleteId
|
||
})
|
||
```
|
||
|
||
**后端接口**: `GET /api/mini/score/detail/{athleteId}` ⚠️ 待开发
|
||
|
||
**响应数据**:
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"success": true,
|
||
"msg": "操作成功",
|
||
"data": {
|
||
"athleteInfo": {
|
||
"athleteId": "1",
|
||
"name": "张三",
|
||
"idCard": "123456789000000000",
|
||
"team": "少林寺武术大学院",
|
||
"number": "123-4567898275",
|
||
"totalScore": 8.907
|
||
},
|
||
"judgeScores": [
|
||
{
|
||
"judgeId": "1",
|
||
"judgeName": "欧阳丽娜",
|
||
"score": 8.907,
|
||
"scoreTime": "2025-06-25 09:15:00",
|
||
"note": ""
|
||
}
|
||
],
|
||
"modification": null
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 9. 修改评分(裁判长)
|
||
|
||
**前端调用**:
|
||
```javascript
|
||
// pages/modify-score/modify-score.vue:242
|
||
const response = await dataAdapter.getData('modifyScore', {
|
||
athleteId: this.athleteId,
|
||
modifierId: this.modifierId,
|
||
modifiedScore: this.modifiedScore,
|
||
note: this.modifyReason
|
||
})
|
||
```
|
||
|
||
**后端接口**: `PUT /api/mini/score/modify` ⚠️ 待开发
|
||
|
||
**请求参数**:
|
||
```json
|
||
{
|
||
"athleteId": "1",
|
||
"modifierId": "789",
|
||
"modifiedScore": 8.910,
|
||
"note": "修改原因"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 🔧 需要适配的地方
|
||
|
||
### 1. 分页数据提取
|
||
|
||
后端返回的场地、项目、扣分项都是分页格式,需要提取 `data.records`。
|
||
|
||
**建议修改 api/athlete.js 和 api/score.js**:
|
||
|
||
```javascript
|
||
// api/athlete.js
|
||
export function getVenues(params) {
|
||
return request({
|
||
url: '/martial/venue/list',
|
||
method: 'GET',
|
||
params: {
|
||
...params,
|
||
current: 1,
|
||
size: 100
|
||
}
|
||
}).then(res => {
|
||
return {
|
||
...res,
|
||
data: res.data.records.map(item => ({
|
||
id: item.id,
|
||
name: item.venueName
|
||
}))
|
||
}
|
||
})
|
||
}
|
||
|
||
export function getProjects(params) {
|
||
return request({
|
||
url: '/martial/project/list',
|
||
method: 'GET',
|
||
params: {
|
||
...params,
|
||
current: 1,
|
||
size: 100
|
||
}
|
||
}).then(res => {
|
||
return {
|
||
...res,
|
||
data: res.data.records.map(item => ({
|
||
id: item.id,
|
||
name: item.projectName
|
||
}))
|
||
}
|
||
})
|
||
}
|
||
```
|
||
|
||
```javascript
|
||
// api/score.js
|
||
export function getDeductions(params) {
|
||
return request({
|
||
url: '/martial/deductionItem/list',
|
||
method: 'GET',
|
||
params: {
|
||
...params,
|
||
current: 1,
|
||
size: 100
|
||
}
|
||
}).then(res => {
|
||
return {
|
||
...res,
|
||
data: res.data.records.map(item => ({
|
||
id: item.id,
|
||
text: item.itemName,
|
||
score: item.deductionPoint,
|
||
category: item.category
|
||
}))
|
||
}
|
||
})
|
||
}
|
||
```
|
||
|
||
### 2. 扣分项数据格式
|
||
|
||
提交评分时,后端可能需要 `deductionItems` 为JSON字符串。
|
||
|
||
**修改 api/score.js**:
|
||
|
||
```javascript
|
||
export function submitScore(data) {
|
||
return request({
|
||
url: '/martial/score/submit',
|
||
method: 'POST',
|
||
data: {
|
||
athleteId: data.athleteId,
|
||
judgeId: data.judgeId,
|
||
score: data.score,
|
||
deductionItems: JSON.stringify(data.deductions), // 转为JSON字符串
|
||
note: data.note
|
||
},
|
||
showLoading: true,
|
||
loadingText: '提交中...'
|
||
})
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 🧪 测试流程
|
||
|
||
### 1. Mock模式测试(后端未就绪时)
|
||
|
||
```javascript
|
||
// config/env.config.js
|
||
dataMode: 'mock'
|
||
```
|
||
|
||
**测试步骤**:
|
||
1. 登录页面:输入任意比赛编码,邀请码输入 `pub` 或 `admin`
|
||
2. 评分列表:查看3个选手,其中2个已评分
|
||
3. 评分详情:选择未评分选手,进行评分
|
||
4. 裁判长页面:切换场地和项目,查看选手列表
|
||
5. 修改评分:选择已评分选手,修改分数
|
||
|
||
### 2. API模式测试(后端就绪后)
|
||
|
||
```javascript
|
||
// config/env.config.js
|
||
dataMode: 'api'
|
||
apiBaseURL: 'http://localhost:8080'
|
||
```
|
||
|
||
**测试步骤**:
|
||
|
||
#### 步骤1: 测试登录
|
||
```
|
||
1. 打开登录页面
|
||
2. 输入比赛编码: 123
|
||
3. 输入邀请码: pub
|
||
4. 点击"立即评分"
|
||
5. 检查是否跳转到评分列表页面
|
||
6. 检查Token是否保存成功
|
||
```
|
||
|
||
#### 步骤2: 测试选手列表
|
||
```
|
||
1. 查看选手列表是否正确显示
|
||
2. 检查已评分/未评分状态
|
||
3. 检查我的评分和总分显示
|
||
```
|
||
|
||
#### 步骤3: 测试评分提交
|
||
```
|
||
1. 点击未评分选手的"评分"按钮
|
||
2. 选择扣分项
|
||
3. 输入备注
|
||
4. 点击"提交评分"
|
||
5. 检查是否提交成功
|
||
6. 返回列表,检查状态是否更新
|
||
```
|
||
|
||
#### 步骤4: 测试裁判长功能
|
||
```
|
||
1. 退出登录,使用 admin 邀请码登录
|
||
2. 切换场地和项目
|
||
3. 查看选手列表和评分统计
|
||
4. 点击"修改"按钮
|
||
5. 修改分数并提交
|
||
6. 检查是否修改成功
|
||
```
|
||
|
||
---
|
||
|
||
## 🐛 常见问题
|
||
|
||
### 1. Token过期处理
|
||
|
||
**现象**: 接口返回401错误
|
||
|
||
**处理**: [utils/request.js:114-131](../utils/request.js#L114-L131) 已实现自动处理
|
||
- 显示提示"Token已过期,请重新登录"
|
||
- 清除本地Token
|
||
- 1.5秒后跳转到登录页
|
||
|
||
### 2. 网络错误
|
||
|
||
**现象**: 接口调用失败,显示"网络错误"
|
||
|
||
**排查**:
|
||
1. 检查后端服务是否启动
|
||
2. 检查 `apiBaseURL` 配置是否正确
|
||
3. 检查网络连接
|
||
4. 检查CORS跨域配置
|
||
|
||
### 3. 数据格式不匹配
|
||
|
||
**现象**: 接口返回数据,但页面显示异常
|
||
|
||
**排查**:
|
||
1. 打开调试模式: `config.debug = true`
|
||
2. 查看控制台日志
|
||
3. 检查响应数据格式
|
||
4. 对比Mock数据和API数据的差异
|
||
5. 在 `api/*.js` 中添加数据转换
|
||
|
||
### 4. 分页数据提取
|
||
|
||
**现象**: 场地、项目列表显示为空
|
||
|
||
**原因**: 后端返回的是 `data.records`,不是 `data`
|
||
|
||
**解决**: 参考上面"需要适配的地方"章节
|
||
|
||
---
|
||
|
||
## 📝 联调检查清单
|
||
|
||
### 前端准备
|
||
|
||
- [x] dataAdapter 架构完成
|
||
- [x] API接口定义完成
|
||
- [x] request.js 优化完成
|
||
- [x] Mock数据格式修复
|
||
- [x] 页面接入完成
|
||
- [ ] 分页数据适配(等待后端确认格式)
|
||
- [ ] 扣分项格式适配(等待后端确认格式)
|
||
|
||
### 后端准备
|
||
|
||
- [ ] 5个小程序专用接口开发完成
|
||
- [ ] 测试数据准备完成
|
||
- [ ] Swagger文档更新
|
||
- [ ] 单元测试通过
|
||
|
||
### 联调测试
|
||
|
||
- [ ] 登录接口测试(pub角色)
|
||
- [ ] 登录接口测试(admin角色)
|
||
- [ ] 获取选手列表测试
|
||
- [ ] 提交评分测试
|
||
- [ ] 评分详情查看测试
|
||
- [ ] 修改评分测试
|
||
- [ ] Token过期处理测试
|
||
- [ ] 权限验证测试
|
||
- [ ] 场地切换测试
|
||
- [ ] 项目切换测试
|
||
|
||
---
|
||
|
||
## 📞 联系方式
|
||
|
||
如有问题,请联系:
|
||
- **前端负责人**: [待填写]
|
||
- **后端负责人**: [待填写]
|
||
|
||
---
|
||
|
||
**文档版本**: v1.0
|
||
**最后更新**: 2025-12-12
|
||
**相关文档**:
|
||
- [后端接口开发清单](./后端接口开发清单.md)
|
||
- [API接口测试指南](./API接口测试指南.md)
|