From cfc2aeab044dca7073d2f5c62ba8de44b4261ab3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A9=AC=E6=A2=93=E5=BD=AD?= Date: Mon, 13 Apr 2026 02:07:55 +0800 Subject: [PATCH] =?UTF-8?q?=E9=A1=B5=E9=9D=A2bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../match/manage/Steps/Step3ProjectConfig.vue | 17 ++++- src/views/match/manage/index.vue | 19 +++++- src/views/team/leader/index.vue | 9 ++- src/views/team/trainer/index.vue | 19 ++++-- src/views/user/registration/index.vue | 65 +++++-------------- 5 files changed, 69 insertions(+), 60 deletions(-) diff --git a/src/views/match/manage/Steps/Step3ProjectConfig.vue b/src/views/match/manage/Steps/Step3ProjectConfig.vue index e48faf8..4eec526 100644 --- a/src/views/match/manage/Steps/Step3ProjectConfig.vue +++ b/src/views/match/manage/Steps/Step3ProjectConfig.vue @@ -28,7 +28,7 @@ start-placeholder="开始日期" end-placeholder="结束日期" :model-value="[group.birthDateStart, group.birthDateEnd]" @update:modelValue="(v) => { group.birthDateStart = v?.[0]; group.birthDateEnd = v?.[1]; }" :disabled="readonly" /> - {{ group.birthDateStart }} ~ {{ group.birthDateEnd }} + {{ formatGroupDate(group) }} @@ -150,6 +150,7 @@ import { ref, watch, nextTick, computed } from 'vue'; import ProTable from '/@/components/ProTable/index.vue'; import { projectPageGet, projectDetailGet } from '/@/api/match/project'; import { ElMessage } from 'element-plus'; +import { formatDate } from '/@/utils/formatTime'; const props = defineProps({ modelValue: { type: Object, required: true }, @@ -168,6 +169,20 @@ const localFormData = ref({ registrationLimit: { individualProjectLimit: 1, teamProjectLimit: 1 }, }); const genderList = ref(['全部', '男', '女']) + +// 格式化组别的年龄段(出生日期范围) +const formatGroupDate = (item) => { + const start = item?.birthDateStart; + const end = item?.birthDateEnd; + if (!start && !end) return ''; + const fmt = (v) => { + if (!v) return ''; + try { return formatDate(new Date(v), 'YYYY-mm-dd'); } catch { return String(v); } + }; + if (start && end) return `${fmt(start)} ~ ${fmt(end)}`; + return fmt(start || end); +}; + const addProject = () => { timeProjects.value = []; isShowDialog.value = true; diff --git a/src/views/match/manage/index.vue b/src/views/match/manage/index.vue index c9f5c25..f3eac90 100644 --- a/src/views/match/manage/index.vue +++ b/src/views/match/manage/index.vue @@ -201,9 +201,22 @@ const columns = reactive([ { prop: 'action', label: '操作', align: 'center', width: 200, fixed: 'right', isShow: auths(['event:edit', 'event:delete']) }, ]); -const exportableColumns = computed(() => - columns.filter((item) => item?.prop && item?.label && !['action', 'index'].includes(item.prop)) -); +const exportableColumns = computed(() => [ + { prop: 'eventName', label: '赛事名称' }, + { prop: 'eventType', label: '赛事类型' }, + { prop: 'chargeMode', label: '收费模式' }, + { prop: 'merchantName', label: '收款商户' }, + { prop: 'registrationType', label: '报名方式' }, + { prop: 'eventStatus', label: '赛事状态' }, + { prop: 'registrationTime', label: '报名起止时间' }, + { prop: 'materialUploadEndTime', label: '上传素材截至时间' }, + { prop: 'matchTime', label: '比赛起止时间' }, + { prop: 'detailAddress', label: '赛事地址' }, + { prop: 'hostUnit', label: '主办单位' }, + { prop: 'organizerUnit', label: '承办单位' }, + { prop: 'coOrganizerUnit', label: '协办单位' }, + { prop: 'sponsorUnit', label: '赞助单位' } +]); // 定义变量内容 const menuDialogRef = ref(); diff --git a/src/views/team/leader/index.vue b/src/views/team/leader/index.vue index 8c343c1..d8d8f59 100644 --- a/src/views/team/leader/index.vue +++ b/src/views/team/leader/index.vue @@ -79,7 +79,7 @@ import { appuserLeaderPageGet, appuserLeaderSavePost, appuserMemberDeletePost } const formRef = ref(); const initParam = ref({ refresh: true, - personType: 3 + PersonType: 3 }); const getDefaultFormData = () => ({ @@ -109,7 +109,12 @@ const formRules = ref({ { required: true, message: '请选择性别', trigger: 'change' } ], mobile: [ - { required: true, message: '请输入联系电话', trigger: 'blur' } + { required: true, message: '请输入联系电话', trigger: 'blur' }, + { + pattern: /^1[3-9]\d{9}$/, + message: '请输入有效的手机号码', + trigger: ['blur', 'change'] + } ], }); diff --git a/src/views/team/trainer/index.vue b/src/views/team/trainer/index.vue index b002d0c..66cb3aa 100644 --- a/src/views/team/trainer/index.vue +++ b/src/views/team/trainer/index.vue @@ -91,13 +91,13 @@ import { ElMessage, ElForm } from 'element-plus'; import SysMenuApi from '/@/api/SysMenuApi'; import { auths } from '/@/utils/authFunction'; import ProTable from '/@/components/ProTable/index.vue'; -import { appuserCoachPageGet ,appuserLeaderSavePost , appuserMemberDeletePost} from '/@/api/match/appuser'; +import { appuserCoachPageGet, appuserCoachSavePost, appuserMemberDeletePost } from '/@/api/match/appuser'; // 定义表单引用类型 const formRef = ref(); const initParam = ref({ refresh: true, - personType:2 + PersonType: 2 }); const formData = ref({ name: '', @@ -119,7 +119,12 @@ const formRules = ref({ { required: true, message: '请选择性别', trigger: 'change' } ], mobile: [ - { required: true, message: '请输入联系电话', trigger: 'blur' } + { required: true, message: '请输入联系电话', trigger: 'blur' }, + { + pattern: /^1[3-9]\d{9}$/, + message: '请输入有效的手机号码', + trigger: ['blur', 'change'] + } ], // idCardImageUrl: [ // { required: true, message: '请上传身份证', trigger: 'change' } @@ -142,8 +147,8 @@ const columns = ref([ { label: '女', value: 1 }, ], }, - { prop: 'age', label: '年龄' , search: { el: 'input' }}, - { prop: 'mobile', label: '联系电话' , search: { el: 'input' }}, + { prop: 'age', label: '年龄' }, + { prop: 'mobile', label: '联系电话', search: { el: 'input' } }, // { prop: 'idCardImageUrl', label: '身份证' }, { prop: 'action', label: '操作', align: 'center', fixed: 'right' }, @@ -201,9 +206,9 @@ const onSubmit = () => { try { let res; if (formData.value.id) { - res = await appuserLeaderSavePost(formData.value); + res = await appuserCoachSavePost(formData.value); } else { - res = await appuserLeaderSavePost(formData.value); + res = await appuserCoachSavePost(formData.value); } if (res.succeeded) { diff --git a/src/views/user/registration/index.vue b/src/views/user/registration/index.vue index d9d65e1..8d0db8a 100644 --- a/src/views/user/registration/index.vue +++ b/src/views/user/registration/index.vue @@ -103,7 +103,7 @@
名称:{{ project.name }}
-
类型:{{ project.parentProjectTypeName ?? project.projectTypeName ?? '' }}{{ project.parentProjectTypeName || project.projectTypeName ? '-' + project.name : '' }}
+
类型:{{ project.parentProjectTypeName ?? project.projectTypeName ?? '' }}
完成人数:{{ project.completionCount ?? 0 }}
@@ -261,14 +261,7 @@ style="margin-bottom: 12px;" /> - - + 下一步 @@ -442,7 +435,6 @@ import { usereventregistrationMemberValidatePost, usereventregistrationRegistrationLimitCheckPost, usereventregistrationGroupTeamLimitGet, - usereventregistrationProjectCompletionCheckPost, usereventregistrationOrderStatusGet, } from '/@/api/match/usereventregistration'; import { teamPageGet, teamDetailGet } from '/@/api/match/unitUser'; @@ -807,8 +799,19 @@ const isFreePreview = computed(() => { const toggleGroupSelection = (id) => { const idx = selectedGroupIds.value.indexOf(id); if (idx >= 0) { + // 取消选中 selectedGroupIds.value.splice(idx, 1); } else { + // 选中新组别:先找出这个组别属于哪个项目,然后取消该项目的其他组别 + const clickedGroup = allGroups.value.find(g => g.id === id); + if (clickedGroup && clickedGroup.projectId) { + // 移除同一项目下的其他组别 + selectedGroupIds.value = selectedGroupIds.value.filter(selectedId => { + const selectedGroup = allGroups.value.find(g => g.id === selectedId); + return selectedGroup?.projectId !== clickedGroup.projectId; + }); + } + // 添加新选中的组别 selectedGroupIds.value.push(id); } }; @@ -845,7 +848,6 @@ const selectedMemberIds = ref([]); const memberValidationMap = ref({}); // { groupId_memberId: { isValid: boolean, ageValid: boolean, genderValid: boolean, message: string } } const groupTeamLimitMap = ref({}); // { groupId: { maxTeams: number, currentTeams: number } } const memberRegistrationLimitMap = ref({}); // { memberId: { isLimited: boolean, message: string } } -const projectCompletionCheckResult = ref(null); // 项目完成人数检查结果 const registrationLimitCheckResult = ref(null); // 报名限制检查结果 // Step2: 团队相关 @@ -906,7 +908,6 @@ const clearRegisterState = () => { memberValidationMap.value = {}; groupTeamLimitMap.value = {}; memberRegistrationLimitMap.value = {}; - projectCompletionCheckResult.value = null; registrationLimitCheckResult.value = null; previewLoading.value = false; previewData.value = null; @@ -1102,10 +1103,7 @@ const hasAnyRegistrationLimit = () => { return registrationLimitCheckResult.value?.hasLimit ?? false; }; -// 检查是否有项目完成人数错误 -const hasProjectCompletionCountError = () => { - return projectCompletionCheckResult.value?.hasError ?? false; -}; + // 判断组别是否已达到队伍数量限制 const isGroupAtTeamLimit = (groupId) => { @@ -1159,8 +1157,7 @@ const assignMemberToActiveGroup = async (member) => { } groupMemberMap.value[gId].push({ ...member, teamId: member.teamId }); - // 实时检查项目完成人数和报名限制 - await checkProjectCompletion(); + // 实时检查报名限制 await checkRegistrationLimit(); }; @@ -1278,25 +1275,7 @@ const fetchGroupTeamLimit = async () => { } }; -// 检查项目完成人数 -const checkProjectCompletion = async () => { - if (!currentEventId.value) return; - const groupMembers = selectedGroupIds.value.map((gId) => ({ - groupId: gId, - memberIds: (groupMemberMap.value[gId] ?? []).map((m) => m.userId ?? m.id), - })); - try { - const { succeeded, data } = await usereventregistrationProjectCompletionCheckPost({ - eventId: currentEventId.value, - groupMembers - }); - if (succeeded) { - projectCompletionCheckResult.value = data; - } - } catch { - console.error('检查项目完成人数失败'); - } -}; + // 检查报名限制 const checkRegistrationLimit = async () => { @@ -1337,17 +1316,9 @@ const handleStep1Next = async () => { const handleStep2Next = async () => { if (!currentEventId.value) return; - // 先检查项目完成人数和报名限制 - await checkProjectCompletion(); + // 先检查报名限制 await checkRegistrationLimit(); - // 检查是否有项目完成人数错误 - if (hasProjectCompletionCountError()) { - const errors = projectCompletionCheckResult.value?.errors ?? []; - ElMessage.error(errors[0]?.errorMessage ?? '项目完成人数有错误,请检查'); - return; - } - // 检查是否有报名限制 if (hasAnyRegistrationLimit()) { const details = registrationLimitCheckResult.value?.limitDetails ?? [];