-
-
-
- {{ member.name }}
-
- 队长
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ member.name }}
+
+ 队长
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+ {{ member.name }}
+
+ 队长
+
+
+
+
+
+
+
+
@@ -807,22 +867,41 @@ const formatRefundRules = (rules) => {
// 格式化项目标题
const formatItemTitle = (item) => {
- const projectType = item.projectTypeName || '';
- // 使用报名项目人数作为完成人数显示
- const completionCount = item.personCount ?? 0;
- const projectName = item.projectName || '';
- const groupName = item.groupName || '';
- const dateRange = formatGroupDate(item);
- const genderReq = formatGenderRequirement(item.genderRequirement);
-
- let title = `(${projectType}/${completionCount}) ${projectName}-${groupName}`;
- if (dateRange) {
- title += `/${dateRange}`;
- }
- if (genderReq) {
- title += `/${genderReq}`;
- }
- return title;
+ const projectType = item.projectTypeName || '';
+ // 使用报名项目人数作为完成人数显示
+ const completionCount = item.personCount ?? 0;
+ const projectName = item.projectName || '';
+ const groupName = item.groupName || '';
+ const dateRange = formatGroupDate(item);
+ const genderReq = formatGenderRequirement(item.genderRequirement);
+
+ let title = `(${projectType}/${completionCount}) ${projectName}-${groupName}`;
+ if (dateRange) {
+ title += `/${dateRange}`;
+ }
+ if (genderReq) {
+ title += `/${genderReq}`;
+ }
+ return title;
+};
+
+// 格式化取消报名预览中的项目组别标题
+const formatCancelPreviewItemTitle = (project, group) => {
+ const projectType = group.projectTypeName || '';
+ const completionCount = group.personCount ?? 0;
+ const projectName = project.projectName || '';
+ const groupName = group.groupName || '';
+ const dateRange = formatGroupDate(group);
+ const genderReq = formatGenderRequirement(group.genderRequirement);
+
+ let title = `(${projectType}/${completionCount}) ${projectName}-${groupName}`;
+ if (dateRange) {
+ title += `/${dateRange}`;
+ }
+ if (genderReq) {
+ title += `/${genderReq}`;
+ }
+ return title;
};
const onOpenMenu = async (row) => {
@@ -1153,8 +1232,8 @@ const mockMembers3 = ref([
]);
// 新的响应式变量
- const selectedMembers = ref([]);
- const teamRemoved = ref(false);
+ const selectedMembers = ref([]); // 选择的队员ID
+ const removedTeams = ref(new Set()); // 存储被移除的团队(格式:registrationItemId_teamIndex
const cancelAll = ref(false);
const hasValidationError = ref(false);
const hasLimitError = ref(false);
@@ -1169,12 +1248,107 @@ const mockMembers3 = ref([
const totalRefundAmount = computed(() => {
// 免费项目退款金额为0
- if (isFreeProject.value) {
+ if (isFreeProject.value || cancelPreviewData.value?.chargeMode === 0) {
return 0;
}
- // 使用后端返回的可退款金额
- return cancelPreviewData.value?.refundableAmount ?? 0;
+ // 如果取消全部,直接返回可退款金额
+ if (cancelAll.value) {
+ return cancelPreviewData.value?.refundableAmount ?? 0;
+ }
+
+ // 根据收费模式动态计算退款金额
+ const chargeMode = cancelPreviewData.value?.chargeMode;
+ const refundableAmount = cancelPreviewData.value?.refundableAmount ?? 0;
+ const actualPaidAmount = cancelPreviewData.value?.actualPaidAmount ?? 0;
+
+ // 计算退款比例
+ let refundRatio = 1;
+ if (actualPaidAmount > 0 && refundableAmount >= 0) {
+ refundRatio = refundableAmount / actualPaidAmount;
+ }
+
+ let calculatedAmount = 0;
+
+ switch (chargeMode) {
+ case 1: // 定价(赛事)
+ // 定价赛事:个人取消不退款,团队取消按比例退款
+ // 检查是否有团队被取消
+ const hasRemovedTeam = removedTeams.value.size > 0;
+ if (hasRemovedTeam) {
+ calculatedAmount = refundableAmount;
+ }
+ break;
+
+ case 2: // 单价(赛事)
+ // 单价赛事:个人取消按比例退款,团队取消按比例退款
+ // 统计取消的人数
+ let cancelCount = 0;
+
+ // 统计团队被取消的团队中的队员数量
+ for (const project of cancelPreviewData.value?.projectDetails || []) {
+ for (const group of project.groups || []) {
+ for (const team of group.teams || []) {
+ const teamKey = `${team.registrationItemId}_${team.teamIndex}`;
+ if (removedTeams.value.has(teamKey)) {
+ cancelCount += (team.members?.length || 0);
+ } else {
+ // 统计该团队中被单独取消的队员
+ for (const member of team.members || []) {
+ if (selectedMembers.value.includes(member.memberId)) {
+ cancelCount++;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // 统计总人数
+ let totalCount = 0;
+ for (const member of cancelPreviewData.value?.members || []) {
+ totalCount++;
+ }
+
+ // 计算单价
+ const unitPriceEvent = totalCount > 0 ? actualPaidAmount / totalCount : 0;
+ calculatedAmount = unitPriceEvent * cancelCount * refundRatio;
+ break;
+
+ case 3: // 单价(项目)
+ // 单价项目:个人取消按比例退款,团队取消按比例退款
+ let projectCancelAmount = 0;
+
+ for (const project of cancelPreviewData.value?.projectDetails || []) {
+ for (const group of project.groups || []) {
+ const unitPrice = group.unitPrice || 0;
+
+ for (const team of group.teams || []) {
+ const teamKey = `${team.registrationItemId}_${team.teamIndex}`;
+
+ if (removedTeams.value.has(teamKey)) {
+ // 团队取消:整个团队都取消
+ projectCancelAmount += unitPrice * (team.members?.length || 0);
+ } else {
+ // 统计该团队中被单独取消的队员
+ for (const member of team.members || []) {
+ if (selectedMembers.value.includes(member.memberId)) {
+ projectCancelAmount += unitPrice;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ calculatedAmount = projectCancelAmount * refundRatio;
+ break;
+
+ default:
+ calculatedAmount = 0;
+ }
+
+ return Math.max(0, calculatedAmount);
});
const toggleMember = (memberId) => {
@@ -1183,12 +1357,40 @@ const toggleMember = (memberId) => {
return;
}
- // 团队项目队员不允许手动选择
- const teamMemberIds = (cancelPreviewData.value?.projects || [])
- .filter(p => p.projectType === '团队')
- .flatMap(p => (cancelPreviewData.value?.members || []).map(m => m.memberId));
+ // 检查该队员是否属于团队项目
+ let isTeamMember = false;
- if (teamMemberIds.includes(memberId)) {
+ // 检查新的数据结构
+ if (cancelPreviewData.value?.projectDetails && cancelPreviewData.value.projectDetails.length > 0) {
+ for (const project of cancelPreviewData.value.projectDetails) {
+ if (project.projectType === '团队') {
+ for (const group of project.groups || []) {
+ for (const team of group.teams || []) {
+ for (const member of team.members || []) {
+ if (member.memberId === memberId) {
+ isTeamMember = true;
+ break;
+ }
+ }
+ if (isTeamMember) break;
+ }
+ if (isTeamMember) break;
+ }
+ if (isTeamMember) break;
+ }
+ }
+ } else {
+ // 检查旧的数据结构
+ const teamMemberIds = (cancelPreviewData.value?.projects || [])
+ .filter(p => p.projectType === '团队')
+ .flatMap(p => (cancelPreviewData.value?.members || []).map(m => m.memberId));
+
+ if (teamMemberIds.includes(memberId)) {
+ isTeamMember = true;
+ }
+ }
+
+ if (isTeamMember) {
return;
}
@@ -1212,27 +1414,135 @@ const removeMember = (memberId) => {
}
};
-const toggleTeam = () => {
- teamRemoved.value = !teamRemoved.value;
- if (teamRemoved.value) {
- // 团队被移除时,清空该团队的队员选择
- const teamMemberIds = (cancelPreviewData.value?.members || [])
- .filter(m => !m.isLeader)
- .map(m => m.memberId);
- selectedMembers.value = selectedMembers.value.filter(id => !teamMemberIds.includes(id));
+// 团队级别的移除功能
+const isTeamRemoved = (registrationItemId, teamIndex) => {
+ const teamKey = `${registrationItemId}_${teamIndex}`;
+ return removedTeams.value.has(teamKey);
+};
+
+const toggleTeam = (registrationItemId, teamIndex) => {
+ const teamKey = `${registrationItemId}_${teamIndex}`;
+
+ if (removedTeams.value.has(teamKey)) {
+ removedTeams.value.delete(teamKey);
+ } else {
+ removedTeams.value.add(teamKey);
+
+ // 移除该团队下所有队员的选择
+ for (const project of cancelPreviewData.value?.projectDetails || []) {
+ for (const group of project.groups || []) {
+ for (const team of group.teams || []) {
+ if (team.registrationItemId === registrationItemId && team.teamIndex === teamIndex) {
+ const teamMemberIds = (team.members || [])
+ .filter(m => !m.isLeader)
+ .map(m => m.memberId);
+ selectedMembers.value = selectedMembers.value.filter(id => !teamMemberIds.includes(id));
+ }
+ }
+ }
+ }
+ }
+};
+
+// 项目级别的团队移除功能(兼容旧逻辑)
+const isTeamRemovedForProject = (projectId) => {
+ // 检查该项目下是否有任何团队被移除
+ for (const project of cancelPreviewData.value?.projectDetails || []) {
+ if (project.projectId === projectId) {
+ for (const group of project.groups || []) {
+ for (const team of group.teams || []) {
+ const teamKey = `${team.registrationItemId}_${team.teamIndex}`;
+ if (removedTeams.value.has(teamKey)) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+};
+
+const toggleTeamForProject = (projectId) => {
+ // 切换该项目下所有团队的移除状态
+ let hasAnyRemoved = false;
+ for (const project of cancelPreviewData.value?.projectDetails || []) {
+ if (project.projectId === projectId) {
+ for (const group of project.groups || []) {
+ for (const team of group.teams || []) {
+ const teamKey = `${team.registrationItemId}_${team.teamIndex}`;
+ if (removedTeams.value.has(teamKey)) {
+ hasAnyRemoved = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (hasAnyRemoved) {
+ // 如果有任何团队被移除,则移除所有团队
+ for (const project of cancelPreviewData.value?.projectDetails || []) {
+ if (project.projectId === projectId) {
+ for (const group of project.groups || []) {
+ for (const team of group.teams || []) {
+ const teamKey = `${team.registrationItemId}_${team.teamIndex}`;
+ removedTeams.value.delete(teamKey);
+ }
+ }
+ }
+ }
+ } else {
+ // 如果没有团队被移除,则添加所有团队
+ for (const project of cancelPreviewData.value?.projectDetails || []) {
+ if (project.projectId === projectId) {
+ for (const group of project.groups || []) {
+ for (const team of group.teams || []) {
+ const teamKey = `${team.registrationItemId}_${team.teamIndex}`;
+ removedTeams.value.add(teamKey);
+ }
+ }
+ }
+ }
+
+ // 移除该项目下所有队员的选择
+ for (const project of cancelPreviewData.value?.projectDetails || []) {
+ if (project.projectId === projectId) {
+ const teamMemberIds = [];
+ for (const group of project.groups || []) {
+ for (const team of group.teams || []) {
+ for (const member of team.members || []) {
+ if (!member.isLeader) {
+ teamMemberIds.push(member.memberId);
+ }
+ }
+ }
+ }
+ selectedMembers.value = selectedMembers.value.filter(id => !teamMemberIds.includes(id));
+ }
+ }
}
};
// 监听取消全部的变化
watch(cancelAll, (newVal) => {
if (newVal) {
- // 取消全部:选中所有队员,并取消团队
+ // 取消全部:选中所有队员,并取消所有团队
selectedMembers.value = (cancelPreviewData.value?.members || []).map(m => m.memberId);
- teamRemoved.value = true;
+
+ // 处理新数据结构中的所有团队
+ removedTeams.value.clear();
+ for (const project of cancelPreviewData.value?.projectDetails || []) {
+ for (const group of project.groups || []) {
+ for (const team of group.teams || []) {
+ const teamKey = `${team.registrationItemId}_${team.teamIndex}`;
+ removedTeams.value.add(teamKey);
+ }
+ }
+ }
} else {
// 取消取消全部:清空选择
selectedMembers.value = [];
- teamRemoved.value = false;
+ removedTeams.value.clear();
}
});
@@ -1244,7 +1554,7 @@ const openCancelDialog = async (row) => {
cancelPreviewData.value = null;
cancelResult.value = null;
selectedMembers.value = [];
- teamRemoved.value = false;
+ removedTeams.value.clear();
cancelAll.value = false;
hasValidationError.value = false;
hasLimitError.value = false;
@@ -1294,16 +1604,39 @@ const submitCancel = async () => {
}
}
+ // 收集所有要取消的人员ID
+ const allCancelMemberIds = new Set(selectedMembers.value);
+
+ // 添加被取消团队中的所有队员
+ for (const project of cancelPreviewData.value?.projectDetails || []) {
+ for (const group of project.groups || []) {
+ for (const team of group.teams || []) {
+ const teamKey = `${team.registrationItemId}_${team.teamIndex}`;
+ if (removedTeams.value.has(teamKey)) {
+ for (const member of team.members || []) {
+ allCancelMemberIds.add(member.memberId);
+ }
+ }
+ }
+ }
+ }
+
+ const finalPersonIds = Array.from(allCancelMemberIds);
+
cancelSubmitting.value = true;
try {
const payload = {
registrationId: cancelPreviewData.value.registrationId,
cancelType: cancelAll.value ? 0 : 1,
- cancelReason: '个人原因'
+ cancelReason: '个人原因',
+ // 添加取消的团队
+ cancelTeams: Array.from(removedTeams.value),
+ // 添加计算后的退款金额
+ calculatedRefundAmount: totalRefundAmount.value
};
if (!cancelAll.value) {
- payload.personIds = selectedMembers.value;
+ payload.personIds = finalPersonIds;
}
// 如果是线下支付且已支付,添加收款人信息
@@ -1361,7 +1694,7 @@ const onCancelDialogClosed = () => {
cancelResult.value = null;
// 按顺序重置,避免 watch 触发问题
selectedMembers.value = [];
- teamRemoved.value = false;
+ removedTeams.value.clear();
cancelAll.value = false;
hasValidationError.value = false;
hasLimitError.value = false;
@@ -1926,6 +2259,62 @@ const submitChangeMembers = async () => {
font-weight: 500;
}
+// 组别容器
+.group-container {
+ margin-bottom: 12px;
+}
+
+.group-header {
+ display: inline-block;
+ padding: 4px 10px;
+ background: #f0f7ff;
+ color: #409eff;
+ border-radius: 4px;
+ font-size: 13px;
+ font-weight: 500;
+ margin-bottom: 8px;
+}
+
+// 团队容器
+.team-container {
+ margin-left: 16px;
+ margin-bottom: 8px;
+}
+
+.team-name {
+ font-size: 13px;
+ color: var(--el-text-color-secondary);
+ margin-bottom: 6px;
+ padding-left: 4px;
+}
+
+.team-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 8px;
+ padding-bottom: 8px;
+ border-bottom: 1px solid #e4e7ed;
+}
+
+.team-label {
+ font-size: 13px;
+ font-weight: 500;
+ color: #606266;
+}
+
+.team-container {
+ margin-bottom: 12px;
+ padding: 12px;
+ background: #f5f7fa;
+ border-radius: 8px;
+ border: 1px dashed #dcdfe6;
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+}
+
.remove-team-icon {
cursor: pointer;
color: var(--el-text-color-secondary);