diff --git a/src/pages/score-list-multi/score-list-multi.vue b/src/pages/score-list-multi/score-list-multi.vue
index 66ea4e2..152a579 100644
--- a/src/pages/score-list-multi/score-list-multi.vue
+++ b/src/pages/score-list-multi/score-list-multi.vue
@@ -4,57 +4,45 @@
评分系统
-
- ⊗
+ ···
+ ◎
{{ matchInfo.name }}
- 比赛时间:{{ matchInfo.time }}
+ 比赛时间:{{ formatDateTime(matchInfo.time) }}
-
-
-
-
-
-
- {{ venue.venueName }}
-
-
-
-
-
-
-
+
+
+
+
-
-
-
+
+
+
{{ project.projectName }}
-
+
- 已评分:
- {{ scoredCount }}/{{ totalCount }}
+ 已评分:
+ {{ scoredCount }}/{{ totalCount }}
@@ -65,25 +53,42 @@
v-for="player in players"
:key="player.athleteId"
>
-
@@ -96,38 +101,47 @@ export default {
data() {
return {
matchInfo: {
- id: '',
name: '',
time: ''
},
- competitionId: '',
- currentVenue: '',
- currentProject: '',
- venues: [],
+ venueInfo: {
+ id: '',
+ name: ''
+ },
+ projectInfo: {
+ id: '',
+ name: ''
+ },
+ judgeId: '',
projects: [],
+ currentProjectIndex: 0,
players: [],
scoredCount: 0,
- totalCount: 0
+ totalCount: 0,
+ pagination: {
+ current: 1,
+ size: 10,
+ total: 0
+ },
+ isLoading: false,
+ hasMore: true,
+ isFirstLoad: true
}
},
async onLoad() {
- // 获取全局数据
const app = getApp()
const globalData = app.globalData || {}
// 检查登录状态
if (!globalData.judgeId || !globalData.token) {
- console.warn('用户未登录,跳转到登录页')
uni.showToast({
title: '请先登录',
icon: 'none',
duration: 1500
})
setTimeout(() => {
- uni.reLaunch({
- url: '/pages/login/login'
- })
+ uni.reLaunch({ url: '/pages/login/login' })
}, 1500)
return
}
@@ -143,171 +157,197 @@ export default {
// 加载比赛信息
this.matchInfo = {
- id: globalData.matchId,
name: globalData.matchName || '比赛名称',
- time: globalData.matchTime || '比赛时间'
+ time: globalData.matchTime || ''
}
- // 注意:裁判长没有固定场地和项目,需要查看所有
- this.competitionId = globalData.matchId
+ // 从 globalData 获取场地信息(与普通裁判相同)
+ this.venueInfo = {
+ id: globalData.venueId,
+ name: globalData.venueName || '场地'
+ }
+
+ // 从 globalData 获取项目列表
+ this.projects = globalData.projects || []
+ this.currentProjectIndex = globalData.currentProjectIndex || 0
+ this.updateCurrentProject()
+ this.judgeId = globalData.judgeId
// 调试信息
if (config.debug) {
console.log('裁判长列表页加载:', {
userRole: globalData.userRole,
- competitionId: this.competitionId
+ judgeId: this.judgeId,
+ venueId: this.venueInfo.id,
+ projectId: this.projectInfo.id
})
}
- // 加载场地和项目列表
- await this.loadVenuesAndProjects()
+ await this.loadPlayers(true)
+ this.isFirstLoad = false
+ },
+
+ async onShow() {
+ // 从修改评分页返回时刷新数据
+ if (!this.isFirstLoad) {
+ if (config.debug) {
+ console.log('页面显示,刷新数据')
+ }
+ await this.loadPlayers(true)
+ }
+ },
+
+ async onPullDownRefresh() {
+ await this.loadPlayers(true)
+ uni.stopPullDownRefresh()
+ },
+
+ async onReachBottom() {
+ if (this.hasMore && !this.isLoading) {
+ await this.loadMore()
+ }
},
methods: {
- async loadVenuesAndProjects() {
+ formatDateTime(dateTimeStr) {
+ if (!dateTimeStr) return ''
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()
- }
-
+ const date = new Date(dateTimeStr)
+ if (isNaN(date.getTime())) return dateTimeStr
+ const year = date.getFullYear()
+ const month = date.getMonth() + 1
+ const day = date.getDate()
+ const hours = date.getHours()
+ const minutes = date.getMinutes()
+ const paddedMinutes = minutes < 10 ? '0' + minutes : minutes
+ return year + '年' + month + '月' + day + '日 ' + hours + ':' + paddedMinutes
} catch (error) {
- uni.hideLoading()
- console.error('加载场地和项目失败:', error)
- uni.showToast({
- title: error.message || '加载失败',
- icon: 'none'
- })
+ return dateTimeStr
}
},
- async loadPlayers() {
- try {
- uni.showLoading({
- title: '加载中...',
- mask: true
- })
+ formatScore(score) {
+ // 处理 null、undefined、-1 等无效值
+ if (score === null || score === undefined || score === -1 || score === '-1') {
+ return '--'
+ }
+ // 如果是字符串类型的数字,直接返回
+ if (typeof score === 'string' && !isNaN(parseFloat(score))) {
+ return score
+ }
+ // 如果是数字类型,保留3位小数
+ if (typeof score === 'number') {
+ return score.toFixed(3)
+ }
+ return score
+ },
- // 🔥 关键改动:使用 dataAdapter 获取选手列表(裁判长视图)
- // Mock模式:调用 mock/athlete.js 的 getAthletesForAdmin 函数
- // API模式:调用 api/athlete.js 的 getAthletesForAdmin 函数(GET /mini/score/athletes)
+ async handleRefresh() {
+ if (this.isLoading) return
+ uni.showToast({ title: '刷新中...', icon: 'loading', duration: 1000 })
+ await this.loadPlayers(true)
+ uni.showToast({ title: '刷新成功', icon: 'success', duration: 1000 })
+ },
+
+ async loadPlayers(refresh = false) {
+ if (this.isLoading) return
+ try {
+ this.isLoading = true
+ if (refresh) {
+ this.pagination.current = 1
+ this.hasMore = true
+ }
+ if (refresh && this.isFirstLoad) {
+ uni.showLoading({ title: '加载中...', mask: true })
+ }
const app = getApp()
const globalData = app.globalData || {}
- const response = await dataAdapter.getData('getAthletesForAdmin', {
- judgeId: globalData.judgeId,
- competitionId: this.competitionId,
- venueId: this.currentVenue,
- projectId: this.currentProject
+ const params = {
+ matchCode: globalData.matchCode,
+ judgeId: this.judgeId,
+ venueId: this.venueInfo.id,
+ projectId: this.projectInfo.id,
+ current: this.pagination.current,
+ size: this.pagination.size
+ }
+ Object.keys(params).forEach(key => {
+ if (params[key] === undefined || params[key] === null || params[key] === '') {
+ delete params[key]
+ }
})
- 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,
+ console.log('请求选手列表参数:', params)
+ }
+
+ // 裁判长使用 getAthletesForAdmin 接口
+ const response = await dataAdapter.getData('getAthletesForAdmin', params)
+
+ if (config.debug) {
+ console.log('选手列表响应:', response)
+ }
+
+ if (refresh && this.isFirstLoad) {
+ uni.hideLoading()
+ }
+ const responseData = response.data || {}
+ const records = responseData.records || response.data || []
+ const total = responseData.total || records.length
+ this.pagination.total = total
+ this.totalCount = total
+ if (refresh) {
+ this.players = records
+ } else {
+ this.players = [...this.players, ...records]
+ }
+ // 裁判长视图:统计有总分的选手
+ this.scoredCount = this.players.filter(p => p.totalScore).length
+ this.hasMore = this.players.length < total
+
+ if (config.debug) {
+ console.log('选手列表处理结果:', {
+ total: total,
+ loaded: this.players.length,
scored: this.scoredCount,
players: this.players
})
}
-
} catch (error) {
uni.hideLoading()
console.error('加载选手列表失败:', error)
- uni.showToast({
- title: error.message || '加载失败',
- icon: 'none'
- })
+ uni.showToast({ title: error.message || '加载失败', icon: 'none' })
+ } finally {
+ this.isLoading = false
}
},
- 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()
+ async loadMore() {
+ if (!this.hasMore || this.isLoading) return
+ this.pagination.current++
+ await this.loadPlayers(false)
},
goToModify(player) {
- // 保存当前选手信息到全局数据
const app = getApp()
app.globalData.currentAthlete = player
+ uni.navigateTo({ url: '/pages/modify-score/modify-score' })
+ },
- uni.navigateTo({
- url: '/pages/modify-score/modify-score'
- })
+ updateCurrentProject() {
+ const currentProject = this.projects[this.currentProjectIndex] || {}
+ this.projectInfo = {
+ id: currentProject.projectId,
+ name: currentProject.projectName || '项目'
+ }
+ },
+
+ async switchProject(index) {
+ if (index === this.currentProjectIndex) return
+ this.currentProjectIndex = index
+ const app = getApp()
+ app.globalData.currentProjectIndex = index
+ this.updateCurrentProject()
+ await this.loadPlayers(true)
}
}
}
@@ -320,7 +360,7 @@ export default {
padding-bottom: 40rpx;
}
-/* 导航栏 */
+/* ==================== 导航栏 ==================== */
.nav-bar {
height: 90rpx;
background: linear-gradient(135deg, #1B7C5E 0%, #2A9D7E 100%);
@@ -335,7 +375,6 @@ export default {
font-size: 36rpx;
font-weight: 600;
color: #FFFFFF;
- letter-spacing: 2rpx;
}
.nav-right {
@@ -343,24 +382,15 @@ export default {
right: 30rpx;
display: flex;
align-items: center;
- gap: 30rpx;
+ gap: 20rpx;
}
-.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;
+.nav-dots, .nav-circle {
font-size: 32rpx;
color: #FFFFFF;
- font-weight: bold;
}
-/* 比赛信息 */
+/* ==================== 比赛信息 ==================== */
.match-info {
padding: 30rpx;
background-color: #F5F5F5;
@@ -369,132 +399,94 @@ export default {
.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;
+ color: #1B7C5E;
+ line-height: 1.5;
+ margin-bottom: 8rpx;
}
.match-time {
font-size: 28rpx;
- color: #666666;
+ color: #333333;
}
-/* 场地和项目区域 */
-.venue-section {
+/* ==================== 场地卡片 ==================== */
+.venue-card {
+ margin: 0 30rpx 20rpx;
background-color: #FFFFFF;
- margin: 20rpx 30rpx;
border-radius: 16rpx;
padding: 30rpx;
- box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
+ box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
}
-/* 场地滚动容器 */
-.venue-scroll {
- width: 100%;
- white-space: nowrap;
- margin-bottom: 20rpx;
+.venue-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding-bottom: 24rpx;
+ border-bottom: 4rpx solid #1B7C5E;
+ margin-bottom: 24rpx;
}
-.venue-tabs {
- display: inline-flex;
- gap: 30rpx;
- padding-bottom: 20rpx;
- border-bottom: 4rpx solid #E0E0E0;
- position: relative;
-}
-
-.venue-tab {
+.venue-name {
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;
+.refresh-link {
+ font-size: 26rpx;
+ color: #4A90D9;
}
-.venue-tip {
- font-size: 24rpx;
- line-height: 1.6;
- margin-bottom: 20rpx;
+.project-row {
+ display: flex;
+ flex-direction: column;
}
-.tip-bold {
- color: #FF4D6A;
- font-weight: 500;
+.project-grid {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 16rpx;
}
-.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;
+.project-chip {
+ padding: 20rpx 12rpx;
+ border: 2rpx solid #1B7C5E;
border-radius: 8rpx;
font-size: 26rpx;
- color: #666666;
+ color: #1B7C5E;
+ background-color: #FFFFFF;
+ text-align: center;
+ overflow: hidden;
+ text-overflow: ellipsis;
white-space: nowrap;
- flex-shrink: 0;
}
-.project-btn.active {
+.project-chip.active {
background-color: #1B7C5E;
color: #FFFFFF;
- border-color: #1B7C5E;
- font-weight: 500;
}
-/* 评分统计 */
+/* ==================== 评分统计 ==================== */
.score-stats {
padding: 20rpx 30rpx;
+ display: flex;
+ align-items: center;
+}
+
+.stats-label {
font-size: 28rpx;
color: #333333;
}
-.stats-text {
- color: #666666;
-}
-
-.stats-number {
+.stats-value {
+ font-size: 32rpx;
color: #1B7C5E;
font-weight: 600;
+ margin-left: 8rpx;
}
-/* 选手列表 */
+/* ==================== 选手卡片 ==================== */
.player-list {
padding: 0 30rpx;
}
@@ -502,12 +494,12 @@ export default {
.player-card {
background-color: #FFFFFF;
border-radius: 16rpx;
- padding: 30rpx;
+ padding: 24rpx;
margin-bottom: 20rpx;
- box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
+ box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
}
-.player-header {
+.card-header {
display: flex;
align-items: flex-start;
justify-content: space-between;
@@ -520,32 +512,31 @@ export default {
color: #333333;
}
+/* ==================== 操作区域 ==================== */
.action-area {
display: flex;
- flex-direction: column;
- align-items: flex-end;
- gap: 10rpx;
+ align-items: center;
+ gap: 16rpx;
}
-.total-score {
- font-size: 26rpx;
- color: #333333;
- font-weight: 600;
-}
-
-.chief-actions {
+.score-tag {
display: flex;
- flex-direction: column;
- align-items: flex-end;
- gap: 10rpx;
+ align-items: center;
+ padding: 12rpx 20rpx;
+ background-color: #F5F5F5;
+ border-radius: 8rpx;
+ border: 2rpx solid #E5E5E5;
}
-.chief-hint {
- font-size: 22rpx;
- color: #FF4D6A;
- text-align: right;
- line-height: 1.5;
- max-width: 400rpx;
+.tag-label {
+ font-size: 24rpx;
+ color: #666666;
+}
+
+.tag-value {
+ font-size: 28rpx;
+ color: #333333;
+ font-weight: 500;
}
.modify-btn {
@@ -555,21 +546,50 @@ export default {
font-size: 28rpx;
color: #FFFFFF;
font-weight: 500;
+ border: none;
+ line-height: 1.4;
}
-.modify-btn:active {
- opacity: 0.9;
-}
-
-.player-info {
+/* ==================== 选手详情 ==================== */
+.player-details {
display: flex;
flex-direction: column;
- gap: 12rpx;
+ gap: 8rpx;
}
-.info-item {
+.detail-row {
+ line-height: 1.6;
+}
+
+.detail-text {
font-size: 26rpx;
color: #666666;
- line-height: 1.5;
+}
+
+/* ==================== 加载状态 ==================== */
+.loading-status {
+ padding: 30rpx 0;
+ text-align: center;
+}
+
+.loading-text {
+ font-size: 26rpx;
+ color: #1B7C5E;
+}
+
+.no-more-text {
+ font-size: 26rpx;
+ color: #999999;
+}
+
+/* ==================== 空状态 ==================== */
+.empty-state {
+ padding: 100rpx 0;
+ text-align: center;
+}
+
+.empty-text {
+ font-size: 28rpx;
+ color: #999999;
}
diff --git a/src/pages/score-list/score-list.vue b/src/pages/score-list/score-list.vue
index 40d4506..d26e887 100644
--- a/src/pages/score-list/score-list.vue
+++ b/src/pages/score-list/score-list.vue
@@ -25,19 +25,17 @@
-
-
-
- {{ project.projectName }}
-
+
+
+ {{ project.projectName }}
-
+
@@ -443,23 +441,23 @@ export default {
flex-direction: column;
}
-.project-scroll {
- white-space: nowrap;
-}
-
-.project-chips {
- display: inline-flex;
- gap: 20rpx;
+.project-grid {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 16rpx;
}
.project-chip {
- display: inline-block;
- padding: 16rpx 32rpx;
+ padding: 20rpx 12rpx;
border: 2rpx solid #1B7C5E;
border-radius: 8rpx;
- font-size: 28rpx;
+ font-size: 26rpx;
color: #1B7C5E;
background-color: #FFFFFF;
+ text-align: center;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
}
.project-chip.active {