feat(team): 添加集体/团队管理功能

- 创建martial_team和martial_team_member表
- 添加MartialTeam和MartialTeamMember实体类
- 添加MartialTeamController提供集体CRUD接口
- 支持集体成员关联管理
This commit is contained in:
2025-12-30 18:02:00 +08:00
parent 87a05df04f
commit c7038a5883
17 changed files with 366 additions and 0 deletions

View File

@@ -0,0 +1,58 @@
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.modules.martial.pojo.dto.TeamSubmitDTO;
import org.springblade.modules.martial.pojo.entity.MartialTeam;
import org.springblade.modules.martial.pojo.vo.MartialTeamVO;
import org.springblade.modules.martial.service.IMartialTeamService;
import org.springframework.web.bind.annotation.*;
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/martial/team")
@Tag(name = "集体管理", description = "集体/团队接口")
public class MartialTeamController extends BladeController {
private final IMartialTeamService teamService;
@GetMapping("/list")
@Operation(summary = "分页列表", description = "获取当前用户的集体列表")
public R<IPage<MartialTeamVO>> list(Query query) {
Long userId = AuthUtil.getUserId();
IPage<MartialTeamVO> pages = teamService.getTeamList(userId, query.getCurrent(), query.getSize());
return R.data(pages);
}
@GetMapping("/detail")
@Operation(summary = "详情", description = "获取集体详情")
public R<MartialTeamVO> detail(@RequestParam Long id) {
return R.data(teamService.getTeamDetail(id));
}
@PostMapping("/submit")
@Operation(summary = "保存", description = "新增或修改集体")
public R<Boolean> submit(@RequestBody TeamSubmitDTO dto) {
MartialTeam team = new MartialTeam();
team.setTeamName(dto.getTeamName());
team.setRemark(dto.getRemark());
boolean result = teamService.saveTeamWithMembers(team, dto.getMemberIds());
return R.data(result);
}
@PostMapping("/remove")
@Operation(summary = "删除", description = "删除集体")
public R<Boolean> remove(@RequestParam Long id) {
return R.data(teamService.removeTeamWithMembers(id));
}
}

View File

@@ -0,0 +1,7 @@
package org.springblade.modules.martial.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springblade.modules.martial.pojo.entity.MartialTeam;
public interface MartialTeamMapper extends BaseMapper<MartialTeam> {
}

View File

@@ -0,0 +1,7 @@
package org.springblade.modules.martial.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springblade.modules.martial.pojo.entity.MartialTeamMember;
public interface MartialTeamMemberMapper extends BaseMapper<MartialTeamMember> {
}

View File

@@ -0,0 +1,21 @@
package org.springblade.modules.martial.pojo.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Data
@Schema(description = "集体提交DTO")
public class TeamSubmitDTO {
@Schema(description = "集体名称")
private String teamName;
@Schema(description = "备注")
private String remark;
@Schema(description = "成员ID列表")
private List<Long> memberIds;
}

View File

@@ -0,0 +1,29 @@
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;
/**
* 集体/团队实体类
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("martial_team")
@Schema(description = "集体/团队")
public class MartialTeam extends TenantEntity {
private static final long serialVersionUID = 1L;
@Schema(description = "集体名称")
private String teamName;
@Schema(description = "备注")
private String remark;
@Schema(description = "成员数量")
private Integer memberCount;
}

View File

@@ -0,0 +1,40 @@
package org.springblade.modules.martial.pojo.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 集体成员关联实体类
*/
@Data
@TableName("martial_team_member")
@Schema(description = "集体成员关联")
public class MartialTeamMember implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(type = IdType.AUTO)
private Long id;
@Schema(description = "集体ID")
private Long teamId;
@Schema(description = "选手ID")
private Long athleteId;
@Schema(description = "创建时间")
private LocalDateTime createTime;
@Schema(description = "是否删除")
private Integer isDeleted;
@Schema(description = "租户ID")
private String tenantId;
}

View File

@@ -0,0 +1,33 @@
package org.springblade.modules.martial.pojo.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springblade.modules.martial.pojo.entity.MartialTeam;
import java.util.List;
@Data
@EqualsAndHashCode(callSuper = true)
@Schema(description = "集体视图对象")
public class MartialTeamVO extends MartialTeam {
private static final long serialVersionUID = 1L;
@Schema(description = "成员列表")
private List<MemberInfo> members;
@Data
@Schema(description = "成员信息")
public static class MemberInfo {
@Schema(description = "选手ID")
private Long id;
@Schema(description = "选手姓名")
private String name;
@Schema(description = "身份证号")
private String idCard;
}
}

View File

