feat: add contact management and judge project assignment features

- Add MartialContact entity, mapper, service, and controller for contact management
- Add updateProjects endpoint to MartialJudgeInviteController for project assignment
- Fix MartialRegistrationOrderController for multi-project registration
- Update MartialJudgeInviteVO with projects field

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
This commit is contained in:
2026-01-05 15:10:27 +08:00
parent 9fa5eb46df
commit 29e9fb4e0a
9 changed files with 290 additions and 57 deletions

View File

@@ -0,0 +1,64 @@
package org.springblade.modules.martial.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.martial.pojo.entity.MartialContact;
import org.springblade.modules.martial.service.IMartialContactService;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/martial/contact")
@Tag(name = "联系人管理", description = "联系人接口")
public class MartialContactController extends BladeController {
private final IMartialContactService contactService;
@GetMapping("/list")
@Operation(summary = "分页列表", description = "获取当前用户的联系人列表")
public R<IPage<MartialContact>> list(Query query) {
Long userId = AuthUtil.getUserId();
IPage<MartialContact> pages = contactService.getContactList(userId, query.getCurrent(), query.getSize());
return R.data(pages);
}
@GetMapping("/detail")
@Operation(summary = "详情", description = "获取联系人详情")
public R<MartialContact> detail(@RequestParam Long id) {
return R.data(contactService.getContactDetail(id));
}
@PostMapping("/submit")
@Operation(summary = "保存", description = "新增或修改联系人")
public R<Boolean> submit(@RequestBody MartialContact contact) {
Long userId = AuthUtil.getUserId();
log.info("Contact submit - id: {}, name: {}, userId: {}", contact.getId(), contact.getName(), userId);
if (contact.getId() == null) {
contact.setCreateUser(userId);
contact.setCreateTime(new Date());
}
contact.setUpdateUser(userId);
contact.setUpdateTime(new Date());
return R.data(contactService.saveOrUpdate(contact));
}
@PostMapping("/remove")
@Operation(summary = "删除", description = "删除联系人")
public R<Boolean> remove(@RequestParam String ids) {
return R.data(contactService.removeByIds(Func.toLongList(ids)));
}
}

View File

@@ -224,4 +224,24 @@ public class MartialJudgeInviteController extends BladeController {
// 使用EasyExcel或POI导出
}
/**
* 更新邀请的项目分配
*/
@PutMapping("/updateProjects")
@Operation(summary = "更新项目分配", description = "更新裁判邀请的项目分配")
public R updateProjects(@RequestBody java.util.Map<String, Object> params) {
Long inviteId = Long.valueOf(params.get("inviteId").toString());
String projects = params.get("projects").toString();
MartialJudgeInvite invite = judgeInviteService.getById(inviteId);
if (invite == null) {
return R.fail("邀请记录不存在");
}
invite.setProjects(projects);
boolean success = judgeInviteService.updateById(invite);
return success ? R.success("更新成功") : R.fail("更新失败");
}
}

View File

