完成内容: - 5个完整的UI页面(登录、评分列表、评分详情、多场地列表、修改评分) - 完整的Mock数据展示 - 完整的业务逻辑实现 - 文档体系建立(2000+行文档) 文档包含: - 项目概述.md - 页面功能说明.md - API接口设计.md (17个接口) - 数据结构设计.md (17个接口定义) - 功能模块划分.md - 后端实现对比报告.md - 数据可行性分析报告.md (95分评估) - 保护Mock版本的实施方案.md (4层保护机制) - API对接完成度检查报告.md 此版本为Mock原型版本,所有UI功能完整,数据为硬编码Mock数据。
752 lines
14 KiB
Markdown
752 lines
14 KiB
Markdown
# 页面功能说明
|
||
|
||
## 页面总览
|
||
|
||
| 页面 | 路径 | 权限 | 功能描述 |
|
||
|------|------|------|----------|
|
||
| 登录页 | pages/login/login.vue | 所有用户 | 用户登录认证 |
|
||
| 评分列表页 | pages/score-list/score-list.vue | 普通评委(pub) | 查看选手列表并进行评分 |
|
||
| 评分详情页 | pages/score-detail/score-detail.vue | 普通评委(pub) | 对选手进行详细评分 |
|
||
| 多场地列表页 | pages/score-list-multi/score-list-multi.vue | 裁判长(admin) | 查看所有场地和项目 |
|
||
| 修改评分页 | pages/modify-score/modify-score.vue | 裁判长(admin) | 修改已有评分 |
|
||
|
||
---
|
||
|
||
## 1. 登录页 (login.vue)
|
||
|
||
### 页面路径
|
||
`pages/login/login.vue`
|
||
|
||
### 访问权限
|
||
所有用户
|
||
|
||
### 页面功能
|
||
|
||
#### 核心功能
|
||
- 用户通过比赛编码和邀请码进行登录认证
|
||
- 根据邀请码类型(pub/admin)自动跳转到对应页面
|
||
|
||
#### 页面元素
|
||
|
||
1. **自定义导航栏**
|
||
- 标题: "评分系统"
|
||
- 右侧图标: 菜单按钮、关闭按钮
|
||
|
||
2. **输入区域**
|
||
- 比赛编码输入框
|
||
- 评委邀请码输入框
|
||
|
||
3. **操作按钮**
|
||
- "立即评分" 提交按钮
|
||
|
||
### 数据结构
|
||
|
||
```javascript
|
||
data() {
|
||
return {
|
||
matchCode: '', // 比赛编码
|
||
inviteCode: '' // 邀请码 (pub/admin)
|
||
}
|
||
}
|
||
```
|
||
|
||
### 业务逻辑
|
||
|
||
#### 提交流程
|
||
1. 验证比赛编码不为空
|
||
2. 验证邀请码不为空
|
||
3. 判断邀请码类型(pub 或 admin)
|
||
4. 保存用户信息到全局数据
|
||
5. 根据角色跳转页面
|
||
|
||
```javascript
|
||
// 全局数据存储
|
||
getApp().globalData = {
|
||
userRole: 'pub' | 'admin', // 用户角色
|
||
matchCode: string // 比赛编码
|
||
}
|
||
```
|
||
|
||
#### 角色跳转规则
|
||
- **admin (裁判长)**: 跳转到多场地列表页 (score-list-multi)
|
||
- **pub (普通评委)**: 跳转到评分列表页 (score-list)
|
||
|
||
### 需要对接的API
|
||
|
||
#### 1. 登录认证接口
|
||
|
||
**接口**: `POST /api/auth/login`
|
||
|
||
**请求参数**:
|
||
```json
|
||
{
|
||
"matchCode": "string", // 比赛编码
|
||
"inviteCode": "string" // 邀请码
|
||
}
|
||
```
|
||
|
||
**返回数据**:
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "登录成功",
|
||
"data": {
|
||
"token": "string", // JWT Token
|
||
"userRole": "pub|admin", // 用户角色
|
||
"matchId": "string", // 比赛ID
|
||
"matchName": "string", // 比赛名称
|
||
"judgeName": "string", // 评委姓名
|
||
"judgeId": "string" // 评委ID
|
||
}
|
||
}
|
||
```
|
||
|
||
### 样式特点
|
||
- 使用渐变背景(深绿到浅绿)
|
||
- 输入框带阴影和圆角
|
||
- 提交按钮带渐变和悬停效果
|
||
|
||
---
|
||
|
||
## 2. 评分列表页 (score-list.vue)
|
||
|
||
### 页面路径
|
||
`pages/score-list/score-list.vue`
|
||
|
||
### 访问权限
|
||
普通评委 (pub)
|
||
|
||
### 页面功能
|
||
|
||
#### 核心功能
|
||
- 显示当前比赛信息
|
||
- 显示选手列表
|
||
- 查看已评分/未评分状态
|
||
- 跳转到评分详情页进行评分
|
||
|
||
#### 页面元素
|
||
|
||
1. **自定义导航栏**
|
||
- 标题: "评分系统"
|
||
|
||
2. **比赛信息区域**
|
||
- 比赛标题
|
||
- 比赛时间
|
||
|
||
3. **场地和项目区域**
|
||
- 当前场地显示(第一场地)
|
||
- 当前项目显示(男子组陈氏太极拳)
|
||
|
||
4. **评分统计**
|
||
- 已评分数量/总数 (如: 2/30)
|
||
|
||
5. **选手列表**
|
||
- 选手姓名
|
||
- 身份证号
|
||
- 队伍名称
|
||
- 编号
|
||
- 我的评分(已评分时显示)
|
||
- 总分(已评分时显示)
|
||
- "评分"按钮(未评分时显示)
|
||
|
||
### 数据结构
|
||
|
||
```javascript
|
||
// 当前为静态Mock数据,需要从API获取
|
||
data() {
|
||
return {
|
||
matchInfo: {
|
||
title: '2025年全国武术散打锦标赛暨第十七届世界武术锦标赛选拔赛',
|
||
time: '2025年6月25日 9:00'
|
||
},
|
||
venue: '第一场地',
|
||
project: '男子组陈氏太极拳',
|
||
scoreStats: {
|
||
scored: 2, // 已评分数
|
||
total: 30 // 总数
|
||
},
|
||
players: [] // 选手列表
|
||
}
|
||
}
|
||
```
|
||
|
||
### 需要对接的API
|
||
|
||
#### 1. 获取比赛信息
|
||
|
||
**接口**: `GET /api/match/{matchId}`
|
||
|
||
**返回数据**:
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"data": {
|
||
"matchId": "string",
|
||
"matchName": "string",
|
||
"matchTime": "2025-06-25T09:00:00",
|
||
"venue": "第一场地",
|
||
"project": "男子组陈氏太极拳"
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 2. 获取选手列表
|
||
|
||
**接口**: `GET /api/athletes`
|
||
|
||
**请求参数**:
|
||
```
|
||
matchId: string
|
||
venueId: string
|
||
projectId: string
|
||
judgeId: string
|
||
```
|
||
|
||
**返回数据**:
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"data": {
|
||
"total": 30,
|
||
"scored": 2,
|
||
"athletes": [
|
||
{
|
||
"athleteId": "string",
|
||
"name": "张三",
|
||
"idCard": "123456789000000000",
|
||
"team": "少林寺武术大学院",
|
||
"number": "123-4567898275",
|
||
"myScore": 8.906, // 我的评分(已评分)
|
||
"totalScore": 8.907, // 总分(已评分)
|
||
"scored": true // 是否已评分
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
### 交互逻辑
|
||
|
||
1. 点击"评分"按钮跳转到评分详情页
|
||
2. 页面显示时自动刷新选手列表
|
||
3. 已评分的选手显示分数,未评分显示评分按钮
|
||
|
||
---
|
||
|
||
## 3. 评分详情页 (score-detail.vue)
|
||
|
||
### 页面路径
|
||
`pages/score-detail/score-detail.vue`
|
||
|
||
### 访问权限
|
||
普通评委 (pub)
|
||
|
||
### 页面功能
|
||
|
||
#### 核心功能
|
||
- 对选手进行精确评分(精度0.001)
|
||
- 选择扣分项(多选)
|
||
- 填写评分备注
|
||
- 提交评分
|
||
|
||
#### 页面元素
|
||
|
||
1. **自定义导航栏**
|
||
- 返回按钮
|
||
- 标题: "评分详情"
|
||
|
||
2. **选手信息区域**
|
||
- 选手姓名
|
||
- 身份证号
|
||
- 队伍名称
|
||
- 编号
|
||
|
||
3. **评分提示**
|
||
- "点击分数填写或拖动滑块打分(5-10分)"
|
||
|
||
4. **分数控制区域**
|
||
- 减少按钮(-0.001)
|
||
- 当前分数显示(3位小数)
|
||
- 增加按钮(+0.001)
|
||
|
||
5. **扣分项区域**
|
||
- 8个扣分项(多选)
|
||
- 圆形复选框
|
||
|
||
6. **备注区域**
|
||
- 多行文本输入框
|
||
- 最大200字
|
||
|
||
7. **提交按钮**
|
||
|
||
### 数据结构
|
||
|
||
```javascript
|
||
data() {
|
||
return {
|
||
athleteId: '', // 选手ID(从路由参数获取)
|
||
currentScore: 8.907, // 当前评分
|
||
note: '', // 备注
|
||
minScore: 5.0, // 最低分
|
||
maxScore: 10.0, // 最高分
|
||
deductions: [ // 扣分项列表
|
||
{ id: 1, text: '扣分项描述', checked: false },
|
||
{ id: 2, text: '扣分项描述', checked: false },
|
||
// ... 共8项
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
### 业务逻辑
|
||
|
||
#### 评分控制
|
||
- 每次点击增加/减少0.001分
|
||
- 分数范围: 5.000 - 10.000
|
||
- 超出范围时按钮置灰(需实现)
|
||
|
||
#### 扣分项选择
|
||
- 支持多选
|
||
- 点击切换选中状态
|
||
|
||
#### 提交评分
|
||
1. 验证分数范围
|
||
2. 收集扣分项
|
||
3. 提交数据到后端
|
||
4. 显示成功提示
|
||
5. 返回列表页
|
||
|
||
### 需要对接的API
|
||
|
||
#### 1. 获取选手详情
|
||
|
||
**接口**: `GET /api/athletes/{athleteId}`
|
||
|
||
**返回数据**:
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"data": {
|
||
"athleteId": "string",
|
||
"name": "张三",
|
||
"idCard": "123456789000000000",
|
||
"team": "少林寺武术大学院",
|
||
"number": "123-4567898275",
|
||
"defaultScore": 8.907 // 默认分数
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 2. 获取扣分项列表
|
||
|
||
**接口**: `GET /api/deductions`
|
||
|
||
**请求参数**:
|
||
```
|
||
projectId: string
|
||
```
|
||
|
||
**返回数据**:
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"data": [
|
||
{
|
||
"deductionId": "string",
|
||
"text": "扣分项描述",
|
||
"score": -0.1 // 扣分值
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
#### 3. 提交评分
|
||
|
||
**接口**: `POST /api/scores`
|
||
|
||
**请求参数**:
|
||
```json
|
||
{
|
||
"matchId": "string",
|
||
"athleteId": "string",
|
||
"judgeId": "string",
|
||
"score": 8.907,
|
||
"deductions": ["deductionId1", "deductionId2"],
|
||
"note": "string"
|
||
}
|
||
```
|
||
|
||
**返回数据**:
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "评分提交成功",
|
||
"data": {
|
||
"scoreId": "string",
|
||
"createTime": "2025-06-25T09:15:00"
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 4. 多场地列表页 (score-list-multi.vue)
|
||
|
||
### 页面路径
|
||
`pages/score-list-multi/score-list-multi.vue`
|
||
|
||
### 访问权限
|
||
裁判长 (admin)
|
||
|
||
### 页面功能
|
||
|
||
#### 核心功能
|
||
- 查看所有场地和项目
|
||
- 切换场地(横向滚动)
|
||
- 切换项目(横向滚动)
|
||
- 查看各场地选手列表
|
||
- 修改已有评分
|
||
|
||
#### 页面元素
|
||
|
||
1. **自定义导航栏**
|
||
- 标题: "评分系统"
|
||
|
||
2. **比赛信息区域**
|
||
- 比赛标题
|
||
- 比赛时间
|
||
|
||
3. **场地切换区域**
|
||
- 5个场地横向滚动切换
|
||
- 当前场地高亮显示
|
||
|
||
4. **项目切换区域**
|
||
- 8个项目横向滚动切换
|
||
- 当前项目高亮显示
|
||
|
||
5. **评分统计**
|
||
- 当前场地已评分数/总数
|
||
|
||
6. **选手列表**
|
||
- 选手信息
|
||
- 总分显示
|
||
- "修改"按钮
|
||
|
||
### 数据结构
|
||
|
||
```javascript
|
||
data() {
|
||
return {
|
||
currentVenue: 1, // 当前场地ID
|
||
currentProject: 0, // 当前项目索引
|
||
venues: [ // 场地列表
|
||
{ id: 1, name: '第一场地' },
|
||
{ id: 2, name: '第二场地' },
|
||
{ id: 3, name: '第三场地' },
|
||
{ id: 4, name: '第四场地' },
|
||
{ id: 5, name: '第五场地' }
|
||
],
|
||
projects: [ // 项目列表
|
||
'女子组长拳',
|
||
'男子组陈氏太极拳',
|
||
'女子组双剑(含长穗双剑)',
|
||
'男子组杨氏太极拳',
|
||
'女子组刀术',
|
||
'男子组棍术',
|
||
'女子组枪术',
|
||
'男子组剑术'
|
||
],
|
||
players: [] // 选手列表
|
||
}
|
||
}
|
||
```
|
||
|
||
### 需要对接的API
|
||
|
||
#### 1. 获取场地列表
|
||
|
||
**接口**: `GET /api/venues`
|
||
|
||
**请求参数**:
|
||
```
|
||
matchId: string
|
||
```
|
||
|
||
**返回数据**:
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"data": [
|
||
{
|
||
"venueId": "string",
|
||
"venueName": "第一场地",
|
||
"order": 1
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
#### 2. 获取项目列表
|
||
|
||
**接口**: `GET /api/projects`
|
||
|
||
**请求参数**:
|
||
```
|
||
matchId: string
|
||
```
|
||
|
||
**返回数据**:
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"data": [
|
||
{
|
||
"projectId": "string",
|
||
"projectName": "女子组长拳",
|
||
"order": 1
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
#### 3. 获取选手列表(带总分)
|
||
|
||
**接口**: `GET /api/athletes/scored`
|
||
|
||
**请求参数**:
|
||
```
|
||
matchId: string
|
||
venueId: string
|
||
projectId: string
|
||
```
|
||
|
||
**返回数据**:
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"data": {
|
||
"total": 30,
|
||
"scored": 25,
|
||
"athletes": [
|
||
{
|
||
"athleteId": "string",
|
||
"name": "张三",
|
||
"idCard": "123456789000000000",
|
||
"team": "少林寺武术大学院",
|
||
"number": "123-4567898275",
|
||
"totalScore": 8.907, // 总分
|
||
"judgeCount": 6, // 评委数量
|
||
"canModify": true // 是否可修改
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
### 交互逻辑
|
||
|
||
1. 横向滚动切换场地
|
||
2. 横向滚动切换项目
|
||
3. 切换场地/项目时自动加载对应选手列表
|
||
4. 点击"修改"按钮跳转到修改评分页
|
||
|
||
---
|
||
|
||
## 5. 修改评分页 (modify-score.vue)
|
||
|
||
### 页面路径
|
||
`pages/modify-score/modify-score.vue`
|
||
|
||
### 访问权限
|
||
裁判长 (admin)
|
||
|
||
### 页面功能
|
||
|
||
#### 核心功能
|
||
- 查看选手信息和当前总分
|
||
- 查看所有评委的评分详情
|
||
- 修改总分(精度0.001)
|
||
- 填写修改备注
|
||
- 提交修改
|
||
|
||
#### 页面元素
|
||
|
||
1. **自定义导航栏**
|
||
- 返回按钮
|
||
- 标题: "修改评分"
|
||
|
||
2. **选手信息区域**
|
||
- 选手姓名
|
||
- 当前总分
|
||
- 身份证号
|
||
- 队伍名称
|
||
- 编号
|
||
|
||
3. **评委评分统计区域**
|
||
- 标题: "共有X位评委完成评分"
|
||
- 各评委的评分列表
|
||
|
||
4. **修改总分区域**
|
||
- 说明: "修改总分(+-0.005分)"
|
||
- 减少按钮(-0.001)
|
||
- 当前分数显示
|
||
- "可不改"提示
|
||
- 增加按钮(+0.001)
|
||
|
||
5. **备注区域**
|
||
- 多行文本输入框
|
||
- "可不填"提示
|
||
- 最大200字
|
||
|
||
6. **修改按钮**
|
||
|
||
### 数据结构
|
||
|
||
```javascript
|
||
data() {
|
||
return {
|
||
athleteId: '', // 选手ID
|
||
originalScore: 8.907, // 原始总分
|
||
currentScore: 8.907, // 修改后的分数
|
||
note: '', // 修改备注
|
||
minScore: 5.0, // 最低分
|
||
maxScore: 10.0, // 最高分
|
||
judgeScores: [] // 评委评分列表
|
||
}
|
||
}
|
||
```
|
||
|
||
### 需要对接的API
|
||
|
||
#### 1. 获取选手评分详情
|
||
|
||
**接口**: `GET /api/scores/{athleteId}/detail`
|
||
|
||
**返回数据**:
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"data": {
|
||
"athleteId": "string",
|
||
"name": "张三",
|
||
"idCard": "123456789000000000",
|
||
"team": "少林寺武术大学院",
|
||
"number": "123-4567898275",
|
||
"totalScore": 8.907,
|
||
"judgeCount": 6,
|
||
"judgeScores": [
|
||
{
|
||
"judgeId": "string",
|
||
"judgeName": "欧阳丽娜",
|
||
"score": 8.907,
|
||
"deductions": ["扣分项1", "扣分项2"],
|
||
"note": "备注内容",
|
||
"scoreTime": "2025-06-25T09:15:00"
|
||
}
|
||
],
|
||
"modifications": [
|
||
{
|
||
"modifyId": "string",
|
||
"modifier": "裁判长姓名",
|
||
"originalScore": 8.907,
|
||
"modifiedScore": 8.910,
|
||
"note": "修改原因",
|
||
"modifyTime": "2025-06-25T10:00:00"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 2. 修改评分
|
||
|
||
**接口**: `PUT /api/scores/{athleteId}/modify`
|
||
|
||
**请求参数**:
|
||
```json
|
||
{
|
||
"athleteId": "string",
|
||
"originalScore": 8.907,
|
||
"modifiedScore": 8.910,
|
||
"note": "修改原因",
|
||
"modifier": "裁判长ID"
|
||
}
|
||
```
|
||
|
||
**返回数据**:
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "修改成功",
|
||
"data": {
|
||
"modifyId": "string",
|
||
"modifiedScore": 8.910,
|
||
"modifyTime": "2025-06-25T10:00:00"
|
||
}
|
||
}
|
||
```
|
||
|
||
### 业务逻辑
|
||
|
||
#### 修改总分
|
||
- 每次点击增加/减少0.001分
|
||
- 分数范围: 5.000 - 10.000
|
||
- "可不改"表示可以不修改分数
|
||
|
||
#### 提交修改
|
||
1. 验证分数范围
|
||
2. 检查是否有实际修改
|
||
3. 提交数据到后端
|
||
4. 显示成功提示
|
||
5. 返回多场地列表页
|
||
|
||
### 交互逻辑
|
||
|
||
1. 显示所有评委的评分明细
|
||
2. 裁判长可以调整总分
|
||
3. 必须填写修改备注(可选)
|
||
4. 提交后返回列表页
|
||
|
||
---
|
||
|
||
## 页面间跳转关系
|
||
|
||
```
|
||
登录页 (login.vue)
|
||
├─→ [pub角色] → 评分列表页 (score-list.vue)
|
||
│ └─→ 评分详情页 (score-detail.vue)
|
||
│ └─→ [提交后返回] → 评分列表页
|
||
│
|
||
└─→ [admin角色] → 多场地列表页 (score-list-multi.vue)
|
||
└─→ 修改评分页 (modify-score.vue)
|
||
└─→ [修改后返回] → 多场地列表页
|
||
```
|
||
|
||
## 页面共同特性
|
||
|
||
### 1. 自定义导航栏
|
||
所有页面都使用自定义导航栏(`navigationStyle: "custom"`)
|
||
|
||
- 高度: 90rpx
|
||
- 背景: 渐变绿色 (#1B7C5E → #2A9D7E)
|
||
- 标题居中
|
||
- 右侧固定菜单和关闭按钮
|
||
|
||
### 2. 响应式设计
|
||
使用rpx单位实现跨设备适配
|
||
|
||
### 3. 色彩系统统一
|
||
- 主色: #1B7C5E(深绿)
|
||
- 次色: #2A9D7E(浅绿)
|
||
- 强调色: #FF4D6A(红色)
|
||
|
||
### 4. 交互反馈
|
||
- 按钮点击有透明度变化
|
||
- 表单验证有toast提示
|
||
- 加载状态需要添加loading(待实现)
|
||
|
||
### 5. 错误处理
|
||
- 网络请求失败提示(待实现)
|
||
- 表单验证提示
|
||
- 权限验证提示
|