feat: 关注工单支持收藏夹

This commit is contained in:
曹鹏飞 2025-03-02 10:00:30 +08:00
parent 0112f267e3
commit 7684461953
17 changed files with 325 additions and 37 deletions

View File

@ -96,6 +96,9 @@ public class TicketController extends ControllerBase {
@Resource @Resource
private RedisTemplate<String, String> redisTemplate; private RedisTemplate<String, String> redisTemplate;
@Resource
private ITicketFavoritesService ticketFavoritesService;
/** /**
* 获取问题类型 * 获取问题类型
* @return 问题类型列表 * @return 问题类型列表
@ -107,13 +110,58 @@ public class TicketController extends ControllerBase {
} }
/** /**
* 关注或取消关注工单 * 获取收藏夹
* @param id 收藏夹id0为根节点
* @return 收藏夹信息
*/
@GetMapping("getFavorites")
@ApiMark(moduleName = "工单管理", apiName = "获取收藏夹",isPublic = true)
public ApiResult<FavoritesVO> getFavorites(@RequestParam(defaultValue ="0") Integer id){
return ApiResult.success(ticketFavoritesService.getList(AdminUserUtil.getUserId(),id));
}
/**
* 添加收藏夹
* @param request 请求信息
* @return
*/
@PostMapping("addFavorites")
@ApiMark(moduleName = "工单管理", apiName = "添加收藏夹",isPublic = true)
public ApiResult<Void> addFavorites(@Valid @RequestBody AdminFavoritesRequest request){
ticketFavoritesService.addFavorites(request,AdminUserUtil.getUserId());
return ApiResult.success();
}
/**
* 删除收藏夹
* @param favoritesId 收藏夹id
* @return
*/
@PostMapping("deleteFavorites")
@ApiMark(moduleName = "工单管理", apiName = "删除收藏夹",isPublic = true)
public ApiResult<Void> deleteFavorites(@Valid @RequestParam @NotNull Integer favoritesId){
ticketFavoritesService.deleteFavorites(AdminUserUtil.getUserId(),favoritesId);
return ApiResult.success();
}
/**
* 关注工单
* @param request 请求信息 * @param request 请求信息
**/ **/
@PostMapping("followTiket") @PostMapping("followTiket")
@ApiMark(moduleName = "工单管理", apiName = "关注或取消关注") @ApiMark(moduleName = "工单管理", apiName = "关注工单")
public ApiResult<Void> followTiket(@Valid @RequestBody FollowRequest request) { public ApiResult<Void> followTiket(@Valid @RequestBody AdminFollowRequest request){
ticketFollowService.handleAdmin(request, AdminUserUtil.getUserId()); ticketFollowService.follow(request, AdminUserUtil.getUserId());
return ApiResult.success();
}
/**
* 取消关注工单
* @param ticketId 工单id
**/
@PostMapping("unfollowTicket")
public ApiResult<Void> unfollowTicket(@Valid @RequestParam @NotNull Integer ticketId){
ticketFollowService.unfollow(AdminUserUtil.getUserId(),ticketId);
return ApiResult.success(); return ApiResult.success();
} }

View File

@ -0,0 +1,18 @@
package com.nflg.mobilebroken.common.pojo.request;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@Data
public class AdminFavoritesRequest {
//父级id
@NotNull
private Integer parentId;
//名称
@NotBlank
private String name;
}

View File

@ -0,0 +1,17 @@
package com.nflg.mobilebroken.common.pojo.request;
import lombok.Data;
import javax.validation.constraints.NotNull;
@Data
public class AdminFollowRequest {
//工单id
@NotNull(message = "工单id不能为空")
private Integer ticketId;
//收藏夹id
@NotNull(message = "收藏夹id不能为空")
private Integer favoritesId;
}

View File

@ -0,0 +1,23 @@
package com.nflg.mobilebroken.common.pojo.vo;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
@Data
@Accessors(chain = true)
public class FavoritesVO {
//收藏夹id
private Integer id;
//收藏夹名称
private String name;
//子收藏夹
private List<FavoritesVO> children;
//工单
private List<TicketVO> tickets;
}

View File

@ -0,0 +1,51 @@
package com.nflg.mobilebroken.repository.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* <p>
*
* </p>
*
* @author 代码生成器生成
* @since 2025
*/
@Getter
@Setter
@Accessors(chain = true)
@TableName("ticket_favorites")
public class TicketFavorites implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
/**
* 上级id
*/
private Integer parentId;
/**
* 名称
*/
private String name;
/**
* 创建人
*/
private Integer createBy;
/**
* 创建时间
*/
private LocalDateTime createTime;
}

