fix bugs
This commit is contained in:
303
src/pages/login/login.vue
Normal file
303
src/pages/login/login.vue
Normal file
@@ -0,0 +1,303 @@
|
||||
<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="content">
|
||||
<view class="page-title">进入评分</view>
|
||||
|
||||
<!-- 比赛编码输入 -->
|
||||
<view class="input-group">
|
||||
<view class="input-label">比赛编码</view>
|
||||
<view class="input-wrapper">
|
||||
<input
|
||||
class="input-field"
|
||||
type="text"
|
||||
placeholder="请输入比赛编码"
|
||||
v-model="matchCode"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 评委邀请码输入 -->
|
||||
<view class="input-group">
|
||||
<view class="input-label">评委邀请码</view>
|
||||
<view class="input-wrapper">
|
||||
<input
|
||||
class="input-field"
|
||||
type="text"
|
||||
placeholder="请输入评委邀请码"
|
||||
v-model="inviteCode"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 立即评分按钮 -->
|
||||
<button class="submit-btn" @click="handleSubmit">立即评分</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import dataAdapter from '@/utils/dataAdapter.js'
|
||||
import config from '@/config/env.config.js'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
matchCode: '',
|
||||
inviteCode: ''
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
// 开发环境显示当前数据模式
|
||||
if (config.debug) {
|
||||
console.log('='.repeat(50))
|
||||
console.log('当前数据模式:', config.dataMode)
|
||||
console.log('Mock模式:', dataAdapter.isMockMode() ? '是' : '否')
|
||||
console.log('API模式:', dataAdapter.isApiMode() ? '是' : '否')
|
||||
console.log('='.repeat(50))
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async handleSubmit() {
|
||||
// 表单验证
|
||||
if (!this.matchCode) {
|
||||
uni.showToast({
|
||||
title: '请输入比赛编码',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
if (!this.inviteCode) {
|
||||
uni.showToast({
|
||||
title: '请输入评委邀请码',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
// 显示加载
|
||||
uni.showLoading({
|
||||
title: '登录中...',
|
||||
mask: true
|
||||
})
|
||||
|
||||
// 🔥 关键改动:使用 dataAdapter 进行登录
|
||||
// Mock模式:调用 mock/login.js 的 login 函数
|
||||
// API模式:调用 api/auth.js 的 login 函数(POST /api/mini/login)
|
||||
const response = await dataAdapter.getData('login', {
|
||||
matchCode: this.matchCode,
|
||||
inviteCode: this.inviteCode
|
||||
})
|
||||
|
||||
uni.hideLoading()
|
||||
|
||||
// 处理登录响应(Mock和API返回格式相同)
|
||||
const {
|
||||
token,
|
||||
userRole,
|
||||
matchId,
|
||||
matchName,
|
||||
matchTime,
|
||||
judgeId,
|
||||
judgeName,
|
||||
venueId,
|
||||
venueName,
|
||||
projects
|
||||
} = response.data
|
||||
|
||||
// 保存Token到本地存储
|
||||
uni.setStorageSync('token', token)
|
||||
|
||||
// 保存用户信息到全局数据
|
||||
getApp().globalData = {
|
||||
userRole, // 'pub' 或 'admin'
|
||||
matchCode: this.matchCode,
|
||||
matchId,
|
||||
matchName,
|
||||
matchTime,
|
||||
judgeId,
|
||||
judgeName,
|
||||
venueId, // 普通评委有场地,裁判长为null
|
||||
venueName,
|
||||
projects, // 分配的项目列表
|
||||
currentProjectIndex: 0 // 当前选中的项目索引
|
||||
}
|
||||
|
||||
// 调试信息
|
||||
if (config.debug) {
|
||||
console.log('登录成功:', {
|
||||
userRole,
|
||||
judgeName,
|
||||
venueId: venueId || '全部场地',
|
||||
projects: projects.length + '个项目'
|
||||
})
|
||||
}
|
||||
|
||||
// 显示登录成功提示
|
||||
uni.showToast({
|
||||
title: '登录成功',
|
||||
icon: 'success',
|
||||
duration: 1500
|
||||
})
|
||||
|
||||
// 根据角色跳转到不同页面
|
||||
setTimeout(() => {
|
||||
if (userRole === 'admin') {
|
||||
// 裁判长跳转到多场地列表页(可以修改评分)
|
||||
uni.navigateTo({
|
||||
url: '/pages/score-list-multi/score-list-multi'
|
||||
})
|
||||
} else {
|
||||
// 普通裁判跳转到评分列表页(可以评分)
|
||||
uni.navigateTo({
|
||||
url: '/pages/score-list/score-list'
|
||||
})
|
||||
}
|
||||
}, 1500)
|
||||
|
||||
} catch (error) {
|
||||
uni.hideLoading()
|
||||
|
||||
// 错误处理
|
||||
console.error('登录失败:', error)
|
||||
|
||||
uni.showToast({
|
||||
title: error.message || '登录失败,请重试',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.container {
|
||||
min-height: 100vh;
|
||||
background-color: #F5F5F5;
|
||||
}
|
||||
|
||||
/* 导航栏 */
|
||||
.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;
|
||||
}
|
||||
|
||||
/* 主体内容 */
|
||||
.content {
|
||||
padding: 60rpx 40rpx;
|
||||
}
|
||||
|
||||
.page-title {
|
||||
font-size: 40rpx;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
margin-bottom: 60rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* 输入组 */
|
||||
.input-group {
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.input-label {
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.input-wrapper {
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.input-field {
|
||||
width: 100%;
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.input-field::placeholder {
|
||||
color: #CCCCCC;
|
||||
}
|
||||
|
||||
.input-tip {
|
||||
position: absolute;
|
||||
right: 30rpx;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
font-size: 24rpx;
|
||||
color: #FF4D6A;
|
||||
}
|
||||
|
||||
/* 提交按钮 */
|
||||
.submit-btn {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
background: linear-gradient(135deg, #1B7C5E 0%, #2A9D7E 100%);
|
||||
border-radius: 16rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #FFFFFF;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: 80rpx;
|
||||
box-shadow: 0 8rpx 20rpx rgba(27, 124, 94, 0.3);
|
||||
}
|
||||
|
||||
.submit-btn:active {
|
||||
opacity: 0.9;
|
||||
}
|
||||
</style>
|
||||
588
src/pages/modify-score/modify-score.vue
Normal file
588
src/pages/modify-score/modify-score.vue
Normal file
@@ -0,0 +1,588 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<!-- 自定义导航栏 -->
|
||||
<view class="nav-bar">
|
||||
<view class="nav-left" @click="goBack">
|
||||
<text class="back-icon">‹</text>
|
||||
</view>
|
||||
<view class="nav-title">修改评分</view>
|
||||
<view class="nav-right">
|
||||
<view class="icon-menu">···</view>
|
||||
<view class="icon-close">⊗</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 选手信息 -->
|
||||
<view class="player-info-section">
|
||||
<view class="player-header">
|
||||
<view class="player-name">{{ athleteInfo.name }}</view>
|
||||
<view class="total-score-label">
|
||||
<text class="label-text">总分:</text>
|
||||
<text class="score-value">{{ athleteInfo.totalScore }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="player-details">
|
||||
<view class="detail-item">身份证:{{ athleteInfo.idCard }}</view>
|
||||
<view class="detail-item">队伍:{{ athleteInfo.team }}</view>
|
||||
<view class="detail-item">编号:{{ athleteInfo.number }}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 评委评分统计 -->
|
||||
<view class="judges-section">
|
||||
<view class="section-title">共有{{ judgeScores.length }}位评委完成评分</view>
|
||||
<view class="judges-scores">
|
||||
<view
|
||||
class="judge-score-item"
|
||||
v-for="judge in judgeScores"
|
||||
:key="judge.judgeId"
|
||||
>
|
||||
<text class="judge-name">{{ judge.judgeName }}:</text>
|
||||
<text class="judge-score">{{ judge.score }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 修改总分区域 -->
|
||||
<view class="modify-section">
|
||||
<view class="modify-header">
|
||||
<text class="modify-label">修改总分(+-0.005分)</text>
|
||||
</view>
|
||||
|
||||
<view class="score-control">
|
||||
<view class="control-btn decrease" @click="decreaseScore">
|
||||
<text class="btn-symbol">-</text>
|
||||
<text class="btn-value">-0.001</text>
|
||||
</view>
|
||||
|
||||
<view class="score-display">
|
||||
<text class="current-score">{{ currentScore.toFixed(3) }}</text>
|
||||
<text class="no-modify-text">可不改</text>
|
||||
</view>
|
||||
|
||||
<view class="control-btn increase" @click="increaseScore">
|
||||
<text class="btn-symbol">+</text>
|
||||
<text class="btn-value">+0.001</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- <view class="modify-tip">
|
||||
裁判长修改:保留3位小数点,超过上限或下限时,按钮置灰
|
||||
</view> -->
|
||||
</view>
|
||||
|
||||
<!-- 备注 -->
|
||||
<view class="note-section">
|
||||
<view class="note-label">
|
||||
<text>备注:</text>
|
||||
</view>
|
||||
<view class="note-input-wrapper">
|
||||
<textarea
|
||||
class="note-input"
|
||||
placeholder="请输入修改备注"
|
||||
v-model="note"
|
||||
maxlength="200"
|
||||
/>
|
||||
<text class="optional-text">可不填</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 修改按钮 -->
|
||||
<button class="modify-btn" @click="handleModify">修改</button>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import dataAdapter from '@/utils/dataAdapter.js'
|
||||
import config from '@/config/env.config.js'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
athleteInfo: {
|
||||
athleteId: '',
|
||||
name: '',
|
||||
idCard: '',
|
||||
team: '',
|
||||
number: '',
|
||||
totalScore: 0
|
||||
},
|
||||
judgeScores: [],
|
||||
modification: null,
|
||||
modifierId: '',
|
||||
currentScore: 8.000,
|
||||
originalScore: 8.000,
|
||||
note: '',
|
||||
minScore: 5.0,
|
||||
maxScore: 10.0
|
||||
}
|
||||
},
|
||||
|
||||
async onLoad() {
|
||||
// 获取全局数据
|
||||
const app = getApp()
|
||||
const globalData = app.globalData || {}
|
||||
|
||||
// 获取当前选手信息(从 score-list-multi 页面传递)
|
||||
const currentAthlete = globalData.currentAthlete || {}
|
||||
|
||||
// 获取裁判长ID
|
||||
this.modifierId = globalData.judgeId
|
||||
|
||||
// 调试信息
|
||||
if (config.debug) {
|
||||
console.log('修改评分页加载:', {
|
||||
athleteId: currentAthlete.athleteId,
|
||||
modifierId: this.modifierId
|
||||
})
|
||||
}
|
||||
|
||||
// 加载选手评分详情
|
||||
if (currentAthlete.athleteId) {
|
||||
await this.loadScoreDetail(currentAthlete.athleteId)
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
async loadScoreDetail(athleteId) {
|
||||
try {
|
||||
uni.showLoading({
|
||||
title: '加载中...',
|
||||
mask: true
|
||||
})
|
||||
|
||||
// 🔥 关键改动:使用 dataAdapter 获取评分详情
|
||||
// Mock模式:调用 mock/score.js 的 getScoreDetail 函数
|
||||
// API模式:调用 api/score.js 的 getScoreDetail 函数(GET /api/mini/score/detail/{athleteId})
|
||||
const response = await dataAdapter.getData('getScoreDetail', {
|
||||
athleteId: athleteId
|
||||
})
|
||||
|
||||
uni.hideLoading()
|
||||
|
||||
// 保存选手信息和评分详情
|
||||
this.athleteInfo = response.data.athleteInfo || {}
|
||||
this.judgeScores = response.data.judgeScores || []
|
||||
this.modification = response.data.modification || null
|
||||
|
||||
// 设置初始分数
|
||||
this.originalScore = this.athleteInfo.totalScore || 8.000
|
||||
this.currentScore = this.originalScore
|
||||
|
||||
// 如果之前已修改过,加载修改后的分数
|
||||
if (this.modification && this.modification.modifiedScore) {
|
||||
this.currentScore = this.modification.modifiedScore
|
||||
}
|
||||
|
||||
// 调试信息
|
||||
if (config.debug) {
|
||||
console.log('评分详情加载成功:', {
|
||||
athlete: this.athleteInfo,
|
||||
judges: this.judgeScores.length,
|
||||
originalScore: this.originalScore,
|
||||
currentScore: this.currentScore,
|
||||
modification: this.modification
|
||||
})
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
uni.hideLoading()
|
||||
console.error('加载评分详情失败:', error)
|
||||
uni.showToast({
|
||||
title: error.message || '加载失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
goBack() {
|
||||
uni.navigateBack()
|
||||
},
|
||||
|
||||
decreaseScore() {
|
||||
if (this.currentScore > this.minScore) {
|
||||
this.currentScore = parseFloat((this.currentScore - 0.001).toFixed(3))
|
||||
}
|
||||
},
|
||||
|
||||
increaseScore() {
|
||||
if (this.currentScore < this.maxScore) {
|
||||
this.currentScore = parseFloat((this.currentScore + 0.001).toFixed(3))
|
||||
}
|
||||
},
|
||||
|
||||
async handleModify() {
|
||||
// 验证评分范围
|
||||
if (this.currentScore < this.minScore || this.currentScore > this.maxScore) {
|
||||
uni.showToast({
|
||||
title: `评分必须在${this.minScore}-${this.maxScore}分之间`,
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否有修改
|
||||
if (this.currentScore === this.originalScore && !this.note) {
|
||||
uni.showToast({
|
||||
title: '请修改分数或填写备注',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
uni.showLoading({
|
||||
title: '提交中...',
|
||||
mask: true
|
||||
})
|
||||
|
||||
// 🔥 关键改动:使用 dataAdapter 修改评分
|
||||
// Mock模式:调用 mock/score.js 的 modifyScore 函数
|
||||
// API模式:调用 api/score.js 的 modifyScore 函数(PUT /api/mini/score/modify)
|
||||
const response = await dataAdapter.getData('modifyScore', {
|
||||
athleteId: this.athleteInfo.athleteId,
|
||||
modifierId: this.modifierId,
|
||||
modifiedScore: this.currentScore,
|
||||
note: this.note
|
||||
})
|
||||
|
||||
uni.hideLoading()
|
||||
|
||||
// 调试信息
|
||||
if (config.debug) {
|
||||
console.log('修改评分成功:', {
|
||||
athleteId: this.athleteInfo.athleteId,
|
||||
originalScore: this.originalScore,
|
||||
modifiedScore: this.currentScore,
|
||||
note: this.note,
|
||||
response: response
|
||||
})
|
||||
}
|
||||
|
||||
// 显示成功提示
|
||||
uni.showToast({
|
||||
title: '修改成功',
|
||||
icon: 'success',
|
||||
duration: 1500
|
||||
})
|
||||
|
||||
// 返回上一页
|
||||
setTimeout(() => {
|
||||
uni.navigateBack()
|
||||
}, 1500)
|
||||
|
||||
} catch (error) {
|
||||
uni.hideLoading()
|
||||
console.error('修改评分失败:', error)
|
||||
|
||||
uni.showToast({
|
||||
title: error.message || '修改失败,请重试',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</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-left {
|
||||
position: absolute;
|
||||
left: 30rpx;
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.back-icon {
|
||||
font-size: 60rpx;
|
||||
color: #FFFFFF;
|
||||
font-weight: 300;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
/* 选手信息 */
|
||||
.player-info-section {
|
||||
margin: 30rpx;
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
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: 34rpx;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.total-score-label {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
.label-text {
|
||||
font-size: 26rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.score-value {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
|
||||
.player-details {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
.detail-item {
|
||||
font-size: 26rpx;
|
||||
color: #666666;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
/* 评委评分统计 */
|
||||
.judges-section {
|
||||
margin: 30rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.judges-scores {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.judge-score-item {
|
||||
font-size: 26rpx;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.judge-name {
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.judge-score {
|
||||
color: #333333;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 修改总分区域 */
|
||||
.modify-section {
|
||||
margin: 30rpx;
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 16rpx;
|
||||
padding: 40rpx 30rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.modify-header {
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.modify-label {
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.score-control {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.control-btn {
|
||||
width: 140rpx;
|
||||
height: 140rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #F5F5F5;
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
|
||||
.control-btn.decrease {
|
||||
background-color: #FFE5E5;
|
||||
}
|
||||
|
||||
.control-btn.increase {
|
||||
background-color: #E5F5F0;
|
||||
}
|
||||
|
||||
.btn-symbol {
|
||||
font-size: 48rpx;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.control-btn.decrease .btn-symbol {
|
||||
color: #FF4D6A;
|
||||
}
|
||||
|
||||
.control-btn.increase .btn-symbol {
|
||||
color: #1B7C5E;
|
||||
}
|
||||
|
||||
.btn-value {
|
||||
font-size: 24rpx;
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
|
||||
.control-btn.decrease .btn-value {
|
||||
color: #FF4D6A;
|
||||
}
|
||||
|
||||
.control-btn.increase .btn-value {
|
||||
color: #1B7C5E;
|
||||
}
|
||||
|
||||
.score-display {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.current-score {
|
||||
font-size: 60rpx;
|
||||
font-weight: 600;
|
||||
color: #1B7C5E;
|
||||
}
|
||||
|
||||
.no-modify-text {
|
||||
font-size: 24rpx;
|
||||
color: #FF4D6A;
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
|
||||
.modify-tip {
|
||||
font-size: 24rpx;
|
||||
color: #FF4D6A;
|
||||
line-height: 1.6;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* 备注 */
|
||||
.note-section {
|
||||
margin: 30rpx;
|
||||
}
|
||||
|
||||
.note-label {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.note-input-wrapper {
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.note-input {
|
||||
width: 100%;
|
||||
min-height: 120rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.note-input::placeholder {
|
||||
color: #CCCCCC;
|
||||
}
|
||||
|
||||
.optional-text {
|
||||
position: absolute;
|
||||
right: 30rpx;
|
||||
bottom: 30rpx;
|
||||
font-size: 24rpx;
|
||||
color: #FF4D6A;
|
||||
}
|
||||
|
||||
/* 修改按钮 */
|
||||
.modify-btn {
|
||||
margin: 30rpx;
|
||||
height: 90rpx;
|
||||
background: linear-gradient(135deg, #1B7C5E 0%, #2A9D7E 100%);
|
||||
border-radius: 16rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #FFFFFF;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 8rpx 20rpx rgba(27, 124, 94, 0.3);
|
||||
}
|
||||
|
||||
.modify-btn:active {
|
||||
opacity: 0.9;
|
||||
}
|
||||
</style>
|
||||
581
src/pages/score-detail/score-detail.vue
Normal file
581
src/pages/score-detail/score-detail.vue
Normal file
@@ -0,0 +1,581 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<!-- 自定义导航栏 -->
|
||||
<view class="nav-bar">
|
||||
<view class="nav-left" @click="goBack">
|
||||
<text class="back-icon">‹</text>
|
||||
</view>
|
||||
<view class="nav-title">评分详情</view>
|
||||
<view class="nav-right">
|
||||
<view class="icon-menu">···</view>
|
||||
<view class="icon-close">⊗</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 选手信息 -->
|
||||
<view class="player-info-section">
|
||||
<view class="player-name">{{ player.name }}</view>
|
||||
<view class="player-details">
|
||||
<view class="detail-item">身份证:{{ player.idCard }}</view>
|
||||
<view class="detail-item">队伍:{{ player.team }}</view>
|
||||
<view class="detail-item">编号:{{ player.number }}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 评分提示 -->
|
||||
<view class="score-tip">
|
||||
点击分数填写或拖动滑块打分(5-10分)
|
||||
</view>
|
||||
|
||||
<!-- 分数调整 -->
|
||||
<view class="score-control">
|
||||
<view class="control-btn decrease" @click="decreaseScore">
|
||||
<text class="btn-symbol">-</text>
|
||||
<!-- <text class="btn-value">-0.001</text> -->
|
||||
</view>
|
||||
|
||||
<view class="score-display">
|
||||
<text class="current-score">{{ currentScore.toFixed(3) }}</text>
|
||||
</view>
|
||||
|
||||
<view class="control-btn increase" @click="increaseScore">
|
||||
<text class="btn-symbol">+</text>
|
||||
<!-- <text class="btn-value">+0.001</text> -->
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- <view class="judge-tip">
|
||||
裁判评分:保留3位小数点,超过上限或下限时,按钮置灰
|
||||
</view> -->
|
||||
|
||||
<!-- 扣分项 -->
|
||||
<view class="deduction-section">
|
||||
<view class="deduction-header">
|
||||
<text class="deduction-label">扣分项:</text>
|
||||
<!-- <text class="deduction-hint">扣分项多选</text> -->
|
||||
</view>
|
||||
|
||||
<view class="deduction-list">
|
||||
<view
|
||||
v-for="(item, index) in deductions"
|
||||
:key="item.deductionId"
|
||||
class="deduction-item"
|
||||
@click="toggleDeduction(index)"
|
||||
>
|
||||
<view :class="['checkbox', item.checked ? 'checked' : '']">
|
||||
<text v-if="item.checked" class="check-icon">✓</text>
|
||||
</view>
|
||||
<text class="deduction-text">{{ item.deductionName }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 备注 -->
|
||||
<view class="note-section">
|
||||
<view class="note-label">
|
||||
<text>备注:</text>
|
||||
</view>
|
||||
<view class="note-input-wrapper">
|
||||
<textarea
|
||||
class="note-input"
|
||||
placeholder="请输入修改备注"
|
||||
v-model="note"
|
||||
maxlength="200"
|
||||
/>
|
||||
<!-- <text class="optional-text">可不填</text> -->
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 提交按钮 -->
|
||||
<button class="submit-btn" @click="handleSubmit">提交</button>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import dataAdapter from '@/utils/dataAdapter.js'
|
||||
import config from '@/config/env.config.js'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
player: {
|
||||
athleteId: '',
|
||||
name: '',
|
||||
idCard: '',
|
||||
team: '',
|
||||
number: ''
|
||||
},
|
||||
judgeId: '',
|
||||
projectId: '',
|
||||
currentScore: 8.000,
|
||||
note: '',
|
||||
minScore: 5.0,
|
||||
maxScore: 10.0,
|
||||
deductions: []
|
||||
}
|
||||
},
|
||||
|
||||
async onLoad() {
|
||||
// 获取全局数据
|
||||
const app = getApp()
|
||||
const globalData = app.globalData || {}
|
||||
|
||||
// 加载当前选手信息(从 score-list 页面传递)
|
||||
const currentAthlete = globalData.currentAthlete || {}
|
||||
this.player = {
|
||||
athleteId: currentAthlete.athleteId || '',
|
||||
name: currentAthlete.name || '选手姓名',
|
||||
idCard: currentAthlete.idCard || '',
|
||||
team: currentAthlete.team || '',
|
||||
number: currentAthlete.number || ''
|
||||
}
|
||||
|
||||
// 如果选手已评分,加载其原有评分
|
||||
if (currentAthlete.scored && currentAthlete.myScore) {
|
||||
this.currentScore = currentAthlete.myScore
|
||||
}
|
||||
|
||||
// 加载评委ID和项目ID
|
||||
this.judgeId = globalData.judgeId
|
||||
const projects = globalData.projects || []
|
||||
const currentIndex = globalData.currentProjectIndex || 0
|
||||
const currentProject = projects[currentIndex] || {}
|
||||
this.projectId = currentProject.projectId
|
||||
|
||||
// 调试信息
|
||||
if (config.debug) {
|
||||
console.log('评分详情页加载:', {
|
||||
athlete: this.player,
|
||||
judgeId: this.judgeId,
|
||||
projectId: this.projectId,
|
||||
initialScore: this.currentScore
|
||||
})
|
||||
}
|
||||
|
||||
// 加载扣分项列表
|
||||
await this.loadDeductions()
|
||||
},
|
||||
|
||||
methods: {
|
||||
async loadDeductions() {
|
||||
try {
|
||||
// 🔥 关键改动:使用 dataAdapter 获取扣分项列表
|
||||
// Mock模式:调用 mock/score.js 的 getDeductions 函数
|
||||
// API模式:调用 api/score.js 的 getDeductions 函数(GET /martial/deductionItem/list)
|
||||
const response = await dataAdapter.getData('getDeductions', {
|
||||
projectId: this.projectId
|
||||
})
|
||||
|
||||
// 为每个扣分项添加 checked 状态
|
||||
this.deductions = (response.data || []).map(item => ({
|
||||
...item,
|
||||
checked: false
|
||||
}))
|
||||
|
||||
// 调试信息
|
||||
if (config.debug) {
|
||||
console.log('扣分项加载成功:', this.deductions)
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('加载扣分项失败:', error)
|
||||
uni.showToast({
|
||||
title: '加载扣分项失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
goBack() {
|
||||
uni.navigateBack()
|
||||
},
|
||||
|
||||
decreaseScore() {
|
||||
if (this.currentScore > this.minScore) {
|
||||
this.currentScore = parseFloat((this.currentScore - 0.001).toFixed(3))
|
||||
}
|
||||
},
|
||||
|
||||
increaseScore() {
|
||||
if (this.currentScore < this.maxScore) {
|
||||
this.currentScore = parseFloat((this.currentScore + 0.001).toFixed(3))
|
||||
}
|
||||
},
|
||||
|
||||
toggleDeduction(index) {
|
||||
this.deductions[index].checked = !this.deductions[index].checked
|
||||
},
|
||||
|
||||
async handleSubmit() {
|
||||
// 验证评分范围
|
||||
if (this.currentScore < this.minScore || this.currentScore > this.maxScore) {
|
||||
uni.showToast({
|
||||
title: `评分必须在${this.minScore}-${this.maxScore}分之间`,
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 收集选中的扣分项
|
||||
const selectedDeductions = this.deductions
|
||||
.filter(item => item.checked)
|
||||
.map(item => ({
|
||||
deductionId: item.deductionId,
|
||||
deductionName: item.deductionName,
|
||||
deductionScore: item.deductionScore
|
||||
}))
|
||||
|
||||
try {
|
||||
uni.showLoading({
|
||||
title: '提交中...',
|
||||
mask: true
|
||||
})
|
||||
|
||||
// 🔥 关键改动:使用 dataAdapter 提交评分
|
||||
// Mock模式:调用 mock/score.js 的 submitScore 函数
|
||||
// API模式:调用 api/score.js 的 submitScore 函数(POST /martial/score/submit)
|
||||
const response = await dataAdapter.getData('submitScore', {
|
||||
athleteId: this.player.athleteId,
|
||||
judgeId: this.judgeId,
|
||||
score: this.currentScore,
|
||||
deductions: selectedDeductions,
|
||||
note: this.note
|
||||
})
|
||||
|
||||
uni.hideLoading()
|
||||
|
||||
// 调试信息
|
||||
if (config.debug) {
|
||||
console.log('评分提交成功:', {
|
||||
athleteId: this.player.athleteId,
|
||||
score: this.currentScore,
|
||||
deductions: selectedDeductions,
|
||||
response: response
|
||||
})
|
||||
}
|
||||
|
||||
// 显示成功提示
|
||||
uni.showToast({
|
||||
title: '提交成功',
|
||||
icon: 'success',
|
||||
duration: 1500
|
||||
})
|
||||
|
||||
// 返回上一页
|
||||
setTimeout(() => {
|
||||
uni.navigateBack()
|
||||
}, 1500)
|
||||
|
||||
} catch (error) {
|
||||
uni.hideLoading()
|
||||
console.error('提交评分失败:', error)
|
||||
|
||||
uni.showToast({
|
||||
title: error.message || '提交失败,请重试',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</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-left {
|
||||
position: absolute;
|
||||
left: 30rpx;
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.back-icon {
|
||||
font-size: 60rpx;
|
||||
color: #FFFFFF;
|
||||
font-weight: 300;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
/* 选手信息 */
|
||||
.player-info-section {
|
||||
margin: 30rpx;
|
||||
}
|
||||
|
||||
.player-name {
|
||||
font-size: 34rpx;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.player-details {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8rpx;
|
||||
}
|
||||
|
||||
.detail-item {
|
||||
font-size: 26rpx;
|
||||
color: #CD8B6F;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
/* 评分提示 */
|
||||
.score-tip {
|
||||
padding: 0 30rpx;
|
||||
font-size: 26rpx;
|
||||
color: #666666;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
/* 分数控制 */
|
||||
.score-control {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 60rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.control-btn {
|
||||
width: 140rpx;
|
||||
height: 140rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #F5F5F5;
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
|
||||
.control-btn.decrease {
|
||||
background-color: #FFE5E5;
|
||||
}
|
||||
|
||||
.control-btn.increase {
|
||||
background-color: #E5F5F0;
|
||||
}
|
||||
|
||||
.btn-symbol {
|
||||
font-size: 48rpx;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.control-btn.decrease .btn-symbol {
|
||||
color: #FF4D6A;
|
||||
}
|
||||
|
||||
.control-btn.increase .btn-symbol {
|
||||
color: #1B7C5E;
|
||||
}
|
||||
|
||||
.btn-value {
|
||||
font-size: 24rpx;
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
|
||||
.control-btn.decrease .btn-value {
|
||||
color: #FF4D6A;
|
||||
}
|
||||
|
||||
.control-btn.increase .btn-value {
|
||||
color: #1B7C5E;
|
||||
}
|
||||
|
||||
.score-display {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.current-score {
|
||||
font-size: 80rpx;
|
||||
font-weight: 600;
|
||||
color: #1B7C5E;
|
||||
}
|
||||
|
||||
.judge-tip {
|
||||
padding: 0 30rpx;
|
||||
font-size: 24rpx;
|
||||
color: #FF4D6A;
|
||||
text-align: center;
|
||||
line-height: 1.6;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
/* 扣分项 */
|
||||
.deduction-section {
|
||||
margin: 30rpx;
|
||||
}
|
||||
|
||||
.deduction-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.deduction-label {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.deduction-hint {
|
||||
font-size: 24rpx;
|
||||
color: #FF4D6A;
|
||||
}
|
||||
|
||||
.deduction-list {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.deduction-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 20rpx;
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 12rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
.checkbox {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
border: 2rpx solid #CCCCCC;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 16rpx;
|
||||
flex-shrink: 0;
|
||||
background-color: #F5F5F5;
|
||||
}
|
||||
|
||||
.checkbox.checked {
|
||||
background-color: #1B7C5E;
|
||||
border-color: #1B7C5E;
|
||||
}
|
||||
|
||||
.check-icon {
|
||||
color: #FFFFFF;
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.deduction-text {
|
||||
font-size: 26rpx;
|
||||
color: #333333;
|
||||
line-height: 1.4;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
/* 备注 */
|
||||
.note-section {
|
||||
margin: 30rpx;
|
||||
}
|
||||
|
||||
.note-label {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.note-input-wrapper {
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.note-input {
|
||||
width: 100%;
|
||||
min-height: 120rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.note-input::placeholder {
|
||||
color: #CCCCCC;
|
||||
}
|
||||
|
||||
.optional-text {
|
||||
position: absolute;
|
||||
right: 30rpx;
|
||||
bottom: 30rpx;
|
||||
font-size: 24rpx;
|
||||
color: #FF4D6A;
|
||||
}
|
||||
|
||||
/* 提交按钮 */
|
||||
.submit-btn {
|
||||
margin: 30rpx;
|
||||
height: 90rpx;
|
||||
background: linear-gradient(135deg, #1B7C5E 0%, #2A9D7E 100%);
|
||||
border-radius: 16rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #FFFFFF;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 8rpx 20rpx rgba(27, 124, 94, 0.3);
|
||||
}
|
||||
|
||||
.submit-btn:active {
|
||||
opacity: 0.9;
|
||||
}
|
||||
</style>
|
||||
547
src/pages/score-list-multi/score-list-multi.vue
Normal file
547
src/pages/score-list-multi/score-list-multi.vue
Normal file
@@ -0,0 +1,547 @@
|
||||
<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">
|
||||
<!-- 场地切换 - 横向滚动 -->
|
||||
<scroll-view class="venue-scroll" scroll-x="true" show-scrollbar="false">
|
||||
<view class="venue-tabs">
|
||||
<view
|
||||
v-for="venue in venues"
|
||||
:key="venue.venueId"
|
||||
:class="['venue-tab', currentVenue === venue.venueId ? 'active' : '']"
|
||||
@click="switchVenue(venue.venueId)"
|
||||
>
|
||||
{{ venue.venueName }}
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<view class="venue-tip">
|
||||
<!-- <text class="tip-bold">裁判长可看见所有场地和项目</text> -->
|
||||
<!-- <text class="tip-normal">(场地和项目可动态全部),可以点击切换</text> -->
|
||||
</view>
|
||||
|
||||
<!-- 项目选择 - 横向滚动 -->
|
||||
<scroll-view class="project-scroll" scroll-x="true" show-scrollbar="false">
|
||||
<view class="project-list">
|
||||
<view
|
||||
v-for="(project, index) in projects"
|
||||
:key="project.projectId"
|
||||
:class="['project-btn', currentProject === project.projectId ? 'active' : '']"
|
||||
@click="switchProject(project.projectId)"
|
||||
>
|
||||
{{ project.projectName }}
|
||||
</view>
|
||||
</view>
|
||||
</scroll-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="action-area" v-if="player.totalScore">
|
||||
<text class="total-score">总分:{{ player.totalScore }}</text>
|
||||
<view class="chief-actions">
|
||||
<!-- <text class="chief-hint">裁判长功能:修改评分、修改按钮需等总分出来才出现</text> -->
|
||||
<button class="modify-btn" @click="goToModify(player)">修改</button>
|
||||
</view>
|
||||
</view>
|
||||
</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: {
|
||||
id: '',
|
||||
name: '',
|
||||
time: ''
|
||||
},
|
||||
competitionId: '',
|
||||
currentVenue: '',
|
||||
currentProject: '',
|
||||
venues: [],
|
||||
projects: [],
|
||||
players: [],
|
||||
scoredCount: 0,
|
||||
totalCount: 0
|
||||
}
|
||||
},
|
||||
|
||||
async onLoad() {
|
||||
// 获取全局数据
|
||||
const app = getApp()
|
||||
const globalData = app.globalData || {}
|
||||
|
||||
// 加载比赛信息
|
||||
this.matchInfo = {
|
||||
id: globalData.matchId,
|
||||
name: globalData.matchName || '比赛名称',
|
||||
time: globalData.matchTime || '比赛时间'
|
||||
}
|
||||
|
||||
// 注意:裁判长没有固定场地和项目,需要查看所有
|
||||
this.competitionId = globalData.matchId
|
||||
|
||||
// 调试信息
|
||||
if (config.debug) {
|
||||
console.log('裁判长列表页加载:', {
|
||||
userRole: globalData.userRole,
|
||||
competitionId: this.competitionId
|
||||
})
|
||||
}
|
||||
|
||||
// 加载场地和项目列表
|
||||
await this.loadVenuesAndProjects()
|
||||
},
|
||||
|
||||
methods: {
|
||||
async loadVenuesAndProjects() {
|
||||
try {
|
||||
uni.showLoading({
|
||||
title: '加载中...',
|
||||
mask: true
|
||||
})
|
||||
|
||||
// 🔥 关键改动:使用 dataAdapter 获取场地列表
|
||||
// Mock模式:调用 mock/athlete.js 的 getVenues 函数
|
||||
// API模式:调用 api/athlete.js 的 getVenues 函数(GET /martial/venue/list)
|
||||
const venuesRes = await dataAdapter.getData('getVenues', {
|
||||
competitionId: this.competitionId
|
||||
})
|
||||
|
||||
// 🔥 关键改动:使用 dataAdapter 获取项目列表
|
||||
// Mock模式:调用 mock/athlete.js 的 getProjects 函数
|
||||
// API模式:调用 api/athlete.js 的 getProjects 函数(GET /martial/project/list)
|
||||
const projectsRes = await dataAdapter.getData('getProjects', {
|
||||
competitionId: this.competitionId
|
||||
})
|
||||
|
||||
this.venues = venuesRes.data || []
|
||||
this.projects = projectsRes.data || []
|
||||
|
||||
// 默认选中第一个场地和项目
|
||||
if (this.venues.length > 0) {
|
||||
this.currentVenue = this.venues[0].venueId
|
||||
}
|
||||
if (this.projects.length > 0) {
|
||||
this.currentProject = this.projects[0].projectId
|
||||
}
|
||||
|
||||
uni.hideLoading()
|
||||
|
||||
// 调试信息
|
||||
if (config.debug) {
|
||||
console.log('场地和项目加载成功:', {
|
||||
venues: this.venues.length,
|
||||
projects: this.projects.length,
|
||||
currentVenue: this.currentVenue,
|
||||
currentProject: this.currentProject
|
||||
})
|
||||
}
|
||||
|
||||
// 加载选手列表
|
||||
if (this.currentVenue && this.currentProject) {
|
||||
await this.loadPlayers()
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
uni.hideLoading()
|
||||
console.error('加载场地和项目失败:', error)
|
||||
uni.showToast({
|
||||
title: error.message || '加载失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
async loadPlayers() {
|
||||
try {
|
||||
uni.showLoading({
|
||||
title: '加载中...',
|
||||
mask: true
|
||||
})
|
||||
|
||||
// 🔥 关键改动:使用 dataAdapter 获取选手列表(裁判长视图)
|
||||
// Mock模式:调用 mock/athlete.js 的 getAthletesForAdmin 函数
|
||||
// API模式:调用 api/athlete.js 的 getAthletesForAdmin 函数(GET /api/mini/athletes/admin)
|
||||
const response = await dataAdapter.getData('getAthletesForAdmin', {
|
||||
competitionId: this.competitionId,
|
||||
venueId: this.currentVenue,
|
||||
projectId: this.currentProject
|
||||
})
|
||||
|
||||
uni.hideLoading()
|
||||
|
||||
// 保存选手列表
|
||||
this.players = response.data || []
|
||||
|
||||
// 计算评分统计(裁判长视图:统计有总分的选手)
|
||||
this.totalCount = this.players.length
|
||||
this.scoredCount = this.players.filter(p => p.totalScore).length
|
||||
|
||||
// 调试信息
|
||||
if (config.debug) {
|
||||
console.log('选手列表加载成功:', {
|
||||
venueId: this.currentVenue,
|
||||
projectId: this.currentProject,
|
||||
total: this.totalCount,
|
||||
scored: this.scoredCount,
|
||||
players: this.players
|
||||
})
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
uni.hideLoading()
|
||||
console.error('加载选手列表失败:', error)
|
||||
uni.showToast({
|
||||
title: error.message || '加载失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
async switchVenue(venueId) {
|
||||
if (this.currentVenue === venueId) return
|
||||
|
||||
this.currentVenue = venueId
|
||||
|
||||
// 调试信息
|
||||
if (config.debug) {
|
||||
console.log('切换场地:', venueId)
|
||||
}
|
||||
|
||||
// 重新加载选手列表
|
||||
await this.loadPlayers()
|
||||
},
|
||||
|
||||
async switchProject(projectId) {
|
||||
if (this.currentProject === projectId) return
|
||||
|
||||
this.currentProject = projectId
|
||||
|
||||
// 调试信息
|
||||
if (config.debug) {
|
||||
console.log('切换项目:', projectId)
|
||||
}
|
||||
|
||||
// 重新加载选手列表
|
||||
await this.loadPlayers()
|
||||
},
|
||||
|
||||
goToModify(player) {
|
||||
// 保存当前选手信息到全局数据
|
||||
const app = getApp()
|
||||
app.globalData.currentAthlete = player
|
||||
|
||||
uni.navigateTo({
|
||||
url: '/pages/modify-score/modify-score'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</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-scroll {
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.venue-tabs {
|
||||
display: inline-flex;
|
||||
gap: 30rpx;
|
||||
padding-bottom: 20rpx;
|
||||
border-bottom: 4rpx solid #E0E0E0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.venue-tab {
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
color: #666666;
|
||||
padding: 0 20rpx;
|
||||
position: relative;
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.venue-tab.active {
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.venue-tab.active::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -24rpx;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 4rpx;
|
||||
background-color: #1B7C5E;
|
||||
}
|
||||
|
||||
.venue-tip {
|
||||
font-size: 24rpx;
|
||||
line-height: 1.6;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.tip-bold {
|
||||
color: #FF4D6A;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.tip-normal {
|
||||
color: #FF4D6A;
|
||||
}
|
||||
|
||||
/* 项目滚动容器 */
|
||||
.project-scroll {
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.project-list {
|
||||
display: inline-flex;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.project-btn {
|
||||
padding: 20rpx 30rpx;
|
||||
background-color: #FFFFFF;
|
||||
border: 2rpx solid #CCCCCC;
|
||||
border-radius: 8rpx;
|
||||
font-size: 26rpx;
|
||||
color: #666666;
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.project-btn.active {
|
||||
background-color: #1B7C5E;
|
||||
color: #FFFFFF;
|
||||
border-color: #1B7C5E;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 评分统计 */
|
||||
.score-stats {
|
||||
padding: 20rpx 30rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.stats-text {
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.stats-number {
|
||||
color: #1B7C5E;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* 选手列表 */
|
||||
.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: flex-start;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.player-name {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.action-area {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
gap: 10rpx;
|
||||
}
|
||||
|
||||
.total-score {
|
||||
font-size: 26rpx;
|
||||
color: #333333;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.chief-actions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
gap: 10rpx;
|
||||
}
|
||||
|
||||
.chief-hint {
|
||||
font-size: 22rpx;
|
||||
color: #FF4D6A;
|
||||
text-align: right;
|
||||
line-height: 1.5;
|
||||
max-width: 400rpx;
|
||||
}
|
||||
|
||||
.modify-btn {
|
||||
padding: 12rpx 40rpx;
|
||||
background: linear-gradient(135deg, #1B7C5E 0%, #2A9D7E 100%);
|
||||
border-radius: 8rpx;
|
||||
font-size: 28rpx;
|
||||
color: #FFFFFF;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.modify-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>
|
||||
441
src/pages/score-list/score-list.vue
Normal file
441
src/pages/score-list/score-list.vue
Normal file
@@ -0,0 +1,441 @@
|
||||
<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>
|
||||
Reference in New Issue
Block a user