@@ -1,7 +1,6 @@
package org.springblade.modules.martial.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -25,7 +24,6 @@ import org.springblade.modules.martial.mapper.MartialTeamMemberMapper;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Slf4j
@@ -84,7 +82,6 @@ public class MartialRegistrationOrderController extends BladeController {
List<Long> athleteIds = Func.toLongList(dto.getAthleteIds());
List<Long> teamIds = Func.toLongList(dto.getTeamIds());
List<Long> projectIds = Func.toLongList(dto.getProjectIds());
Long firstProjectId = projectIds.isEmpty() ? null : projectIds.get(0);
// Determine if this is a team registration
boolean isTeamRegistration = !teamIds.isEmpty();
@@ -105,7 +102,7 @@ public class MartialRegistrationOrderController extends BladeController {
log.info("订单创建成功订单ID: {}", orderId);
if (isTeamRegistration) {
// Handle team registration
// Handle team registration - create record for each team and each project
for (Long teamId : teamIds) {
MartialTeam team = teamService.getById(teamId);
if (team == null) {
@@ -113,21 +110,16 @@ public class MartialRegistrationOrderController extends BladeController {
continue;
}
// Get team members
LambdaQueryWrapper<MartialTeamMember> memberWrapper = new LambdaQueryWrapper<>();
memberWrapper.eq(MartialTeamMember::getTeamId, teamId);
memberWrapper.eq(MartialTeamMember::getIsDeleted, 0);
List<MartialTeamMember> members = teamMemberMapper.selectList(memberWrapper);
// Create a martial_athlete record for the team
// Create a record for each project
for (Long projectId : projectIds) {
MartialAthlete teamAthlete = new MartialAthlete();
teamAthlete.setOrderId(orderId);
teamAthlete.setCompetitionId(dto.getCompetitionId());
teamAthlete.setProjectId(firstProjectId);
teamAthlete.setProjectId(projectId);
teamAthlete.setTeamName(team.getTeamName());
teamAthlete.setPlayerName(team.getTeamName());
teamAthlete.setOrganization(team.getTeamName());
teamAthlete.setRegistrationStatus(1); // Auto confirm after payment
teamAthlete.setRegistrationStatus(1);
teamAthlete.setCompetitionStatus(0);
teamAthlete.setCreateUser(AuthUtil.getUserId());
teamAthlete.setCreateTime(new java.util.Date());
@@ -136,24 +128,42 @@ public class MartialRegistrationOrderController extends BladeController {
teamAthlete.setStatus(1);
athleteService.save(teamAthlete);
log.info("创建集体参赛记录: teamName={}, athleteId={}", team.getTeamName(), teamAthlete.getId());
log.info("创建集体参赛记录: teamName={}, projectId={}", team.getTeamName(), projectId);
}
}
} else {
// Handle individual registration
if (!athleteIds.isEmpty()) {
LambdaUpdateWrapper<MartialAthlete> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.in(MartialAthlete::getId, athleteIds)
.set(MartialAthlete::getOrderId, orderId)
.set(MartialAthlete::getCompetitionId, dto.getCompetitionId());
if (firstProjectId != null) {
updateWrapper.set(MartialAthlete::getProjectId, firstProjectId);
// Handle individual registration - create record for each athlete and each project
for (Long athleteId : athleteIds) {
MartialAthlete existingAthlete = athleteService.getById(athleteId);
if (existingAthlete == null) {
log.warn("选手不存在: {}", athleteId);
continue;
}
// Auto confirm after payment
updateWrapper.set(MartialAthlete::getRegistrationStatus, 1);
boolean updated = athleteService.update(updateWrapper);
log.info("更新选手关联,选手数量: {}, 更新结果: {}", athleteIds.size(), updated);
// Create a record for each project
for (Long projectId : projectIds) {
MartialAthlete newRecord = new MartialAthlete();
newRecord.setOrderId(orderId);
newRecord.setCompetitionId(dto.getCompetitionId());
newRecord.setProjectId(projectId);
newRecord.setPlayerName(existingAthlete.getPlayerName());
newRecord.setGender(existingAthlete.getGender());
newRecord.setIdCard(existingAthlete.getIdCard());
newRecord.setIdCardType(existingAthlete.getIdCardType());
newRecord.setContactPhone(existingAthlete.getContactPhone());
newRecord.setOrganization(existingAthlete.getOrganization());
newRecord.setTeamName(existingAthlete.getTeamName());
newRecord.setRegistrationStatus(1);
newRecord.setCompetitionStatus(0);
newRecord.setCreateUser(AuthUtil.getUserId());
newRecord.setCreateTime(new java.util.Date());
newRecord.setTenantId("000000");
newRecord.setIsDeleted(0);
newRecord.setStatus(1);
athleteService.save(newRecord);
log.info("创建选手参赛记录: playerName={}, projectId={}", existingAthlete.getPlayerName(), projectId);
}
}
}

View File

@@ -0,0 +1,13 @@
package org.springblade.modules.martial.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springblade.modules.martial.pojo.entity.MartialContact;
/**
* Contact Mapper
*/
@Mapper
public interface MartialContactMapper extends BaseMapper<MartialContact> {
}

View File

@@ -0,0 +1,41 @@
package org.springblade.modules.martial.pojo.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springblade.core.tenant.mp.TenantEntity;
/**
* Contact entity
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("martial_contact")
@Schema(description = "联系人")
public class MartialContact extends TenantEntity {
private static final long serialVersionUID = 1L;
@Schema(description = "证件类型")
private String idType;
@Schema(description = "姓名")
private String name;
@Schema(description = "证件号码")
private String idCard;
@Schema(description = "手机号码")
private String phone;
@Schema(description = "邮箱")
private String email;
@Schema(description = "地址")
private String address;
@Schema(description = "是否默认联系人")
private Boolean isDefault;
}

View File

@@ -80,4 +80,15 @@ public class MartialJudgeInviteVO extends MartialJudgeInvite {
@Schema(description = "场地名称")
private String venueName;
/**
* 获取场地名称
* 总裁(referee_type=3)显示全部场地
*/
public String getVenueName() {
if (this.getRefereeType() != null && this.getRefereeType() == 3) {
return "全部场地";
}
return venueName;
}
}

View File

@@ -0,0 +1,22 @@
package org.springblade.modules.martial.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import org.springblade.modules.martial.pojo.entity.MartialContact;
/**
* Contact Service Interface
*/
public interface IMartialContactService extends IService<MartialContact> {
/**
* Get contact list by user
*/
IPage<MartialContact> getContactList(Long userId, Integer current, Integer size);
/**
* Get contact detail
*/
MartialContact getContactDetail(Long id);
}

View File

@@ -0,0 +1,38 @@
package org.springblade.modules.martial.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.modules.martial.mapper.MartialContactMapper;
import org.springblade.modules.martial.pojo.entity.MartialContact;
import org.springblade.modules.martial.service.IMartialContactService;
import org.springframework.stereotype.Service;
/**
* Contact Service Implementation
*/
@Slf4j
@Service
@AllArgsConstructor
public class MartialContactServiceImpl extends ServiceImpl<MartialContactMapper, MartialContact> implements IMartialContactService {
@Override
public IPage<MartialContact> getContactList(Long userId, Integer current, Integer size) {
Page<MartialContact> page = new Page<>(current, size);
LambdaQueryWrapper<MartialContact> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(MartialContact::getCreateUser, userId);
wrapper.eq(MartialContact::getIsDeleted, 0);
wrapper.orderByDesc(MartialContact::getIsDefault);
wrapper.orderByDesc(MartialContact::getCreateTime);
return this.page(page, wrapper);
}
@Override
public MartialContact getContactDetail(Long id) {
return this.getById(id);
}
}

View File

@@ -152,18 +152,25 @@ public class MartialRegistrationOrderServiceImpl extends ServiceImpl<MartialRegi
if (!athletes.isEmpty()) {
String athleteNames = athletes.stream()
.map(MartialAthlete::getPlayerName)
.distinct()
.collect(Collectors.joining(""));
vo.setAthleteNames(athleteNames);
List<MartialRegistrationOrderVO.AthleteInfo> athleteList = athletes.stream()
.map(athlete -> {
.collect(Collectors.toMap(
MartialAthlete::getPlayerName,
athlete -> {
MartialRegistrationOrderVO.AthleteInfo info = new MartialRegistrationOrderVO.AthleteInfo();
info.setId(athlete.getId());
info.setPlayerName(athlete.getPlayerName());
info.setGender(athlete.getGender());
info.setIdCard(athlete.getIdCard());
return info;
})
},
(existing, replacement) -> existing
))
.values()
.stream()
.collect(Collectors.toList());
vo.setAthleteList(athleteList);
@@ -242,18 +249,25 @@ public class MartialRegistrationOrderServiceImpl extends ServiceImpl<MartialRegi
if (!athletes.isEmpty()) {
String athleteNames = athletes.stream()
.map(MartialAthlete::getPlayerName)
.distinct()
.collect(Collectors.joining(""));
vo.setAthleteNames(athleteNames);
List<MartialRegistrationOrderVO.AthleteInfo> athleteList = athletes.stream()
.map(athlete -> {
.collect(Collectors.toMap(
MartialAthlete::getPlayerName,
athlete -> {
MartialRegistrationOrderVO.AthleteInfo info = new MartialRegistrationOrderVO.AthleteInfo();
info.setId(athlete.getId());
info.setPlayerName(athlete.getPlayerName());
info.setGender(athlete.getGender());
info.setIdCard(athlete.getIdCard());
return info;
})
},
(existing, replacement) -> existing
))
.values()
.stream()
.collect(Collectors.toList());
vo.setAthleteList(athleteList);