View File

@ -40,6 +40,11 @@ public class TicketFollow implements Serializable {
*/ */
private Integer userId; private Integer userId;
/**
* 收藏夹id
*/
private Integer favoritesId;
/** /**
* 来源0用户端1管理端 * 来源0用户端1管理端
*/ */

View File

@ -0,0 +1,16 @@
package com.nflg.mobilebroken.repository.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.nflg.mobilebroken.repository.entity.TicketFavorites;
/**
* <p>
* Mapper 接口
* </p>
*
* @author 代码生成器生成
* @since 2025
*/
public interface TicketFavoritesMapper extends BaseMapper<TicketFavorites> {
}

View File

@ -35,4 +35,6 @@ public interface TicketMapper extends BaseMapper<Ticket> {
IPage<AdminTicketVO> searchFromAdminAndFollow(AdminTicketSearchRequest request, Integer userId, IPage<?> page); IPage<AdminTicketVO> searchFromAdminAndFollow(AdminTicketSearchRequest request, Integer userId, IPage<?> page);
List<AdminTicketVO> searchAllFromAdminAndFollow(AdminTicketSearchRequest request, Integer userId); List<AdminTicketVO> searchAllFromAdminAndFollow(AdminTicketSearchRequest request, Integer userId);
List<TicketVO> getAdminFavorites(Integer favoritesId);
} }

View File

@ -0,0 +1,23 @@
package com.nflg.mobilebroken.repository.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.nflg.mobilebroken.common.pojo.request.AdminFavoritesRequest;
import com.nflg.mobilebroken.common.pojo.vo.FavoritesVO;
import com.nflg.mobilebroken.repository.entity.TicketFavorites;
/**
* <p>
* 服务类
* </p>
*
* @author 代码生成器生成
* @since 2025
*/
public interface ITicketFavoritesService extends IService<TicketFavorites> {
FavoritesVO getList(Integer userId,Integer id);
void addFavorites(AdminFavoritesRequest request, Integer userId);
void deleteFavorites(Integer userId,Integer favoritesId);
}

View File

