拼桌聊天后台功能

This commit is contained in:
SjS 2025-05-24 18:02:32 +08:00
parent ba679dce2b
commit 8c54f8aaa1
27 changed files with 476 additions and 75 deletions

View File

@ -5,13 +5,18 @@ import com.ruoyi.bst.booth.domain.Booth;
import com.ruoyi.bst.booth.domain.BoothQuery;
import com.ruoyi.bst.booth.domain.BoothVO;
import com.ruoyi.bst.booth.mapper.BoothMapper;
import com.ruoyi.bst.booth.service.BoothService;
import com.ruoyi.bst.booth.service.BoothValidator;
import com.ruoyi.bst.device.domain.DeviceQuery;
import com.ruoyi.bst.device.domain.DeviceVO;
import com.ruoyi.bst.store.domain.StoreVO;
import com.ruoyi.bst.store.service.StoreService;
import com.ruoyi.bst.storeStaff.domain.enums.StoreStaffPermission;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.common.utils.collection.CollectionUtils;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Arrays;
@ -21,11 +26,13 @@ import java.util.List;
@Service
public class BoothValidatorImpl implements BoothValidator {
private final BoothMapper boothMapper;
@Autowired
private BoothMapper boothMapper;
@Autowired
private BoothService boothService;
@Autowired
private StoreService storeService;
public BoothValidatorImpl(BoothMapper boothMapper) {
this.boothMapper = boothMapper;
}
@Override
public boolean canEdit(Long boothId) {
@ -37,6 +44,7 @@ public class BoothValidatorImpl implements BoothValidator {
return canOperate(ids);
}
// 是否可以操作卡座
private boolean canOperate(List<Long> boothIds) {
return hasPermission(boothIds);

View File

@ -1,7 +1,24 @@
package com.ruoyi.bst.chat.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
@Data
public class ChatQuery extends ChatVO{
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty("截止时间")
private LocalDateTime deadline;
@ApiModelProperty("发送人名称")
private String sendName;
@ApiModelProperty("接收人名称")
private String receiveName;
}

View File

@ -1,7 +1,29 @@
package com.ruoyi.bst.chat.domain;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class ChatVO extends Chat{
@ApiModelProperty("队伍名称")
private String teamName;
@ApiModelProperty("发送人名称")
private String senderName;
@ApiModelProperty("接收人名称")
private String receiverName;
@ApiModelProperty("队伍ID")
private Long teamId;
@ApiModelProperty("最新未读消息时间")
private LocalDateTime latestTime;
@ApiModelProperty("未读消息数量")
private Integer unReadNum;
}

View File

@ -0,0 +1,22 @@
package com.ruoyi.bst.chat.domain.enums;
import com.ruoyi.common.utils.collection.CollectionUtils;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.List;
@Getter
@AllArgsConstructor
public enum ChatMsgType {
TEXT("1", "文本"),
PICTURE("2", "图片"),
VIDEO("3", "视频"),
WELCOME("4", "系统欢迎");
private final String code;
private final String name;
}

View File

@ -5,6 +5,7 @@ import com.ruoyi.bst.chat.domain.Chat;
import com.ruoyi.bst.chat.domain.ChatVO;
import com.ruoyi.bst.chat.domain.ChatQuery;
import org.apache.ibatis.annotations.Param;
import org.springframework.security.core.parameters.P;
/**
* 聊天记录列表Mapper接口
@ -80,4 +81,8 @@ public interface ChatMapper
* @return
*/
int selectCount(@Param("query") ChatQuery query);
List<ChatVO> selectTeamMsgList(@Param("query") ChatQuery query);
int retractMessage(@Param("batchId") String batchId);
}

View File

@ -18,26 +18,40 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<sql id="selectChatVo">
select
id,
send_id,
receive_id,
team_id,
is_read,
deleted,
type,
create_time,
read_time
from bst_chat
bc.id,
bc.send_id,
bc.receive_id,
bc.team_id,
bc.is_read,
bc.deleted,
bc.type,
bc.create_time,
bc.read_time,
bc.batch_id,
bt.name as team_name,
su_send.nick_name as sender_name,
su_receive.nick_name as receiver_name
from <include refid="searchTable"/>
</sql>
<sql id="searchTable">
bst_chat bc
left join bst_team bt on bc.team_id = bt.id
left join sys_user su_send on bc.send_id = su_send.user_id
left join sys_user su_receive on bc.receive_id = su_receive.user_id
</sql>
<sql id="searchCondition">
<if test="query.sendId != null "> and send_id = #{query.sendId}</if>
<if test="query.receiveId != null "> and receive_id = #{query.receiveId}</if>
<if test="query.teamId != null "> and team_id = #{query.teamId}</if>
<if test="query.isRead != null "> and is_read = #{query.isRead}</if>
<if test="query.deleted != null "> and deleted = #{query.deleted}</if>
<if test="query.type != null and query.type != ''"> and type = #{query.type}</if>
<if test="query.readTime != null "> and read_time = #{query.readTime}</if>
<if test="query.sendId != null "> and bc.send_id = #{query.sendId}</if>
<if test="query.receiveId != null "> and bc.receive_id = #{query.receiveId}</if>
<if test="query.teamId != null "> and bc.team_id = #{query.teamId}</if>
<if test="query.isRead != null "> and bc.is_read = #{query.isRead}</if>
<if test="query.deleted != null "> and bc.deleted = #{query.deleted}</if>
<if test="query.type != null and query.type != ''"> and bc.type = #{query.type}</if>
<if test="query.readTime != null "> and bc.read_time = #{query.readTime}</if>
<if test="query.deadline != null "> and bc.create_time &lt;= #{query.deadline}</if>
<if test="query.senderName != null "> and su_send.nick_name like concat ('%',#{query.senderName},'%')</if>
<if test="query.receiverName != null "> and su_receive.nick_name like concat ('%',#{query.receiverName},'%')</if>
${query.params.dataScope}
</sql>
@ -61,6 +75,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</where>
</select>
<select id="selectTeamMsgList" resultType="com.ruoyi.bst.chat.domain.ChatVO">
select bt.name as team_name,count(bc.id) as unread_num,bt.id as team_id,max(bc.create_time) as latest_time
from <include refid="searchTable"/>
<where>
<include refid="searchCondition"/>
</where>
group by bc.team_id
</select>
<insert id="insertChat" parameterType="Chat" useGeneratedKeys="true" keyProperty="id">
insert into bst_chat
<trim prefix="(" suffix=")" suffixOverrides=",">
@ -235,6 +258,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</where>
</update>
<!--retractMessage-->
<update id="retractMessage">
update bst_chat bc
set bc.deleted = true
where bc.batch_id = #{batchId}
</update>
<sql id="updateColumns">
<if test="data.sendId != null">send_id = #{data.sendId},</if>
<if test="data.receiveId != null">receive_id = #{data.receiveId},</if>

View File

@ -80,4 +80,9 @@ public interface ChatService
*/
public int selectCount(ChatQuery query);
void sendWelcomeMessage(Long teamId, Long userId);
List<ChatVO> selectTeamMsgList(ChatQuery query);
int retractMessage(String bchId);
}

View File

@ -5,13 +5,19 @@ import com.ruoyi.bst.chat.domain.ChatVO;
import com.ruoyi.bst.chat.service.ChatConverter;
import com.ruoyi.bst.chat.service.ChatService;
import com.ruoyi.bst.team.domain.TeamQuery;
import com.ruoyi.bst.team.domain.TeamVO;
import com.ruoyi.bst.team.domain.enums.TeamStatus;
import com.ruoyi.bst.team.service.TeamService;
import com.ruoyi.bst.teamUser.service.TeamUserService;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
@ -24,15 +30,22 @@ public class ChatConverterImpl implements ChatConverter {
@Autowired
private TeamUserService teamUserService;
@Autowired
private TeamService teamService;
@Override
public List<ChatVO> toPoByCreate(Chat chat) {
chat.setBatchId(IdUtils.simpleUUID());
chat.setCreateTime(DateUtils.getNowDate());
// 拼桌存在校验
TeamQuery query = new TeamQuery();
query.setStatus(TeamStatus.NORMAL.getCode());
query.setId(chat.getTeamId());
TeamVO vo = teamService.selectOne(query);
ServiceUtil.assertion(vo==null,"id为%s的拼桌不存在");
// 获取成员ID列表
List<Long> userIds = teamUserService.selectUserIdsByTeamId(chat.getTeamId())
.stream()
.collect(Collectors.toList());
List<Long> userIds = teamUserService.selectUserIdsByTeamId(chat.getTeamId());
ServiceUtil.assertion(!userIds.contains(chat.getSendId()), "你不是当前群聊的成员,无法发送消息");
List<ChatVO> messages = userIds.stream()
.map(receiverId -> buildChatMessage(chat, receiverId))
@ -46,6 +59,10 @@ public class ChatConverterImpl implements ChatConverter {
BeanUtils.copyProperties(origin, message);
// 设置接收者ID
message.setReceiveId(receiverId);
// 设置批次ID
message.setBatchId(IdUtils.simpleUUID());
// 设置创建时间
message.setCreateTime(DateUtils.getNowDate());
return message;
}
}

View File

@ -1,13 +1,18 @@
package com.ruoyi.bst.chat.service.impl;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import com.ruoyi.bst.chat.domain.enums.ChatMsgType;
import com.ruoyi.bst.chat.service.ChatConverter;
import com.ruoyi.common.core.domain.vo.UserVO;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.collection.CollectionUtils;
import com.ruoyi.system.user.service.UserService;
import com.ruoyi.ws.service.UserWebSocketService;
import org.checkerframework.checker.units.qual.C;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.bst.chat.mapper.ChatMapper;
@ -33,6 +38,8 @@ public class ChatServiceImpl implements ChatService
private RedisCache redisCache;
@Autowired
private UserWebSocketService userWebSocketService;
@Autowired
private UserService userService;
/**
* 查询聊天记录列表
@ -116,6 +123,29 @@ public class ChatServiceImpl implements ChatService
});
}
@Override
public void sendWelcomeMessage(Long teamId, Long userId) {
UserVO user = userService.selectUserById(userId);
Chat chat = new Chat();
chat.setTeamId(teamId);
chat.setReceiveId(userId);
chat.setCreateTime(DateUtils.getNowDate());
chat.setType(ChatMsgType.WELCOME.getCode());
chat.setContent("欢迎用户"+user.getNickName()+"加入拼桌");
redisCache.rightPush("chat:pending:welcome:" + userId, chat);
userWebSocketService.sendMessageToUser(chat, user.getUserId());
}
@Override
public List<ChatVO> selectTeamMsgList(ChatQuery query) {
return chatMapper.selectTeamMsgList(query);
}
@Override
public int retractMessage(String batchId) {
return chatMapper.retractMessage(batchId);
}
@Override
public int batchInsert(List<Chat> list) {
if (CollectionUtils.isEmptyElement(list)) {
@ -144,4 +174,6 @@ public class ChatServiceImpl implements ChatService
public int selectCount(ChatQuery query) {
return chatMapper.selectCount(query);
}
}

View File

@ -12,4 +12,13 @@ public class TeamVO extends Team{
@ApiModelProperty("店铺名称")
private String storeName;
@ApiModelProperty("卡座名称")
private String boothName;
@ApiModelProperty("发起人姓名")
private String sponsorName;
@ApiModelProperty("发起人ID")
private Long sponsorId;
}

View File

@ -73,4 +73,6 @@ public interface TeamMapper
public int deleteTeamByIds(Long[] ids);
int addCurrentNums(@Param("data") TeamVO vo);
int reduceCurrentNum(@Param("teamId") Long teamId);
}

View File

@ -33,27 +33,35 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
bt.create_time,
bt.status,
bt.current_num,
bs.store_name
from bst_team bt
bs.store_name,
bb.booth_name
from <include refid="searchTable"/>
</sql>
<sql id="searchTable">
bst_team bt
left join bst_store bs on bt.store_id = bs.store_id
left join bst_booth bb on bt.booth_id = bb.booth_id
</sql>
<sql id="searchCondition">
<if test="query.storeId != null "> and store_id = #{query.storeId}</if>
<if test="query.id != null "> and id = #{query.id}</if>
<if test="query.boothId != null "> and booth_id = #{query.boothId}</if>
<if test="query.name != null and query.name != ''"> and name like concat('%', #{query.name}, '%')</if>
<if test="query.prefer != null and query.prefer != ''"> and prefer = #{query.prefer}</if>
<if test="query.type != null and query.type != ''"> and type = #{query.type}</if>
<if test="query.topic != null and query.topic != ''"> and topic like concat('%', #{query.topic}, '%')</if>
<if test="query.limitNum != null "> and limit_num = #{query.limitNum}</if>
<if test="query.bookTime != null "> and book_time = #{query.bookTime}</if>
<if test="query.status != null "> and status = #{query.status}</if>
<if test="query.storeId != null "> and bt.store_id = #{query.storeId}</if>
<if test="query.id != null "> and bt.id = #{query.id}</if>
<if test="query.boothId != null "> and bt.booth_id = #{query.boothId}</if>
<if test="query.name != null and query.name != ''"> and bt.name like concat('%', #{query.name}, '%')</if>
<if test="query.prefer != null and query.prefer != ''"> and bt.prefer = #{query.prefer}</if>
<if test="query.type != null and query.type != ''"> and bt.type = #{query.type}</if>
<if test="query.topic != null and query.topic != ''"> and bt.topic like concat('%', #{query.topic}, '%')</if>
<if test="query.limitNum != null "> and bt.limit_num = #{query.limitNum}</if>
<if test="query.bookTime != null "> and bt.book_time = #{query.bookTime}</if>
<if test="query.status != null "> and bt.status = #{query.status}</if>
<if test="query.storeName != null "> and bs.store_name like concat('%', #{query.storeName}, '%')</if>
<if test="query.boothName != null "> and bb.booth_name like concat('%', #{query.boothName}, '%')</if>
${@com.ruoyi.framework.util.DataScopeUtil@create(query.scope)
.userSetAlias("bs.user_id")
.storeAlias("bt.store_id",query.storePermissions)
.build()
}
}
${query.params.dataScope}
</sql>
@ -252,6 +260,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
where id = #{data.id}
</update>
<update id="reduceCurrentNum">
update bst_team
set current_num = current_num - 1
where id = #{teamId} and current_num &gt; 0
</update>
<sql id="updateColumns">
<if test="data.storeId != null">store_id = #{data.storeId},</if>
<if test="data.boothId != null">booth_id = #{data.boothId},</if>

View File

@ -0,0 +1,17 @@
package com.ruoyi.bst.team.service;
import com.ruoyi.bst.team.domain.TeamVO;
import java.util.List;
public interface TeamAssembler {
/**
* 拼接发起人
* @param list
*/
void assembleSponsor(List<TeamVO> list);
}

View File

@ -79,9 +79,13 @@ public interface TeamService
int exitTeam(Long teamId, Long userId);
int kick(Long teamId, Long userId);
int disTeam(Long teamId);
TeamVO selectOne(TeamQuery query);
List<TeamUserVO> getTeammate(Long teamId);
TeamVO getTeamInfo(TeamQuery query);
}

View File

@ -0,0 +1,49 @@
package com.ruoyi.bst.team.service.impl;
import com.ruoyi.bst.team.domain.TeamQuery;
import com.ruoyi.bst.team.domain.TeamVO;
import com.ruoyi.bst.team.service.TeamAssembler;
import com.ruoyi.bst.team.service.TeamService;
import com.ruoyi.bst.teamUser.domain.TeamUser;
import com.ruoyi.bst.teamUser.domain.TeamUserQuery;
import com.ruoyi.bst.teamUser.domain.TeamUserVO;
import com.ruoyi.bst.teamUser.domain.enums.RoleType;
import com.ruoyi.bst.teamUser.service.TeamUserAssembler;
import com.ruoyi.bst.teamUser.service.TeamUserService;
import com.ruoyi.common.utils.collection.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
public class TeamAssemblerImpl implements TeamAssembler {
@Autowired
private TeamUserService teamUserService;
@Override
public void assembleSponsor(List<TeamVO> list) {
if (CollectionUtils.isEmptyElement(list)) {
return;
}
List<Long> teamIds = CollectionUtils.map(list, TeamVO::getId);
List<TeamUserVO> teamUserList = new ArrayList<>();
TeamUserQuery query = new TeamUserQuery();
query.setTeamIds(teamIds);
query.setRole(RoleType.CREATOR.getCode());
teamUserList = teamUserService.selectTeamUserList(query);
Map<Long, TeamUserVO> teamUserMap = teamUserList.stream().collect(Collectors.toMap(TeamUserVO::getTeamId, TeamUserVO -> TeamUserVO));
for (TeamVO team : list) {
team.setSponsorId(teamUserMap.get(team.getId()).getUserId());
team.setSponsorName(teamUserMap.get(team.getId()).getNickName());
}
}
}

View File

@ -1,13 +1,19 @@
package com.ruoyi.bst.team.service.impl;
import com.ruoyi.bst.booth.domain.BoothVO;
import com.ruoyi.bst.booth.service.BoothService;
import com.ruoyi.bst.booth.service.BoothValidator;
import com.ruoyi.bst.store.domain.Store;
import com.ruoyi.bst.store.service.StoreConverter;
import com.ruoyi.bst.team.domain.Team;
import com.ruoyi.bst.team.domain.TeamVO;
import com.ruoyi.bst.team.domain.enums.TeamStatus;
import com.ruoyi.bst.team.domain.enums.TeamType;
import com.ruoyi.bst.team.service.TeamConverter;
import com.ruoyi.bst.team.service.TeamService;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ServiceUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
@ -15,22 +21,31 @@ import java.util.Date;
@Service
public class TeamConverterImpl implements TeamConverter {
@Autowired
private BoothValidator boothValidator;
@Autowired
private BoothService boothService;
@Autowired
private TeamService teamService;
@Override
public Team toPoByCreate(Team data) {
if (data == null) {
return null;
}
Team po = new Team();
// 设置基本信息
Team po = new Team();
if (data.getType().equals(TeamType.BOOK.getCode())){
ServiceUtil.assertion(data.getBookTime()==null,"预约拼桌时间不可以为空");
po.setBookTime(data.getBookTime());
}
po.setStoreId(data.getStoreId());
po.setBoothId(data.getBoothId());
po.setName(data.getName());
po.setPrefer(data.getPrefer());
po.setType(data.getType());
if (data.getType().equals(TeamType.BOOK.getCode())){
ServiceUtil.assertion(data.getBookTime()==null,"预约拼桌时间不可以为空");
po.setBookTime(data.getBookTime());
}
po.setTopic(data.getTopic());
po.setLimitNum(data.getLimitNum());
po.setCreateTime(DateUtils.getNowDate());
@ -43,8 +58,16 @@ public class TeamConverterImpl implements TeamConverter {
if (data == null) {
return null;
}
Team po = new Team();
// 校验
ServiceUtil.assertion(data.getId() == null,"拼桌ID不能为空");
TeamVO team = teamService.selectTeamById(data.getId());
if (data.getBoothId() != null) {
BoothVO booth = boothService.selectBoothByBoothId(data.getBoothId());
ServiceUtil.assertion(booth.getStoreId().equals(team.getStoreId()),"id为%s的分区不属id为%s的店铺",data.getBoothId(),team.getStoreId());
}
// 设置基本信息
Team po = new Team();
po.setId(data.getId());
po.setName(data.getName());
po.setPrefer(data.getPrefer());

View File

@ -9,6 +9,7 @@ import com.ruoyi.bst.account.domain.AccountQuery;
import com.ruoyi.bst.account.domain.AccountVO;
import com.ruoyi.bst.booth.domain.BoothVO;
import com.ruoyi.bst.booth.service.BoothService;
import com.ruoyi.bst.chat.service.ChatService;
import com.ruoyi.bst.store.domain.StoreQuery;
import com.ruoyi.bst.store.domain.StoreVO;
import com.ruoyi.bst.storeStaff.domain.enums.StoreStaffPermission;
@ -63,6 +64,8 @@ public class TeamServiceImpl implements TeamService {
private TeamUserValidator teamUserValidator;
@Autowired
private TeamValidator teamValidator;
@Autowired
private ChatService chatService;
/**
* 查询拼桌
@ -157,6 +160,15 @@ public class TeamServiceImpl implements TeamService {
@Override
public int exitTeam(Long teamId, Long userId) {
return this.exit(teamId, userId,TeamUserStatus.EXITED.getCode());
}
@Override
public int kick(Long teamId, Long userId) {
return this.exit(teamId, userId,TeamUserStatus.KICKED.getCode());
}
public int exit(Long teamId, Long userId ,String userStatus) {
TeamUserQuery query = new TeamUserQuery();
query.setTeamId(teamId);
query.setUserId(userId);
@ -165,14 +177,16 @@ public class TeamServiceImpl implements TeamService {
TeamVO team = teamMapper.selectTeamById(teamId);
ServiceUtil.assertion(team == null, "id为%s的拼桌信息不存在", teamId);
TeamUserVO vo = teamUserService.selectOne(query);
ServiceUtil.assertion(vo == null, "您不属于该拼桌的成员");
ServiceUtil.assertion(vo.getRole().equals(RoleType.CREATOR.getCode()), "发起者如果要退出请选择解散拼桌");
vo.setStatus(TeamUserStatus.EXITED.getCode());
ServiceUtil.assertion(vo == null, "id为%s的用户不属于属于该拼桌的成员",userId);
// 区分管理员踢出成员还是主动退出
if (userStatus.equals(TeamUserStatus.EXITED.getCode())) {
ServiceUtil.assertion(vo.getRole().equals(RoleType.CREATOR.getCode()), "发起者如果要退出请选择解散拼桌");
}
vo.setStatus(userStatus);
Integer result = transactionTemplate.execute(status -> {
// 更新当前拼桌人数
team.setCurrentNum(team.getCurrentNum() - 1);
int i = teamMapper.updateTeam(team);
ServiceUtil.assertion(i <= 0, "退出拼桌失败");
int i = teamMapper.reduceCurrentNum(teamId);
ServiceUtil.assertion(i <= 0, "拼桌人数减少失败");
// 更新用户状态
i = teamUserService.updateTeamUser(vo);
ServiceUtil.assertion(i <= 0, "退出拼桌失败");
@ -190,7 +204,7 @@ public class TeamServiceImpl implements TeamService {
team.setCurrentNum(0);
int i = teamService.updateTeam(team);
ServiceUtil.assertion(i <= 0, "拼桌信息更新失败");
// 修改对应的用户为退出状态
// 修改对应的用户为解散状态
TeamUser data = new TeamUser();
data.setStatus(TeamUserStatus.DISBANDED.getCode());
TeamUserQuery query = new TeamUserQuery();
@ -226,6 +240,13 @@ public class TeamServiceImpl implements TeamService {
return userList;
}
@Override
public TeamVO getTeamInfo(TeamQuery query) {
TeamVO vo = teamService.selectOne(query);
ServiceUtil.assertion(vo == null,"该拼桌不存在或已解散");
return vo;
}
@Override
public int createTeam(Team team, Long userId) {
BoothVO booth = boothService.selectBoothByBoothId(team.getBoothId());
@ -249,9 +270,12 @@ public class TeamServiceImpl implements TeamService {
TeamVO vo = teamService.selectTeamById(teamId);
ServiceUtil.assertion(vo == null, "id为%s的拼桌信息不存在", teamId);
Integer result = transactionTemplate.execute(status -> {
// 增加当前人数
int i = teamMapper.addCurrentNums(vo);
ServiceUtil.assertion(i <= 0, "加入拼桌失败");
// 插入用户拼桌信息
teamUser.setTeamId(teamId);
teamUser.setUserId(userId);
teamUser.setRole(role);
@ -259,6 +283,9 @@ public class TeamServiceImpl implements TeamService {
teamUser.setStatus(userStatus);
i = teamUserService.insertTeamUser(teamUser);
ServiceUtil.assertion(i <= 0, "加入拼桌失败");
// 向用户发送默认欢迎消息
chatService.sendWelcomeMessage(teamId,userId);
return i;
});
return result;

View File

@ -8,12 +8,6 @@ import java.util.List;
@Data
public class TeamUserQuery extends TeamUserVO{
@ApiModelProperty("用户状态")
private String status;
@ApiModelProperty("用户角色")
private String role;
@ApiModelProperty("队伍ID列表")
private List<Long> teamIds;
}

View File

@ -8,11 +8,23 @@ import lombok.Data;
@Data
public class TeamUserVO extends TeamUser{
@ApiModelProperty("店铺名称")
private String storeName;
@ApiModelProperty("拼桌队伍名称")
private String teamName;
@ApiModelProperty("发起人姓名信息")
private String nickName;
@ApiModelProperty("邀请人姓名")
private String inviterName;
@ApiModelProperty("当前拼桌用户数")
private Integer currentNum;
@ApiModelProperty("店铺名称")
private String storeName;
@ApiModelProperty("店铺ID")
private Long storeId;
@ApiModelProperty("拼桌信息")
private Team team;

View File

@ -9,7 +9,9 @@ public enum TeamUserStatus {
JOINED("1", "已加入"),
EXITED("2", "已退出"),
DISBANDED("3", "已解散"),;
DISBANDED("3", "已解散"),
KICKED("4", "被踢出");
private final String code;
private final String name;

View File

@ -26,10 +26,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
btu.status,
btu.create_time,
bt.current_num,
bs.store_name
bt.name as team_name,
bs.store_name,
bs.store_id,
su.nick_name,
su_inviter.nick_name as inviter_name
from bst_team_user btu
left join bst_team bt on btu.team_id = bt.id
left join bst_store bs on bt.store_id = bs.store_id
left join sys_user su on btu.user_id = su.user_id
left join sys_user su_inviter on btu.inviter_id = su_inviter.user_id
</sql>
<sql id="searchCondition">
@ -39,12 +45,20 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="query.role != null "> and btu.role = #{query.role}</if>
<if test="query.joinType != null and query.joinType != ''"> and btu.join_type = #{query.joinType}</if>
<if test="query.status != null and query.status != ''"> and btu.status = #{query.status}</if>
<if test="query.nickName != null and query.nickName != ''"> and su.nick_name like concat('%', #{query.nickName}, '%')</if>
<if test="query.teamName != null and query.teamName != ''"> and bt.name like concat('%', #{query.teamName}, '%')</if>
<if test="query.inviterName != null and query.inviterName != ''"> and su_inviter.nick_name like concat('%', #{query.inviterName}, '%')</if>
<if test="query.teamIds != null and query.teamIds.size() > 0">
and btu.team_id in
<foreach item="item" collection="query.teamIds" open="(" separator="," close=")">
#{item}
</foreach>
</if>
${@com.ruoyi.framework.util.DataScopeUtil@create(query.scope)
.userSetAlias("bs.user_id")
.storeAlias("bt.store_id",query.storePermissions)
.build()
}
${query.params.dataScope}
</sql>

View File

@ -70,4 +70,8 @@ public interface TeamUserService
TeamUserVO selectMyTeam(Long userId);
List<Long> selectUserIdsByTeamId(Long teamId);
TeamUserVO getTeamUser(TeamUserQuery query);
int kick(Long teamId,Long userId);
}

View File

@ -10,6 +10,7 @@ import com.ruoyi.bst.teamUser.domain.enums.TeamUserStatus;
import com.ruoyi.bst.teamUser.service.TeamUserService;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.common.utils.collection.CollectionUtils;
import com.ruoyi.system.notice.domain.Notice;
import org.springframework.beans.factory.annotation.Autowired;
@ -144,4 +145,16 @@ public class TeamUserServiceImpl implements TeamUserService
public List<Long> selectUserIdsByTeamId(Long teamId) {
return teamUserMapper.selectUserIdsByTeamId(teamId);
}
@Override
public TeamUserVO getTeamUser(TeamUserQuery query) {
TeamUserVO vo = this.selectOne(query);
ServiceUtil.assertion(vo == null,"当前组队成员信息不存在");
return vo;
}
@Override
public int kick(Long teamId, Long userId) {
return teamService.kick(teamId, userId);
}
}

View File

@ -30,6 +30,8 @@ public class AppChatController extends BaseController {
@Autowired
private ChatService chatService;
@Autowired
private ChatMapper chatMapper;
@ApiOperation("发送消息")
@PostMapping("/sendMessage")
@ -42,7 +44,7 @@ public class AppChatController extends BaseController {
@ApiOperation("消息已读id为空时则将本人所有未读消息设置为已读")
@PostMapping("/read")
public AjaxResult read(@RequestParam(required = false) Long id) {
return success(chatService.read(getUserId(), id));
return AjaxResult.success(chatService.read(getUserId(), id));
}
@ApiOperation("获取本人接收的消息列表")
@ -51,17 +53,40 @@ public class AppChatController extends BaseController {
startPage();
PageHelper.orderBy("is_read asc, create_time desc");
query.setReceiveId(getUserId());
query.setDeleted(false);
List<ChatVO> list = chatService.selectChatList(query);
return getDataTable(list);
}
@ApiOperation("获取拼桌未读消息列表")
@GetMapping("/teamMsgRecord")
public TableDataInfo teamMsgRecord(ChatQuery query) {
startPage();
PageHelper.orderBy("latest_time desc");
query.setReceiveId(getUserId());
query.setDeleted(false);
query.setIsRead(false);
query.setReceiveId(getUserId());
List<ChatVO> list = chatService.selectTeamMsgList(query);
return getDataTable(list);
}
@ApiOperation("查询本人未读消息数量")
@GetMapping("/unreadCount")
public AjaxResult unreadCount() {
ChatQuery query = new ChatQuery();
query.setReceiveId(getUserId());
query.setIsRead(false);
return success(chatService.selectCount(query));
return AjaxResult.success(chatService.selectCount(query));
}
@ApiOperation("撤回消息")
@PostMapping("/retractMessage")
public AjaxResult retractMessage(@RequestParam String batchId ,@RequestParam Long userId) {
if (!userId.equals(getUserId())){
return AjaxResult.error("您无权撤回该消息");
}
return AjaxResult.success(chatService.retractMessage(batchId));
}
}

View File

@ -12,6 +12,7 @@ import com.ruoyi.bst.teamUser.domain.TeamUser;
import com.ruoyi.bst.teamUser.domain.TeamUserQuery;
import com.ruoyi.bst.teamUser.domain.TeamUserVO;
import com.ruoyi.bst.teamUser.domain.enums.RoleType;
import com.ruoyi.bst.teamUser.domain.enums.TeamUserStatus;
import com.ruoyi.bst.teamUser.service.TeamUserAssembler;
import com.ruoyi.bst.teamUser.service.TeamUserConverter;
import com.ruoyi.bst.teamUser.service.TeamUserService;
@ -22,6 +23,7 @@ import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.sun.org.apache.bcel.internal.generic.I2F;
import io.swagger.annotations.ApiOperation;
import org.apache.ibatis.cache.CacheKey;
import org.springframework.beans.factory.annotation.Autowired;
@ -95,10 +97,7 @@ public class AppTeamController extends BaseController {
TeamUserQuery query = new TeamUserQuery();
query.setTeamId(teamId);
query.setRole(RoleType.CREATOR.getCode());
TeamUserVO vo = teamUserService.selectOne(query);
if (vo == null) {
return AjaxResult.error("该拼桌不存在");
}
TeamUserVO vo = teamUserService.getTeamUser(query);
if (!vo.getUserId().equals(getUserId())) {
return AjaxResult.error("该拼桌不属于您,您无权解散");
}
@ -110,7 +109,7 @@ public class AppTeamController extends BaseController {
public AjaxResult invCode(@RequestBody InvitedDTO dto) {
String uuid = IdUtils.simpleUUID();
String verifyKey = CacheConstants.TABLE_SHARING_INVITATION_KEY + uuid;
redisCache.setCacheObject(verifyKey, dto, 15, TimeUnit.MINUTES);
redisCache.setCacheObject(verifyKey, dto, 5, TimeUnit.MINUTES);
return AjaxResult.success(uuid);
}
@ -133,16 +132,22 @@ public class AppTeamController extends BaseController {
@GetMapping("/getTeamInfo")
public AjaxResult getTeamInfo(TeamQuery query) {
query.setStatus(TeamStatus.NORMAL.getCode());
TeamVO vo = teamService.selectOne(query);
if (vo == null) {
return AjaxResult.error("该拼桌不存在或已解散");
}
return AjaxResult.success(vo);
return AjaxResult.success(teamService.getTeamInfo(query));
}
@ApiOperation("修改拼桌基础信息")
@PutMapping("/updateBasicInfo")
public AjaxResult updateBasicInfo(@RequestBody Team team) {
public AjaxResult updateBasicInfo(@RequestBody Team team,@RequestParam Long userId) {
// 条件查询用户角色
TeamUserQuery query = new TeamUserQuery();
query.setTeamId(team.getId());
query.setRole(RoleType.CREATOR.getCode());
query.setStatus(TeamUserStatus.JOINED.getCode());
TeamUserVO vo = teamUserService.selectOne(query);
// 权限校验
if (!vo.getUserId().equals(userId)) {
return AjaxResult.error("您无权限修改当前拼桌信息");
}
Team po = teamConverter.toPoByUpdate(team);
return AjaxResult.success(teamService.updateTeam(po));
}

View File

@ -4,7 +4,12 @@ import com.ruoyi.bst.storeStaff.domain.enums.StoreStaffPermission;
import com.ruoyi.bst.team.domain.Team;
import com.ruoyi.bst.team.domain.TeamQuery;
import com.ruoyi.bst.team.domain.TeamVO;
import com.ruoyi.bst.team.service.TeamAssembler;
import com.ruoyi.bst.team.service.TeamService;
import com.ruoyi.bst.teamUser.domain.TeamUserQuery;
import com.ruoyi.bst.teamUser.domain.TeamUserVO;
import com.ruoyi.bst.teamUser.domain.enums.RoleType;
import com.ruoyi.bst.teamUser.service.TeamUserAssembler;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
@ -12,6 +17,7 @@ import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.validate.ValidGroup;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
@ -32,6 +38,10 @@ public class TeamController extends BaseController
{
@Autowired
private TeamService teamService;
@Autowired
private TeamUserAssembler teamUserAssembler;
@Autowired
private TeamAssembler teamAssembler;
/**
* 查询拼桌列表
@ -45,6 +55,7 @@ public class TeamController extends BaseController
query.setScope(true);
query.addStorePermission(StoreStaffPermission.TEAM_VIEW.getCode());
List<TeamVO> list = teamService.selectTeamList(query);
teamAssembler.assembleSponsor(list);
return getDataTable(list);
}
@ -104,4 +115,12 @@ public class TeamController extends BaseController
{
return toAjax(teamService.deleteTeamByIds(ids));
}
@PreAuthorize("@ss.hasPermi('bst:team:forcedDis')")
@Log(title = "强制解散队伍", businessType = BusinessType.OTHER)
@PutMapping("/forcedDis")
public AjaxResult forcedDis(@RequestParam Long teamId) {
return toAjax(teamService.disTeam(teamId));
}
}

View File

@ -1,5 +1,6 @@
package com.ruoyi.web.bst;
import com.ruoyi.bst.storeStaff.domain.enums.StoreStaffPermission;
import com.ruoyi.bst.teamUser.domain.TeamUser;
import com.ruoyi.bst.teamUser.domain.TeamUserQuery;
import com.ruoyi.bst.teamUser.domain.TeamUserVO;
@ -39,6 +40,8 @@ public class TeamUserController extends BaseController
{
startPage();
startOrderBy();
query.setScope(true);
query.addStorePermission(StoreStaffPermission.TEAM_USER_VIEW.getCode());
List<TeamUserVO> list = teamUserService.selectTeamUserList(query);
return getDataTable(list);
}
@ -98,4 +101,11 @@ public class TeamUserController extends BaseController
{
return toAjax(teamUserService.deleteTeamUserByIds(ids));
}
@PreAuthorize("@ss.hasPermi('bst:teamUser:kick')")
@Log(title = "踢出用户", businessType = BusinessType.OTHER)
@PutMapping("/kick")
public AjaxResult kick(@RequestParam Long teamId, @RequestParam Long userId) {
return toAjax(teamUserService.kick(teamId, userId));
}
}