@@ -0,0 +1,32 @@
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.MartialTeam;
import org.springblade.modules.martial.pojo.vo.MartialTeamVO;
import java.util.List;
public interface IMartialTeamService extends IService<MartialTeam> {
/**
* Save team with members
*/
boolean saveTeamWithMembers(MartialTeam team, List<Long> memberIds);
/**
* Get team list with member count
*/
IPage<MartialTeamVO> getTeamList(Long createUser, Integer current, Integer size);
/**
* Get team detail with members
*/
MartialTeamVO getTeamDetail(Long id);
/**
* Remove team and its members
*/
boolean removeTeamWithMembers(Long id);
}

View File

@@ -0,0 +1,139 @@
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 org.springblade.modules.martial.mapper.MartialTeamMapper;
import org.springblade.modules.martial.mapper.MartialTeamMemberMapper;
import org.springblade.modules.martial.pojo.entity.MartialAthlete;
import org.springblade.modules.martial.pojo.entity.MartialTeam;
import org.springblade.modules.martial.pojo.entity.MartialTeamMember;
import org.springblade.modules.martial.pojo.vo.MartialTeamVO;
import org.springblade.modules.martial.service.IMartialAthleteService;
import org.springblade.modules.martial.service.IMartialTeamService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
@AllArgsConstructor
public class MartialTeamServiceImpl extends ServiceImpl<MartialTeamMapper, MartialTeam> implements IMartialTeamService {
private final MartialTeamMemberMapper teamMemberMapper;
private final IMartialAthleteService athleteService;
@Override
@Transactional(rollbackFor = Exception.class)
public boolean saveTeamWithMembers(MartialTeam team, List<Long> memberIds) {
team.setMemberCount(memberIds != null ? memberIds.size() : 0);
boolean saved = this.save(team);
if (saved && memberIds != null && !memberIds.isEmpty()) {
for (Long athleteId : memberIds) {
MartialTeamMember member = new MartialTeamMember();
member.setTeamId(team.getId());
member.setAthleteId(athleteId);
member.setCreateTime(LocalDateTime.now());
member.setIsDeleted(0);
member.setTenantId("000000");
teamMemberMapper.insert(member);
}
}
return saved;
}
@Override
public IPage<MartialTeamVO> getTeamList(Long createUser, Integer current, Integer size) {
LambdaQueryWrapper<MartialTeam> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(MartialTeam::getCreateUser, createUser);
wrapper.orderByDesc(MartialTeam::getCreateTime);
IPage<MartialTeam> page = new Page<>(current, size);
IPage<MartialTeam> teamPage = this.page(page, wrapper);
IPage<MartialTeamVO> voPage = new Page<>(current, size, teamPage.getTotal());
if (teamPage.getRecords().isEmpty()) {
voPage.setRecords(new ArrayList<>());
return voPage;
}
List<MartialTeamVO> voList = teamPage.getRecords().stream()
.map(team -> {
MartialTeamVO vo = new MartialTeamVO();
BeanUtils.copyProperties(team, vo);
return vo;
})
.collect(Collectors.toList());
voPage.setRecords(voList);
return voPage;
}
@Override
public MartialTeamVO getTeamDetail(Long id) {
MartialTeam team = this.getById(id);
if (team == null) {
return null;
}
MartialTeamVO vo = new MartialTeamVO();
BeanUtils.copyProperties(team, vo);
// Get members
LambdaQueryWrapper<MartialTeamMember> memberWrapper = new LambdaQueryWrapper<>();
memberWrapper.eq(MartialTeamMember::getTeamId, id);
memberWrapper.eq(MartialTeamMember::getIsDeleted, 0);
List<MartialTeamMember> teamMembers = teamMemberMapper.selectList(memberWrapper);
if (!teamMembers.isEmpty()) {
List<Long> athleteIds = teamMembers.stream()
.map(MartialTeamMember::getAthleteId)
.collect(Collectors.toList());
List<MartialAthlete> athletes = athleteService.listByIds(athleteIds);
Map<Long, MartialAthlete> athleteMap = athletes.stream()
.collect(Collectors.toMap(MartialAthlete::getId, a -> a));
List<MartialTeamVO.MemberInfo> members = teamMembers.stream()
.map(tm -> {
MartialTeamVO.MemberInfo info = new MartialTeamVO.MemberInfo();
MartialAthlete athlete = athleteMap.get(tm.getAthleteId());
if (athlete != null) {
info.setId(athlete.getId());
info.setName(athlete.getPlayerName());
info.setIdCard(athlete.getIdCard());
}
return info;
})
.filter(info -> info.getId() != null)
.collect(Collectors.toList());
vo.setMembers(members);
}
return vo;
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean removeTeamWithMembers(Long id) {
// Delete members first
LambdaQueryWrapper<MartialTeamMember> memberWrapper = new LambdaQueryWrapper<>();
memberWrapper.eq(MartialTeamMember::getTeamId, id);
teamMemberMapper.delete(memberWrapper);
// Delete team
return this.removeById(id);
}
}