Files
martial-admin-mini/pages/score-list/score-list.vue
宅房 dc9743e6db feat: 完成5个页面接入dataAdapter - Mock模式功能完成
改造页面列表:
- login.vue: 登录验证使用dataAdapter
- score-list.vue: 普通评委选手列表加载
- score-detail.vue: 评分提交和扣分项加载
- score-list-multi.vue: 裁判长多场地列表(含场地/项目切换)
- modify-score.vue: 裁判长修改评分

关键特性:
-  所有页面使用dataAdapter统一数据接口
-  UI模板和样式完全保持不变(零UI修改)
-  支持Mock/API模式一键切换
-  完整的错误处理和加载提示
-  调试模式下输出详细日志

Mock模式测试准备完成,可通过修改config/env.config.js中dataMode切换到API模式。

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-11 14:48:51 +08:00

442 lines
8.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="container">
<!-- 自定义导航栏 -->
<view class="nav-bar">
<view class="nav-title">评分系统</view>
<view class="nav-right">
<view class="icon-menu">···</view>
<view class="icon-close"></view>
</view>
</view>
<!-- 比赛信息 -->
<view class="match-info">
<view class="match-title">{{ matchInfo.name }}</view>
<view class="match-time">比赛时间{{ matchInfo.time }}</view>
</view>
<!-- 场地和项目选择 -->
<view class="venue-section">
<view class="venue-header">
<view class="venue-tab active">{{ venueInfo.name }}</view>
</view>
<view class="project-section">
<view class="project-btn active">{{ projectInfo.name }}</view>
</view>
</view>
<!-- 已评分统计 -->
<view class="score-stats">
<text class="stats-text">已评分</text>
<text class="stats-number">{{ scoredCount }}/{{ totalCount }}</text>
</view>
<!-- 选手列表 -->
<view class="player-list">
<!-- 遍历选手列表 -->
<view
class="player-card"
v-for="player in players"
:key="player.athleteId"
>
<view class="player-header">
<view class="player-name">{{ player.name }}</view>
<!-- 已评分显示我的评分和总分 -->
<view class="player-scores" v-if="player.scored">
<text class="my-score">我的评分{{ player.myScore }}</text>
<text class="total-score">总分{{ player.totalScore }}</text>
</view>
<!-- 未评分显示评分按钮 -->
<button
class="score-btn"
v-else
@click="goToScoreDetail(player)"
>
评分
</button>
</view>
<view class="player-info">
<view class="info-item">身份证{{ player.idCard }}</view>
<view class="info-item">队伍{{ player.team }}</view>
<view class="info-item">编号{{ player.number }}</view>
</view>
</view>
</view>
</view>
</template>
<script>
import dataAdapter from '@/utils/dataAdapter.js'
import config from '@/config/env.config.js'
export default {
data() {
return {
matchInfo: {
name: '',
time: ''
},
venueInfo: {
id: '',
name: ''
},
projectInfo: {
id: '',
name: ''
},
judgeId: '',
players: [],
scoredCount: 0,
totalCount: 0
}
},
async onLoad() {
// 获取全局数据
const app = getApp()
const globalData = app.globalData || {}
// 加载比赛信息
this.matchInfo = {
name: globalData.matchName || '比赛名称',
time: globalData.matchTime || '比赛时间'
}
// 加载场地信息
this.venueInfo = {
id: globalData.venueId,
name: globalData.venueName || '场地'
}
// 加载项目信息
const projects = globalData.projects || []
const currentIndex = globalData.currentProjectIndex || 0
const currentProject = projects[currentIndex] || {}
this.projectInfo = {
id: currentProject.projectId,
name: currentProject.projectName || '项目'
}
this.judgeId = globalData.judgeId
// 调试信息
if (config.debug) {
console.log('评分列表页加载:', {
judgeId: this.judgeId,
venueId: this.venueInfo.id,
projectId: this.projectInfo.id
})
}
// 加载选手列表
await this.loadPlayers()
},
methods: {
async loadPlayers() {
try {
uni.showLoading({
title: '加载中...',
mask: true
})
// 🔥 关键改动:使用 dataAdapter 获取选手列表
// Mock模式调用 mock/athlete.js 的 getMyAthletes 函数
// API模式调用 api/athlete.js 的 getMyAthletes 函数GET /api/mini/athletes
const response = await dataAdapter.getData('getMyAthletes', {
judgeId: this.judgeId,
venueId: this.venueInfo.id,
projectId: this.projectInfo.id
})
uni.hideLoading()
// 保存选手列表
this.players = response.data || []
// 计算评分统计
this.totalCount = this.players.length
this.scoredCount = this.players.filter(p => p.scored).length
// 调试信息
if (config.debug) {
console.log('选手列表加载成功:', {
total: this.totalCount,
scored: this.scoredCount,
players: this.players
})
}
} catch (error) {
uni.hideLoading()
console.error('加载选手列表失败:', error)
uni.showToast({
title: error.message || '加载失败',
icon: 'none'
})
}
},
goToScoreDetail(player) {
// 保存当前选手信息到全局数据
const app = getApp()
app.globalData.currentAthlete = player
uni.navigateTo({
url: '/pages/score-detail/score-detail'
})
}
}
}
</script>
<style scoped>
.container {
min-height: 100vh;
background-color: #F5F5F5;
padding-bottom: 40rpx;
}
/* 导航栏 */
.nav-bar {
height: 90rpx;
background: linear-gradient(135deg, #1B7C5E 0%, #2A9D7E 100%);
display: flex;
align-items: center;
justify-content: center;
position: relative;
padding: 0 30rpx;
}
.nav-title {
font-size: 36rpx;
font-weight: 600;
color: #FFFFFF;
letter-spacing: 2rpx;
}
.nav-right {
position: absolute;
right: 30rpx;
display: flex;
align-items: center;
gap: 30rpx;
}
.icon-menu,
.icon-close {
width: 60rpx;
height: 60rpx;
background-color: rgba(255, 255, 255, 0.25);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 32rpx;
color: #FFFFFF;
font-weight: bold;
}
/* 比赛信息 */
.match-info {
padding: 30rpx;
background-color: #F5F5F5;
}
.match-title {
font-size: 32rpx;
font-weight: 600;
color: #333333;
line-height: 1.6;
margin-bottom: 10rpx;
}
.tip-text {
font-size: 24rpx;
color: #FF4D6A;
margin-bottom: 10rpx;
}
.match-time {
font-size: 28rpx;
color: #666666;
}
/* 场地和项目区域 */
.venue-section {
background-color: #FFFFFF;
margin: 20rpx 30rpx;
border-radius: 16rpx;
padding: 30rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
}
.venue-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 30rpx;
padding-bottom: 20rpx;
border-bottom: 4rpx solid #1B7C5E;
}
.venue-tab {
font-size: 32rpx;
font-weight: 600;
color: #333333;
position: relative;
}
.venue-tab.active::after {
content: '';
position: absolute;
bottom: -24rpx;
left: 0;
right: 0;
height: 4rpx;
background-color: #1B7C5E;
}
.refresh-hint {
font-size: 24rpx;
color: #FF4D6A;
}
.project-section {
display: flex;
align-items: center;
justify-content: space-between;
}
.project-btn {
padding: 20rpx 40rpx;
background-color: #FFFFFF;
border: 2rpx solid #1B7C5E;
border-radius: 8rpx;
font-size: 28rpx;
color: #1B7C5E;
font-weight: 500;
}
.project-btn.active {
background-color: #1B7C5E;
color: #FFFFFF;
}
.project-tip {
font-size: 22rpx;
color: #FF4D6A;
flex: 1;
margin-left: 20rpx;
line-height: 1.5;
}
/* 评分统计 */
.score-stats {
padding: 20rpx 30rpx;
font-size: 28rpx;
color: #333333;
}
.stats-text {
color: #666666;
}
.stats-number {
color: #1B7C5E;
font-weight: 600;
}
.warning-tip {
padding: 0 30rpx 20rpx;
font-size: 24rpx;
color: #FF4D6A;
}
/* 选手列表 */
.player-list {
padding: 0 30rpx;
}
.player-card {
background-color: #FFFFFF;
border-radius: 16rpx;
padding: 30rpx;
margin-bottom: 20rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
}
.player-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 20rpx;
}
.player-name {
font-size: 32rpx;
font-weight: 600;
color: #333333;
}
.player-scores {
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 8rpx;
}
.my-score {
font-size: 26rpx;
color: #666666;
}
.total-score {
font-size: 26rpx;
color: #333333;
font-weight: 600;
}
.action-area {
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 8rpx;
}
.chief-hint {
font-size: 24rpx;
color: #FF4D6A;
}
.score-btn {
padding: 12rpx 40rpx;
background: linear-gradient(135deg, #1B7C5E 0%, #2A9D7E 100%);
border-radius: 8rpx;
font-size: 28rpx;
color: #FFFFFF;
font-weight: 500;
}
.score-btn:active {
opacity: 0.9;
}
.player-info {
display: flex;
flex-direction: column;
gap: 12rpx;
}
.info-item {
font-size: 26rpx;
color: #666666;
line-height: 1.5;
}
</style>