@ -1,11 +1,10 @@
package com.nflg.mobilebroken.repository.service; package com.nflg.mobilebroken.repository.service;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import com.nflg.mobilebroken.common.pojo.request.AdminFollowRequest;
import com.nflg.mobilebroken.common.pojo.request.FollowRequest; import com.nflg.mobilebroken.common.pojo.request.FollowRequest;
import com.nflg.mobilebroken.repository.entity.TicketFollow; import com.nflg.mobilebroken.repository.entity.TicketFollow;
import java.util.List;
/** /**
* <p> * <p>
* 工单-关注 服务类 * 工单-关注 服务类
@ -18,7 +17,9 @@ public interface ITicketFollowService extends IService<TicketFollow> {
void handle(FollowRequest request, Integer userId); void handle(FollowRequest request, Integer userId);
List<TicketFollow> getUsers(Integer id); void follow(AdminFollowRequest request, Integer userId);
void handleAdmin(FollowRequest request, Integer userId); void unfollow(Integer userId, Integer ticketId);
void deleteFavorites(Integer userId, Integer favoritesId);
} }

View File

@ -50,4 +50,6 @@ public interface ITicketService extends IService<Ticket> {
List<Ticket> getNonComment(int days); List<Ticket> getNonComment(int days);
List<AdminUserSimpleVO> getTicketHandle(Integer id); List<AdminUserSimpleVO> getTicketHandle(Integer id);
List<TicketVO> getAdminFavorites(Integer favoritesId);
} }

View File

@ -0,0 +1,65 @@
package com.nflg.mobilebroken.repository.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nflg.mobilebroken.common.pojo.request.AdminFavoritesRequest;
import com.nflg.mobilebroken.common.pojo.vo.FavoritesVO;
import com.nflg.mobilebroken.common.util.VUtils;
import com.nflg.mobilebroken.repository.entity.TicketFavorites;
import com.nflg.mobilebroken.repository.mapper.TicketFavoritesMapper;
import com.nflg.mobilebroken.repository.service.ITicketFavoritesService;
import com.nflg.mobilebroken.repository.service.ITicketFollowService;
import com.nflg.mobilebroken.repository.service.ITicketService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* <p>
* 服务实现类
* </p>
*
* @author 代码生成器生成
* @since 2025
*/
@Service
public class TicketFavoritesServiceImpl extends ServiceImpl<TicketFavoritesMapper, TicketFavorites> implements ITicketFavoritesService {
@Resource
private ITicketService ticketService;
@Resource
private ITicketFollowService ticketFollowService;
@Override
public FavoritesVO getList(Integer userId,Integer id) {
TicketFavorites favorites= Objects.equals(id, 0)? new TicketFavorites().setId(0).setName("收藏夹") : lambdaQuery().eq(TicketFavorites::getId,id).one();
FavoritesVO vo=new FavoritesVO().setId(favorites.getId()).setName(favorites.getName());
vo.setChildren(lambdaQuery().eq(TicketFavorites::getParentId,id).eq(TicketFavorites::getCreateBy,userId).list()
.stream().map(f->new FavoritesVO().setId(f.getId()).setName(f.getName())).collect(Collectors.toList()));
vo.setTickets(ticketService.getAdminFavorites(id));
return vo;
}
@Override
public void addFavorites(AdminFavoritesRequest request, Integer userId) {
VUtils.trueThrowBusinessError(lambdaQuery().eq(TicketFavorites::getParentId,request.getParentId()).eq(TicketFavorites::getName,request.getName()).exists())
.throwMessage("已存在该名称的收藏夹");
save(new TicketFavorites().setParentId(request.getParentId()).setName(request.getName()).setCreateBy(userId).setCreateTime(LocalDateTime.now()));
}
@Transactional
@Override
public void deleteFavorites(Integer userId, Integer favoritesId) {
TicketFavorites favorites = lambdaQuery().eq(TicketFavorites::getId, favoritesId).one();
VUtils.trueThrowBusinessError(Objects.isNull(favorites)).throwMessage("该收藏夹不存在");
VUtils.trueThrowBusinessError(!Objects.equals(favorites.getCreateBy(), userId)).throwMessage("无权限删除该收藏夹");
ticketFollowService.deleteFavorites(userId, favoritesId);
if (!Objects.equals(favoritesId, 0)){
lambdaUpdate().eq(TicketFavorites::getId,favoritesId).remove();
}
}
}

View File

