- 将同一单位的选手合并为一个队伍行 - 多选手队伍可展开查看具体选手 - 队伍状态根据所有选手状态计算(已签到/未签到/部分签到/部分异常) - 上移/下移操作移动整个队伍 - 异常标记:单人队伍在主行标记,多人队伍需展开后标记单个选手 - 修复语法错误(转义字符和字符串引号) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -86,13 +86,44 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-table :data="group.items" border stripe size="small">
|
||||
<el-table :data="groupItemsByTeam(group.items)" border stripe size="small" row-key="id">
|
||||
<!-- 展开列 -->
|
||||
<el-table-column type="expand" width="30">
|
||||
<template #default="{ row }">
|
||||
<div v-if="row.players.length > 1" class="player-expand-list">
|
||||
<div v-for="player in row.players" :key="player.id" class="player-row">
|
||||
<span class="player-name">{{ player.playerName }}</span>
|
||||
<el-tag :type="player.status === '已签到' ? 'success' : player.status === '异常' ? 'danger' : 'info'" size="small">
|
||||
{{ player.status || '未签到' }}
|
||||
</el-tag>
|
||||
<el-button
|
||||
v-if="(player.status || '未签到') === '未签到'"
|
||||
link
|
||||
size="small"
|
||||
@click="markPlayerAsException(group, player)"
|
||||
:disabled="isScheduleCompleted"
|
||||
style="color: #f56c6c;"
|
||||
>
|
||||
异常
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="player-expand-list">
|
||||
<span style="color: #909399;">单人队伍</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="序号" type="index" width="60" align="center"></el-table-column>
|
||||
<el-table-column prop="schoolUnit" label="学校/单位" min-width="200"></el-table-column>
|
||||
<el-table-column prop="status" label="状态" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.status === '已签到' ? 'success' : scope.row.status === '异常' ? 'danger' : 'info'" size="small">
|
||||
{{ scope.row.status || '未签到' }}
|
||||
<el-table-column prop="schoolUnit" label="学校/单位" min-width="150"></el-table-column>
|
||||
<el-table-column label="选手" min-width="120">
|
||||
<template #default="{ row }">
|
||||
{{ row.players.map(p => p.playerName).join('、') }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" width="100" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="getTeamStatusType(row)" size="small">
|
||||
{{ getTeamStatus(row) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -101,7 +132,7 @@
|
||||
<el-button
|
||||
link
|
||||
size="small"
|
||||
@click="handleMoveUp(group, scope.$index)"
|
||||
@click="handleTeamMoveUp(group, scope.$index)"
|
||||
:disabled="scope.$index === 0 || isScheduleCompleted"
|
||||
title="上移"
|
||||
class="move-btn"
|
||||
@@ -111,18 +142,18 @@
|
||||
<el-button
|
||||
link
|
||||
size="small"
|
||||
@click="handleMoveDown(group, scope.$index)"
|
||||
:disabled="scope.$index === group.items.length - 1 || isScheduleCompleted"
|
||||
@click="handleTeamMoveDown(group, scope.$index)"
|
||||
:disabled="scope.$index === groupItemsByTeam(group.items).length - 1 || isScheduleCompleted"
|
||||
title="下移"
|
||||
class="move-btn"
|
||||
>
|
||||
<img src="/img/图标 4@3x.png" class="move-icon" alt="下移" />
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="(scope.row.status || '未签到') === '未签到'"
|
||||
v-if="scope.row.players.length === 1 && (scope.row.players[0].status || '未签到') === '未签到'"
|
||||
link
|
||||
size="small"
|
||||
@click="markAsException(group, scope.$index)"
|
||||
@click="markPlayerAsException(group, scope.row.players[0])"
|
||||
:disabled="isScheduleCompleted"
|
||||
style="color: #f56c6c;"
|
||||
>
|
||||
@@ -372,6 +403,146 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 将选手按学校/单位分组为队伍
|
||||
groupItemsByTeam(items) {
|
||||
if (!items || items.length === 0) return []
|
||||
const teamMap = new Map()
|
||||
items.forEach(item => {
|
||||
const key = item.schoolUnit
|
||||
if (!teamMap.has(key)) {
|
||||
teamMap.set(key, {
|
||||
id: `team_${item.id}`,
|
||||
schoolUnit: key,
|
||||
players: [],
|
||||
playerIds: []
|
||||
})
|
||||
}
|
||||
teamMap.get(key).players.push(item)
|
||||
teamMap.get(key).playerIds.push(item.id)
|
||||
})
|
||||
return Array.from(teamMap.values())
|
||||
},
|
||||
|
||||
// 获取队伍状态
|
||||
getTeamStatus(team) {
|
||||
if (!team || !team.players) return '未签到'
|
||||
const statuses = team.players.map(p => p.status || '未签到')
|
||||
if (statuses.every(s => s === '已签到')) return '已签到'
|
||||
if (statuses.every(s => s === '未签到')) return '未签到'
|
||||
if (statuses.some(s => s === '异常')) return '部分异常'
|
||||
return '部分签到'
|
||||
},
|
||||
|
||||
// 获取队伍状态类型
|
||||
getTeamStatusType(team) {
|
||||
const status = this.getTeamStatus(team)
|
||||
switch(status) {
|
||||
case '已签到': return 'success'
|
||||
case '部分异常': return 'danger'
|
||||
case '部分签到': return 'warning'
|
||||
default: return 'info'
|
||||
}
|
||||
},
|
||||
|
||||
// 队伍上移
|
||||
handleTeamMoveUp(group, teamIndex) {
|
||||
const teams = this.groupItemsByTeam(group.items)
|
||||
if (teamIndex === 0 || this.isScheduleCompleted) return
|
||||
|
||||
const currentTeam = teams[teamIndex]
|
||||
const prevTeam = teams[teamIndex - 1]
|
||||
|
||||
// 找到两个队伍在原数组中的位置范围
|
||||
const currentPlayerIds = currentTeam.playerIds
|
||||
const prevPlayerIds = prevTeam.playerIds
|
||||
|
||||
// 重新排序:将当前队伍的所有选手移到前一个队伍之前
|
||||
const newItems = []
|
||||
let addedCurrent = false
|
||||
|
||||
for (const item of group.items) {
|
||||
if (prevPlayerIds.includes(item.id) && !addedCurrent) {
|
||||
// 先添加当前队伍的所有选手
|
||||
for (const cItem of group.items) {
|
||||
if (currentPlayerIds.includes(cItem.id)) {
|
||||
newItems.push(cItem)
|
||||
}
|
||||
}
|
||||
addedCurrent = true
|
||||
}
|
||||
if (!currentPlayerIds.includes(item.id)) {
|
||||
newItems.push(item)
|
||||
}
|
||||
}
|
||||
|
||||
group.items = newItems
|
||||
this.$message.success('上移成功')
|
||||
},
|
||||
|
||||
// 队伍下移
|
||||
handleTeamMoveDown(group, teamIndex) {
|
||||
const teams = this.groupItemsByTeam(group.items)
|
||||
if (teamIndex === teams.length - 1 || this.isScheduleCompleted) return
|
||||
|
||||
const currentTeam = teams[teamIndex]
|
||||
const nextTeam = teams[teamIndex + 1]
|
||||
|
||||
const currentPlayerIds = currentTeam.playerIds
|
||||
const nextPlayerIds = nextTeam.playerIds
|
||||
|
||||
// 重新排序:将当前队伍的所有选手移到下一个队伍之后
|
||||
const newItems = []
|
||||
let addedCurrent = false
|
||||
|
||||
for (const item of group.items) {
|
||||
if (!currentPlayerIds.includes(item.id)) {
|
||||
newItems.push(item)
|
||||
}
|
||||
if (nextPlayerIds.includes(item.id)) {
|
||||
// 检查是否是下一个队伍的最后一个选手
|
||||
const isLastOfNext = item.id === nextPlayerIds[nextPlayerIds.length - 1]
|
||||
if (isLastOfNext && !addedCurrent) {
|
||||
// 在下一个队伍最后一个选手之后添加当前队伍
|
||||
for (const cItem of group.items) {
|
||||
if (currentPlayerIds.includes(cItem.id)) {
|
||||
newItems.push(cItem)
|
||||
}
|
||||
}
|
||||
addedCurrent = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
group.items = newItems
|
||||
this.$message.success('下移成功')
|
||||
},
|
||||
|
||||
// 标记单个选手为异常
|
||||
markPlayerAsException(group, player) {
|
||||
if (this.isScheduleCompleted) {
|
||||
this.$message.warning('编排已完成,无法标记异常')
|
||||
return
|
||||
}
|
||||
|
||||
// 在 group.items 中找到该选手并修改状态
|
||||
const item = group.items.find(i => i.id === player.id)
|
||||
if (item) {
|
||||
item.status = '异常'
|
||||
|
||||
// 添加到异常列表
|
||||
this.exceptionList.push({
|
||||
groupId: group.id,
|
||||
groupTitle: group.title,
|
||||
participantId: player.id,
|
||||
schoolUnit: player.schoolUnit,
|
||||
playerName: player.playerName,
|
||||
status: '异常'
|
||||
})
|
||||
|
||||
this.$message.success(`已将 ${player.playerName} 标记为异常`)
|
||||
}
|
||||
},
|
||||
|
||||
goBack() {
|
||||
this.$router.go(-1)
|
||||
},
|
||||
@@ -505,6 +676,7 @@ export default {
|
||||
items: (group.participants || []).map(p => ({
|
||||
id: p.id,
|
||||
schoolUnit: p.schoolUnit,
|
||||
playerName: p.playerName,
|
||||
status: p.status || '未签到',
|
||||
sortOrder: p.sortOrder
|
||||
}))
|
||||
@@ -1014,4 +1186,28 @@ export default {
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
// 展开行样式
|
||||
.player-expand-list {
|
||||
padding: 10px 20px 10px 60px;
|
||||
background: #fafafa;
|
||||
|
||||
.player-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 15px;
|
||||
padding: 8px 0;
|
||||
border-bottom: 1px dashed #eee;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.player-name {
|
||||
min-width: 80px;
|
||||
color: #606266;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user