diff --git a/src/api/athlete.js b/src/api/athlete.js index 56f3ca3..0b5d125 100644 --- a/src/api/athlete.js +++ b/src/api/athlete.js @@ -7,8 +7,6 @@ import request from '@/utils/request.js' export default { /** * 获取选手列表 - * @param {Object} params 查询参数 { current, size, competitionId, name } - * @returns {Promise} */ getAthleteList(params = {}) { return request.get('/martial/athlete/list', { @@ -20,8 +18,6 @@ export default { /** * 获取选手详情 - * @param {String|Number} id 选手ID - * @returns {Promise} */ getAthleteDetail(id) { return request.get('/martial/athlete/detail', { id }) @@ -29,8 +25,6 @@ export default { /** * 新增或修改选手 - * @param {Object} data 选手数据 - * @returns {Promise} */ submitAthlete(data) { return request.post('/martial/athlete/submit', data) @@ -38,12 +32,44 @@ export default { /** * 删除选手 - * @param {String|Array} ids 选手ID或ID数组 - * @returns {Promise} */ removeAthlete(ids) { return request.post('/martial/athlete/remove', { ids: Array.isArray(ids) ? ids.join(',') : ids }) + }, + + // ========== 集体/团队相关 API ========== + + /** + * 获取集体列表 + */ + getTeamList(params = {}) { + return request.get('/martial/team/list', { + current: params.current || 1, + size: params.size || 100, + ...params + }) + }, + + /** + * 获取集体详情 + */ + getTeamDetail(id) { + return request.get('/martial/team/detail', { id }) + }, + + /** + * 保存集体 + */ + saveTeam(data) { + return request.post('/martial/team/submit', data) + }, + + /** + * 删除集体 + */ + removeTeam(id) { + return request.post('/martial/team/remove', null, { params: { id } }) } } diff --git a/src/pages/event-register/event-register.vue b/src/pages/event-register/event-register.vue index 454cdd9..8e37571 100644 --- a/src/pages/event-register/event-register.vue +++ b/src/pages/event-register/event-register.vue @@ -4,7 +4,7 @@ - 选择选手信息 + {{ isTeamProject ? '选择集体' : '选择选手信息' }} @@ -18,37 +18,73 @@ - + - 已选:{{ selectedCount }} + + + + + 下一步 @@ -81,11 +117,11 @@ (注意是否用此号码接收信息) - 参赛选手: + {{ isTeamProject ? '参赛集体:' : '参赛选手:' }} - {{ eventInfo.participants || '未选择选手' }} + {{ eventInfo.participants || (isTeamProject ? '未选择集体' : '未选择选手') }} - + 查看证件 @@ -94,8 +130,8 @@ - 人数: - {{ selectedCount }} + {{ isTeamProject ? '集体数:' : '人数:' }} + {{ isTeamProject ? selectedTeamCount : selectedCount }} 合计: @@ -132,14 +168,25 @@ {{ eventInfo.contact }} - 参赛选手:{{ selectedPlayers.length }}人 - - - {{ item.name }} - 身份证:{{ item.idCard }} - 编号:{{ item.number }} + + @@ -179,6 +226,7 @@ export default { currentStep: 1, eventId: '', selectedProjects: [], + isTeamProject: false, eventInfo: { title: '', location: '', @@ -188,7 +236,9 @@ export default { participants: '' }, playerList: [], + teamList: [], selectedPlayers: [], + selectedTeams: [], showPlayerModal: false, totalPrice: 0, registrationId: '' @@ -198,11 +248,8 @@ export default { selectedCount() { return this.playerList.filter(item => item.selected).length }, - participantsText() { - return this.playerList - .filter(item => item.selected) - .map(item => item.name) - .join('、') + selectedTeamCount() { + return this.teamList.filter(item => item.selected).length } }, onLoad(options) { @@ -213,47 +260,44 @@ export default { if (options.projects) { try { - // 尝试解码(可能被双重编码) let projectsStr = decodeURIComponent(options.projects) - - // 如果还包含 %,说明被双重编码了,再解码一次 if (projectsStr.includes('%')) { projectsStr = decodeURIComponent(projectsStr) } - this.selectedProjects = JSON.parse(projectsStr) + + // Check if any project is team type (type === 2) + this.isTeamProject = this.selectedProjects.some(p => p.type === 2 || p.type === '2') } catch (err) { console.error('解析项目数据失败:', err) } } - // 加载选手列表 - this.loadPlayerList() - }, - onShow() { - // 从新增/编辑页面返回时重新加载列表 - if (this.currentStep === 1) { + // Load list based on project type + if (this.isTeamProject) { + this.loadTeamList() + } else { this.loadPlayerList() } }, + onShow() { + if (this.currentStep === 1) { + if (this.isTeamProject) { + this.loadTeamList() + } else { + this.loadPlayerList() + } + } + }, methods: { - /** - * 加载赛事详情 - */ async loadEventDetail(id) { try { const res = await competitionAPI.getCompetitionDetail(id) - - // 尝试多个可能的时间字段名 const startTime = res.startTime || res.competitionStartTime || res.beginTime || res.startDate const endTime = res.endTime || res.competitionEndTime || res.finishTime || res.endDate - - // 如果没有时间字段,尝试使用其他字段 let matchTime = this.formatTimeRange(startTime, endTime) if (!matchTime && res.matchTime) { matchTime = res.matchTime - } else if (!matchTime && res.competitionTime) { - matchTime = res.competitionTime } else if (!matchTime) { matchTime = '待定' } @@ -270,7 +314,6 @@ export default { } } catch (err) { console.error('加载赛事详情失败:', err) - // 设置默认值,防止页面显示空白 this.eventInfo = { title: '未命名赛事', location: '待定', @@ -282,111 +325,105 @@ export default { } }, - /** - * 加载选手列表 - */ async loadPlayerList() { try { - // 获取当前用户信息 const userInfo = getUserInfo() if (!userInfo || !userInfo.userId) { - uni.showToast({ - title: '请先登录', - icon: 'none' - }) + uni.showToast({ title: '请先登录', icon: 'none' }) return } - // 只查询当前用户创建的选手 const res = await athleteAPI.getAthleteList({ current: 1, size: 100, createUser: userInfo.userId }) - let list = [] - if (res.records) { - list = res.records - } else if (Array.isArray(res)) { - list = res - } - - // 数据映射 - 尝试多个可能的字段名 + let list = res.records || (Array.isArray(res) ? res : []) this.playerList = list.map(item => ({ id: item.id, - // 尝试多个可能的姓名字段 - name: item.name || item.athleteName || item.playerName || item.realName || item.userName || '未命名', - // 尝试多个可能的身份证字段 - idCard: item.idCard || item.idCardNumber || item.idCardNo || item.identityCard || '', + name: item.name || item.athleteName || item.playerName || '未命名', + idCard: item.idCard || item.idCardNumber || '', selected: false })) } catch (err) { console.error('加载选手列表失败:', err) - uni.showToast({ - title: '加载选手列表失败', - icon: 'none' - }) } }, - /** - * 格式化时间范围 - */ + async loadTeamList() { + try { + const userInfo = getUserInfo() + if (!userInfo || !userInfo.userId) return + + const res = await athleteAPI.getTeamList({ + current: 1, + size: 100 + }) + + let list = res.records || (Array.isArray(res) ? res : []) + this.teamList = list.map(item => ({ + id: item.id, + name: item.teamName || item.name, + memberCount: item.memberCount || 0, + selected: false + })) + } catch (err) { + console.error('加载集体列表失败:', err) + this.teamList = [] + } + }, + formatTimeRange(startTime, endTime) { if (!startTime || !endTime) return '' - const formatDate = (dateStr) => { if (!dateStr) return '' const date = new Date(dateStr) - const year = date.getFullYear() - const month = String(date.getMonth() + 1).padStart(2, '0') - const day = String(date.getDate()).padStart(2, '0') - return `${year}.${month}.${day}` + return `${date.getFullYear()}.${String(date.getMonth() + 1).padStart(2, '0')}.${String(date.getDate()).padStart(2, '0')}` } - return `${formatDate(startTime)}-${formatDate(endTime)}` }, - /** - * 计算总价 - */ calculateTotalPrice() { - const count = this.selectedCount - - if (!this.selectedProjects || this.selectedProjects.length === 0) { - return 0 - } - - // 计算所有项目的总价(将字符串转换为数字) - const pricePerProject = this.selectedProjects.reduce((sum, p) => { - const price = parseFloat(p.price || 0) - return sum + price - }, 0) - - const total = count * pricePerProject - - return total.toFixed(2) + const count = this.isTeamProject ? this.selectedTeamCount : this.selectedCount + if (!this.selectedProjects || this.selectedProjects.length === 0) return 0 + const pricePerProject = this.selectedProjects.reduce((sum, p) => sum + parseFloat(p.price || 0), 0) + return (count * pricePerProject).toFixed(2) }, togglePlayer(item) { const index = this.playerList.findIndex(p => p.id === item.id) if (index !== -1) { - const newValue = !this.playerList[index].selected - this.$set(this.playerList[index], 'selected', newValue) + this.$set(this.playerList[index], 'selected', !this.playerList[index].selected) } }, + + toggleTeam(item) { + const index = this.teamList.findIndex(t => t.id === item.id) + if (index !== -1) { + this.$set(this.teamList[index], 'selected', !this.teamList[index].selected) + } + }, + goToAddPlayer() { - // 传递赛事ID和项目ID到新增选手页面 const projectIds = this.selectedProjects.map(p => p.id).join(',') uni.navigateTo({ url: `/pages/add-player/add-player?competitionId=${this.eventId}&projectIds=${projectIds}` - }); + }) }, + + goToAddTeam() { + uni.navigateTo({ + url: '/pages/add-team/add-team' + }) + }, + handleEdit(item) { uni.navigateTo({ url: '/pages/edit-player/edit-player?id=' + item.id - }); + }) }, + async handleDelete(item) { try { const confirmRes = await new Promise((resolve) => { @@ -399,167 +436,146 @@ export default { if (confirmRes.confirm) { await athleteAPI.removeAthlete(item.id) - - const index = this.playerList.findIndex(p => p.id === item.id); - if (index > -1) { - this.playerList.splice(index, 1); - } - - uni.showToast({ - title: '删除成功', - icon: 'success' - }) + const index = this.playerList.findIndex(p => p.id === item.id) + if (index > -1) this.playerList.splice(index, 1) + uni.showToast({ title: '删除成功', icon: 'success' }) } } catch (err) { console.error('删除选手失败:', err) - uni.showToast({ - title: '删除失败', - icon: 'none' - }) + uni.showToast({ title: '删除失败', icon: 'none' }) } }, + + async handleDeleteTeam(item) { + try { + const confirmRes = await new Promise((resolve) => { + uni.showModal({ + title: '删除集体', + content: '确定要删除该集体吗?', + success: (res) => resolve(res) + }) + }) + + if (confirmRes.confirm) { + await athleteAPI.removeTeam(item.id) + const index = this.teamList.findIndex(t => t.id === item.id) + if (index > -1) this.teamList.splice(index, 1) + uni.showToast({ title: '删除成功', icon: 'success' }) + } + } catch (err) { + console.error('删除集体失败:', err) + uni.showToast({ title: '删除失败', icon: 'none' }) + } + }, + goToStep2() { - const selected = this.playerList.filter(item => item.selected) - - if (selected.length === 0) { - uni.showToast({ - title: '请至少选择一名选手', - icon: 'none' - }) - return + if (this.isTeamProject) { + const selected = this.teamList.filter(item => item.selected) + if (selected.length === 0) { + uni.showToast({ title: '请至少选择一个集体', icon: 'none' }) + return + } + this.$set(this.eventInfo, 'participants', selected.map(t => t.name).join('、')) + this.selectedTeams = selected + } else { + const selected = this.playerList.filter(item => item.selected) + if (selected.length === 0) { + uni.showToast({ title: '请至少选择一名选手', icon: 'none' }) + return + } + this.$set(this.eventInfo, 'participants', selected.map(p => p.name).join('、')) } - - // 更新参赛选手信息 - const participantsText = selected.map(p => p.name).join('、') - - // 使用 $set 确保响应式更新 - this.$set(this.eventInfo, 'participants', participantsText) + this.totalPrice = this.calculateTotalPrice() - - // 延迟切换步骤,确保数据更新完成 - this.$nextTick(() => { - this.currentStep = 2 - }) + this.$nextTick(() => { this.currentStep = 2 }) }, + async goToStep3() { try { - // 获取选中的选手 - const selected = this.playerList.filter(item => item.selected) - - // 检查必填字段 if (!this.eventId) { - uni.showToast({ - title: '赛事ID缺失', - icon: 'none' - }) + uni.showToast({ title: '赛事ID缺失', icon: 'none' }) return } if (!this.selectedProjects || this.selectedProjects.length === 0) { - uni.showToast({ - title: '请选择报名项目', - icon: 'none' - }) + uni.showToast({ title: '请选择报名项目', icon: 'none' }) return } - if (selected.length === 0) { - uni.showToast({ - title: '请选择参赛选手', - icon: 'none' - }) - return - } - - // 生成订单号:格式 BMyyyyMMddHHmmss + 随机4位数 const now = new Date() - const year = now.getFullYear() - const month = String(now.getMonth() + 1).padStart(2, '0') - const day = String(now.getDate()).padStart(2, '0') - const hours = String(now.getHours()).padStart(2, '0') - const minutes = String(now.getMinutes()).padStart(2, '0') - const seconds = String(now.getSeconds()).padStart(2, '0') - const random = String(Math.floor(Math.random() * 10000)).padStart(4, '0') - const orderNo = `BM${year}${month}${day}${hours}${minutes}${seconds}${random}` + const orderNo = `BM${now.getFullYear()}${String(now.getMonth() + 1).padStart(2, '0')}${String(now.getDate()).padStart(2, '0')}${String(now.getHours()).padStart(2, '0')}${String(now.getMinutes()).padStart(2, '0')}${String(now.getSeconds()).padStart(2, '0')}${String(Math.floor(Math.random() * 10000)).padStart(4, '0')}` - // 构建提交数据 - 确保ID都是数字类型 - const submitData = { - orderNo: orderNo, - competitionId: String(this.eventId), - projectIds: this.selectedProjects.map(p => String(p.id)), - athleteIds: selected.map(p => String(p.id)), - contactPhone: this.eventInfo.contact || '', - totalAmount: parseFloat(this.totalPrice) || 0 + let submitData + if (this.isTeamProject) { + const selected = this.teamList.filter(item => item.selected) + if (selected.length === 0) { + uni.showToast({ title: '请选择参赛集体', icon: 'none' }) + return + } + submitData = { + orderNo: orderNo, + competitionId: String(this.eventId), + projectIds: this.selectedProjects.map(p => String(p.id)), + teamIds: selected.map(t => String(t.id)), + athleteIds: [], + contactPhone: this.eventInfo.contact || '', + totalAmount: parseFloat(this.totalPrice) || 0 + } + } else { + const selected = this.playerList.filter(item => item.selected) + if (selected.length === 0) { + uni.showToast({ title: '请选择参赛选手', icon: 'none' }) + return + } + submitData = { + orderNo: orderNo, + competitionId: String(this.eventId), + projectIds: this.selectedProjects.map(p => String(p.id)), + athleteIds: selected.map(p => String(p.id)), + contactPhone: this.eventInfo.contact || '', + totalAmount: parseFloat(this.totalPrice) || 0 + } } - console.log('=== 提交报名数据 ===') - console.log('订单号:', submitData.orderNo) - console.log('完整提交数据:', submitData) - console.log('赛事ID:', submitData.competitionId, typeof submitData.competitionId) - console.log('项目IDs:', submitData.projectIds) - console.log('选手IDs:', submitData.athleteIds) - console.log('联系电话:', submitData.contactPhone) - console.log('总金额:', submitData.totalAmount, typeof submitData.totalAmount) - - // 提交报名订单 + console.log('提交报名数据:', submitData) const res = await registrationAPI.submitRegistration(submitData) + this.registrationId = res.id || res.registrationId || orderNo - console.log('=== 报名响应数据 ===') - console.log('完整响应:', res) - console.log('响应数据:', res.data) - - // 保存报名ID - 尝试多个可能的字段 - this.registrationId = res.id || res.registrationId || res.data?.id || res.data?.registrationId || orderNo - - console.log('报名ID:', this.registrationId) - - // 更新选中的选手列表(包含编号) - this.selectedPlayers = selected.map((item, index) => { - // 生成编号:使用报名ID或订单号 + 选手索引 - const playerNumber = item.playerNo || item.number || `${this.registrationId}-${String(index + 1).padStart(6, '0')}` - - return { + if (this.isTeamProject) { + this.selectedTeams = this.teamList.filter(item => item.selected).map(item => ({ + name: item.name, + memberCount: item.memberCount + })) + } else { + const selected = this.playerList.filter(item => item.selected) + this.selectedPlayers = selected.map((item, index) => ({ name: item.name, idCard: item.idCard, - number: playerNumber - } - }) + number: `${this.registrationId}-${String(index + 1).padStart(6, '0')}` + })) + } - this.currentStep = 3; - - uni.showToast({ - title: '报名成功', - icon: 'success' - }) + this.currentStep = 3 + uni.showToast({ title: '报名成功', icon: 'success' }) } catch (err) { console.error('提交报名失败:', err) - uni.showToast({ - title: '报名失败,请重试', - icon: 'none' - }) + uni.showToast({ title: '报名失败,请重试', icon: 'none' }) } }, + showPlayers() { - // 更新选中的选手列表 this.selectedPlayers = this.playerList .filter(item => item.selected) - .map(item => ({ - name: item.name, - idCard: item.idCard, - number: '' - })) - - this.showPlayerModal = true; + .map(item => ({ name: item.name, idCard: item.idCard, number: '' })) + this.showPlayerModal = true }, + handleClose() { - uni.navigateBack({ - delta: 3 - }); + uni.navigateBack({ delta: 3 }) } } -}; +} - + +.empty-state { + padding: 100rpx 0; + text-align: center; +} + +.empty-text { + font-size: 28rpx; + color: #999999; +}