@ -2,14 +2,15 @@ package com.nflg.mobilebroken.repository.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nflg.mobilebroken.common.pojo.request.AdminFollowRequest;
import com.nflg.mobilebroken.common.pojo.request.FollowRequest; import com.nflg.mobilebroken.common.pojo.request.FollowRequest;
import com.nflg.mobilebroken.repository.entity.TicketFollow; import com.nflg.mobilebroken.repository.entity.TicketFollow;
import com.nflg.mobilebroken.repository.mapper.TicketFollowMapper; import com.nflg.mobilebroken.repository.mapper.TicketFollowMapper;
import com.nflg.mobilebroken.repository.service.ITicketFollowService; import com.nflg.mobilebroken.repository.service.ITicketFollowService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects; import java.util.Objects;
/** /**
@ -48,35 +49,35 @@ public class TicketFollowServiceImpl extends ServiceImpl<TicketFollowMapper, Tic
} }
} }
@Transactional
@Override @Override
public List<TicketFollow> getUsers(Integer id) { public void follow(AdminFollowRequest request, Integer userId) {
return lambdaQuery() this.remove(new LambdaQueryWrapper<TicketFollow>()
.eq(TicketFollow::getTicketId, id) .eq(TicketFollow::getTicketId, request.getTicketId())
.list(); .eq(TicketFollow::getUserId, userId)
.eq(TicketFollow::getFrom, (byte) 1));
TicketFollow ticketFollow = new TicketFollow()
.setTicketId(request.getTicketId())
.setUserId(userId)
.setFavoritesId(request.getFavoritesId())
.setFrom((byte) 1)
.setCreateTime(LocalDateTime.now());
save(ticketFollow);
} }
@Override @Override
public void handleAdmin(FollowRequest request, Integer userId) { public void unfollow(Integer userId, Integer ticketId) {
if (request.getIsFollow()) { this.remove(new LambdaQueryWrapper<TicketFollow>()
TicketFollow ticketFollow = lambdaQuery() .eq(TicketFollow::getTicketId, ticketId)
.eq(TicketFollow::getTicketId, request.getTicketId()) .eq(TicketFollow::getUserId, userId)
.eq(TicketFollow::getUserId, userId) .eq(TicketFollow::getFrom, (byte) 1));
.eq(TicketFollow::getFrom, (byte) 1) }
.one();
if (Objects.isNull(ticketFollow)) { @Override
TicketFollow follow = new TicketFollow() public void deleteFavorites(Integer userId, Integer favoritesId) {
.setTicketId(request.getTicketId()) this.remove(new LambdaQueryWrapper<TicketFollow>()
.setUserId(userId) .eq(TicketFollow::getFavoritesId, favoritesId)
.setFrom((byte) 1) .eq(TicketFollow::getUserId, userId)
.setCreateTime(LocalDateTime.now()); .eq(TicketFollow::getFrom, (byte) 1));
save(follow);
}
} else {
LambdaQueryWrapper<TicketFollow> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(TicketFollow::getTicketId, request.getTicketId());
lambdaQueryWrapper.eq(TicketFollow::getUserId, userId);
lambdaQueryWrapper.eq(TicketFollow::getFrom, (byte) 1);
this.remove(lambdaQueryWrapper);
}
} }
} }

View File

@ -302,4 +302,9 @@ public class TicketServiceImpl extends ServiceImpl<TicketMapper, Ticket> impleme
List<Integer> handles=Arrays.stream(ticket.getHandle().split(",")).map(Integer::parseInt).collect(Collectors.toList()); List<Integer> handles=Arrays.stream(ticket.getHandle().split(",")).map(Integer::parseInt).collect(Collectors.toList());
return adminUserService.getSimples(handles); return adminUserService.getSimples(handles);
} }
@Override
public List<TicketVO> getAdminFavorites(Integer favoritesId) {
return baseMapper.getAdminFavorites(favoritesId);
}
} }

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.nflg.mobilebroken.repository.mapper.TicketFavoritesMapper">
</mapper>

View File

@ -213,4 +213,11 @@
<include refid="adminSearchWhereCondition"/> <include refid="adminSearchWhereCondition"/>
ORDER BY t.id DESC ORDER BY t.id DESC
</select> </select>
<select id="getAdminFavorites" resultType="com.nflg.mobilebroken.common.pojo.vo.TicketVO">
SELECT t.id,t.no,t.title
FROM ticket_follow tf
INNER JOIN ticket t ON tf.ticket_id=t.id
WHERE tf.`from`=1 AND tf.favorites_id=#{favoritesId}
</select>
</mapper> </mapper>

View File

@ -33,13 +33,12 @@ public class CodeGenerator {
, Paths.get(System.getProperty("user.dir")) + "/src/main/resources/mapper")) , Paths.get(System.getProperty("user.dir")) + "/src/main/resources/mapper"))
) )
.strategyConfig(builder -> { .strategyConfig(builder -> {
builder.addInclude("aaa") //只生成指定表 builder.addInclude("ticket_favorites") //只生成指定表
.entityBuilder() .entityBuilder()
.enableLombok() .enableLombok()
.enableChainModel() .enableChainModel()
.enableFileOverride(); .enableFileOverride();
builder.controllerBuilder().disable(); builder.controllerBuilder().disable();
builder.addExclude("admin_menu");
}) })
.templateEngine(new FreemarkerTemplateEngine()) .templateEngine(new FreemarkerTemplateEngine())
.execute(); .execute();