This commit is contained in:
zc
2026-03-03 11:42:23 +08:00
parent 3892fffa37
commit 7e7db23d82
48 changed files with 149 additions and 2099 deletions

View File

@@ -106,7 +106,7 @@ public abstract class AbstractLoginHandler<T extends LoginReq> implements LoginH
*/
protected void checkUserStatus(UserDO user) {
CheckUtils.throwIfEqual(DisEnableStatusEnum.DISABLE, user.getStatus(), "此账号已被禁用,如有疑问,请联系管理员");
DeptDO dept = deptService.getById(user.getDeptId());
CheckUtils.throwIfEqual(DisEnableStatusEnum.DISABLE, dept.getStatus(), "此账号所属部门已被禁用,如有疑问,请联系管理员");
// DeptDO dept = deptService.getById(user.getDeptId());
// CheckUtils.throwIfEqual(DisEnableStatusEnum.DISABLE, dept.getStatus(), "此账号所属部门已被禁用,如有疑问,请联系管理员");
}
}

View File

@@ -34,7 +34,12 @@ public enum AuthTypeEnum implements BaseEnum<String> {
/**
* 第三方账号
*/
SOCIAL("SOCIAL", "第三方账号", UiConstants.COLOR_ERROR);
SOCIAL("SOCIAL", "第三方账号", UiConstants.COLOR_ERROR),
/**
* 卡号
*/
CARD("CARD", "卡号", UiConstants.COLOR_PRIMARY);
private final String value;
private final String description;

View File

@@ -0,0 +1,43 @@
package top.wms.admin.auth.handler;
import jakarta.servlet.http.HttpServletRequest;
import top.continew.starter.cache.redisson.util.RedisUtils;
import top.continew.starter.core.validation.ValidationUtils;
import top.wms.admin.auth.AbstractLoginHandler;
import top.wms.admin.auth.enums.AuthTypeEnum;
import top.wms.admin.auth.model.req.CardLoginReq;
import top.wms.admin.auth.model.req.PhoneLoginReq;
import top.wms.admin.auth.model.resp.LoginResp;
import top.wms.admin.common.constant.CacheConstants;
import top.wms.admin.system.model.entity.UserDO;
import top.wms.admin.system.model.resp.ClientResp;
public class CardLoginHandler extends AbstractLoginHandler<CardLoginReq> {
@Override
public LoginResp login(CardLoginReq req, ClientResp client, HttpServletRequest request) {
// 验证手机号
UserDO user = userService.getByCard(req.getCardNumber());
ValidationUtils.throwIfNull(user, "此手机号未绑定本系统账号");
// 检查用户状态
super.checkUserStatus(user);
// 执行认证
String token = super.authenticate(user, client);
return LoginResp.builder().token(token).build();
}
@Override
public void preLogin(PhoneLoginReq req, ClientResp client, HttpServletRequest request) {
String phone = req.getPhone();
String captchaKey = CacheConstants.CAPTCHA_KEY_PREFIX + phone;
String captcha = RedisUtils.get(captchaKey);
ValidationUtils.throwIfBlank(captcha, CAPTCHA_EXPIRED);
ValidationUtils.throwIfNotEqualIgnoreCase(req.getCaptcha(), captcha, CAPTCHA_ERROR);
RedisUtils.delete(captchaKey);
}
@Override
public AuthTypeEnum getAuthType() {
return AuthTypeEnum.PHONE;
}
}

View File

@@ -2,7 +2,6 @@ package top.wms.admin.auth.handler;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.ReUtil;
@@ -23,24 +22,18 @@ import top.wms.admin.common.constant.RegexConstants;
import top.wms.admin.common.constant.SysConstants;
import top.wms.admin.common.enums.DisEnableStatusEnum;
import top.wms.admin.common.enums.GenderEnum;
import top.wms.admin.system.enums.MessageTemplateEnum;
import top.wms.admin.system.enums.MessageTypeEnum;
import top.wms.admin.system.model.entity.RoleDO;
import top.wms.admin.system.model.entity.UserDO;
import top.wms.admin.system.model.entity.UserSocialDO;
import top.wms.admin.system.model.req.MessageReq;
import top.wms.admin.system.model.resp.ClientResp;
import top.wms.admin.system.service.MessageService;
import top.wms.admin.system.service.UserRoleService;
import top.wms.admin.system.service.UserSocialService;
import top.continew.starter.core.autoconfigure.project.ProjectProperties;
import top.continew.starter.core.exception.BadRequestException;
import top.continew.starter.core.validation.ValidationUtils;
import top.continew.starter.messaging.websocket.util.WebSocketUtils;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
/**
* 第三方账号登录处理器
@@ -56,7 +49,6 @@ public class SocialLoginHandler extends AbstractLoginHandler<SocialLoginReq> {
private final AuthRequestFactory authRequestFactory;
private final UserSocialService userSocialService;
private final UserRoleService userRoleService;
private final MessageService messageService;
private final ProjectProperties projectProperties;
@Override
@@ -76,21 +68,15 @@ public class SocialLoginHandler extends AbstractLoginHandler<SocialLoginReq> {
UserDO user;
if (null == userSocial) {
String username = authUser.getUsername();
String nickname = authUser.getNickname();
UserDO existsUser = userService.getByUsername(username);
String randomStr = RandomUtil.randomString(RandomUtil.BASE_CHAR, 5);
if (null != existsUser || !ReUtil.isMatch(RegexConstants.USERNAME, username)) {
username = randomStr + IdUtil.fastSimpleUUID();
}
if (!ReUtil.isMatch(RegexConstants.GENERAL_NAME, nickname)) {
nickname = source.toLowerCase() + randomStr;
}
user = new UserDO();
user.setUsername(username);
user.setNickname(nickname);
user.setGender(GenderEnum.valueOf(authUser.getGender().name()));
user.setAvatar(authUser.getAvatar());
user.setDeptId(SysConstants.SUPER_DEPT_ID);
user.setStatus(DisEnableStatusEnum.ENABLE);
userService.save(user);
Long userId = user.getId();
@@ -100,7 +86,6 @@ public class SocialLoginHandler extends AbstractLoginHandler<SocialLoginReq> {
userSocial.setUserId(userId);
userSocial.setSource(source);
userSocial.setOpenId(openId);
this.sendSecurityMsg(user);
} else {
user = BeanUtil.copyProperties(userService.getById(userSocial.getUserId()), UserDO.class);
}
@@ -141,21 +126,4 @@ public class SocialLoginHandler extends AbstractLoginHandler<SocialLoginReq> {
}
}
/**
* 发送安全消息
*
* @param user 用户信息
*/
private void sendSecurityMsg(UserDO user) {
MessageReq req = new MessageReq();
MessageTemplateEnum socialRegister = MessageTemplateEnum.SOCIAL_REGISTER;
req.setTitle(socialRegister.getTitle().formatted(projectProperties.getName()));
req.setContent(socialRegister.getContent().formatted(user.getNickname()));
req.setType(MessageTypeEnum.SECURITY);
messageService.add(req, CollUtil.toList(user.getId()));
List<String> tokenList = StpUtil.getTokenValueListByLoginId(user.getId());
for (String token : tokenList) {
WebSocketUtils.sendMessage(token, "1");
}
}
}

View File

@@ -0,0 +1,30 @@
package top.wms.admin.auth.model.req;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import java.io.Serial;
/**
* 卡号登录参数
*
* @author KAI
* @author Charles7c
* @since 2024/12/25 15:43
*/
@Data
@Schema(description = "卡号登录参数")
public class CardLoginReq extends LoginReq {
@Serial
private static final long serialVersionUID = 1L;
/**
* 卡号
*/
@Schema(description = "卡号", example = "1234567890")
@NotBlank(message = "卡号不能为空")
private String cardNumber;
}

View File

@@ -23,7 +23,8 @@ import java.io.Serializable;
@JsonSubTypes({@JsonSubTypes.Type(value = AccountLoginReq.class, name = "ACCOUNT"),
@JsonSubTypes.Type(value = EmailLoginReq.class, name = "EMAIL"),
@JsonSubTypes.Type(value = PhoneLoginReq.class, name = "PHONE"),
@JsonSubTypes.Type(value = SocialLoginReq.class, name = "SOCIAL")})
@JsonSubTypes.Type(value = SocialLoginReq.class, name = "SOCIAL"),
@JsonSubTypes.Type(value = CardLoginReq.class, name = "CARD")})
@Schema(description = "基础登录参数")
public class LoginReq implements Serializable {

View File

@@ -1,20 +1,14 @@
package top.wms.admin.system.mapper;
import com.alicp.jetcache.anno.Cached;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import top.wms.admin.common.constant.CacheConstants;
import top.wms.admin.system.model.entity.LogDO;
import top.wms.admin.system.model.resp.dashboard.DashboardAccessTrendResp;
import top.wms.admin.system.model.resp.dashboard.DashboardChartCommonResp;
import top.wms.admin.system.model.resp.dashboard.DashboardOverviewCommonResp;
import top.wms.admin.system.model.resp.log.LogResp;
import top.continew.starter.data.mp.base.BaseMapper;
import java.util.Date;
import java.util.List;
/**
@@ -51,83 +45,4 @@ public interface LogMapper extends BaseMapper<LogDO> {
@Select("SELECT COUNT(*) FROM sys_log")
Long selectTotalCount();
/**
* 查询仪表盘 PV 总览
*
* @return 仪表盘 PV 总览
*/
DashboardOverviewCommonResp selectDashboardOverviewPv();
/**
* 查询仪表盘 IP 总览
*
* @return 仪表盘 IP 总览
*/
DashboardOverviewCommonResp selectDashboardOverviewIp();
/**
* 查询仪表盘 PV 近 N 月各月份信息
*
* @param months 近 N 月月份列表
* @return 仪表盘 PV 近 N 月各月份信息
*/
@Cached(key = "#months[0]", name = CacheConstants.DASHBOARD_KEY_PREFIX + "PV:")
List<DashboardChartCommonResp> selectListDashboardAnalysisPv(@Param("months") List<String> months);
/**
* 查询仪表盘 IP 近 N 月各月份信息
*
* @param months 近 N 月月份列表
* @return 仪表盘 IP 近 N 月各月份信息
*/
@Cached(key = "#months[0]", name = CacheConstants.DASHBOARD_KEY_PREFIX + "IP:")
List<DashboardChartCommonResp> selectListDashboardAnalysisIp(@Param("months") List<String> months);
/**
* 查询仪表盘地域分析信息
*
* @return 仪表盘地域分析信息
*/
List<DashboardChartCommonResp> selectListDashboardAnalysisGeo();
/**
* 查询仪表盘访问趋势信息
*
* @param startTime 开始时间
* @param endTime 结束时间
* @return 仪表盘访问趋势信息
*/
List<DashboardAccessTrendResp> selectListDashboardAccessTrend(@Param("startTime") Date startTime,
@Param("endTime") Date endTime);
/**
* 查询仪表盘访问时段分析信息
*
* @return 仪表盘访问时段分析信息
*/
List<DashboardChartCommonResp> selectListDashboardAnalysisTimeslot();
/**
* 查询仪表盘模块分析信息
*
* @param top 显示数量
* @return 仪表盘模块分析信息
*/
List<DashboardChartCommonResp> selectListDashboardAnalysisModule(@Param("top") Integer top);
/**
* 查询仪表盘终端分析信息
*
* @param top 显示数量
* @return 仪表盘终端分析信息
*/
List<DashboardChartCommonResp> selectListDashboardAnalysisOs(@Param("top") Integer top);
/**
* 查询仪表盘浏览器分析信息
*
* @param top 显示数量
* @return 仪表盘浏览器分析信息
*/
List<DashboardChartCommonResp> selectListDashboardAnalysisBrowser(@Param("top") Integer top);
}

View File

@@ -1,28 +0,0 @@
package top.wms.admin.system.mapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import org.apache.ibatis.annotations.Param;
import top.wms.admin.system.model.entity.MessageDO;
import top.wms.admin.system.model.resp.message.MessageResp;
import top.continew.starter.data.mp.base.BaseMapper;
/**
* 消息 Mapper
*
* @author Bull-BCLS
* @since 2023/10/15 19:05
*/
public interface MessageMapper extends BaseMapper<MessageDO> {
/**
* 分页查询列表
*
* @param page 分页查询条件
* @param queryWrapper 查询条件
* @return 分页信息
*/
IPage<MessageResp> selectPageByUserId(@Param("page") IPage<Object> page,
@Param(Constants.WRAPPER) QueryWrapper<MessageDO> queryWrapper);
}

View File

@@ -1,23 +0,0 @@
package top.wms.admin.system.mapper;
import org.apache.ibatis.annotations.Param;
import top.wms.admin.system.model.entity.MessageUserDO;
import top.continew.starter.data.mp.base.BaseMapper;
/**
* 消息和用户 Mapper
*
* @author Bull-BCLS
* @since 2023/10/15 20:25
*/
public interface MessageUserMapper extends BaseMapper<MessageUserDO> {
/**
* 根据用户 ID 和消息类型查询未读消息数量
*
* @param userId 用户 ID
* @param type 消息类型
* @return 未读消息信息
*/
Long selectUnreadCountByUserIdAndType(@Param("userId") Long userId, @Param("type") Integer type);
}

View File

@@ -1,25 +0,0 @@
package top.wms.admin.system.mapper;
import org.apache.ibatis.annotations.Param;
import top.wms.admin.system.model.entity.NoticeDO;
import top.wms.admin.system.model.resp.dashboard.DashboardNoticeResp;
import top.continew.starter.data.mp.base.BaseMapper;
import java.util.List;
/**
* 公告 Mapper
*
* @author Charles7c
* @since 2023/8/20 10:55
*/
public interface NoticeMapper extends BaseMapper<NoticeDO> {
/**
* 查询仪表盘公告列表
*
* @param userId 用户 ID
* @return 仪表盘公告列表
*/
List<DashboardNoticeResp> selectDashboardList(@Param("userId") Long userId);
}

View File

@@ -1,59 +0,0 @@
package top.wms.admin.system.model.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import top.wms.admin.system.enums.MessageTypeEnum;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 消息实体
*
* @author Bull-BCLS
* @since 2023/10/15 19:05
*/
@Data
@TableName("sys_message")
public class MessageDO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* ID
*/
@TableId
private Long id;
/**
* 标题
*/
private String title;
/**
* 内容
*/
private String content;
/**
* 类型1系统消息
*/
private MessageTypeEnum type;
/**
* 创建人
*/
@TableField(fill = FieldFill.INSERT)
private Long createUser;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
}

View File

@@ -1,42 +0,0 @@
package top.wms.admin.system.model.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 消息和用户关联实体
*
* @author Bull-BCLS
* @since 2023/10/15 20:25
*/
@Data
@TableName("sys_message_user")
public class MessageUserDO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 消息 ID
*/
private Long messageId;
/**
* 用户 ID
*/
private Long userId;
/**
* 是否已读
*/
private Boolean isRead;
/**
* 读取时间
*/
private LocalDateTime readTime;
}

View File

@@ -1,62 +0,0 @@
package top.wms.admin.system.model.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import lombok.Data;
import top.wms.admin.common.model.entity.BaseDO;
import top.wms.admin.system.enums.NoticeScopeEnum;
import java.io.Serial;
import java.time.LocalDateTime;
import java.util.List;
/**
* 公告实体
*
* @author Charles7c
* @since 2023/8/20 10:55
*/
@Data
@TableName(value = "sys_notice", autoResultMap = true)
public class NoticeDO extends BaseDO {
@Serial
private static final long serialVersionUID = 1L;
/**
* 标题
*/
private String title;
/**
* 内容
*/
private String content;
/**
* 类型
*/
private String type;
/**
* 生效时间
*/
private LocalDateTime effectiveTime;
/**
* 终止时间
*/
private LocalDateTime terminateTime;
/**
* 通知范围
*/
private NoticeScopeEnum noticeScope;
/**
* 通知用户
*/
@TableField(typeHandler = JacksonTypeHandler.class)
private List<String> noticeUsers;
}

View File

@@ -1,58 +0,0 @@
package top.wms.admin.system.model.query;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import top.wms.admin.system.enums.MessageTypeEnum;
import top.continew.starter.data.core.annotation.Query;
import top.continew.starter.data.core.annotation.QueryIgnore;
import top.continew.starter.data.core.enums.QueryType;
import java.io.Serial;
import java.io.Serializable;
/**
* 消息查询条件
*
* @author Bull-BCLS
* @since 2023/10/15 19:05
*/
@Data
@Schema(description = "消息查询条件")
public class MessageQuery implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* ID
*/
@Schema(description = "ID", example = "1")
private Long id;
/**
* 标题
*/
@Schema(description = "标题", example = "欢迎注册 xxx")
@Query(type = QueryType.LIKE)
private String title;
/**
* 类型
*/
@Schema(description = "类型", example = "1")
private MessageTypeEnum type;
/**
* 是否已读
*/
@Schema(description = "是否已读", example = "true")
@QueryIgnore
private Boolean isRead;
/**
* 用户 ID
*/
@Schema(hidden = true)
@QueryIgnore
private Long userId;
}

View File

@@ -1,36 +0,0 @@
package top.wms.admin.system.model.query;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import top.continew.starter.data.core.annotation.Query;
import top.continew.starter.data.core.enums.QueryType;
import java.io.Serial;
import java.io.Serializable;
/**
* 公告查询条件
*
* @author Charles7c
* @since 2023/8/20 10:55
*/
@Data
@Schema(description = "公告查询条件")
public class NoticeQuery implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 标题
*/
@Schema(description = "标题", example = "这是公告标题")
@Query(type = QueryType.LIKE)
private String title;
/**
* 类型
*/
@Schema(description = "类型", example = "1")
private String type;
}

View File

@@ -1,48 +0,0 @@
package top.wms.admin.system.model.req;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import top.wms.admin.system.enums.MessageTypeEnum;
import java.io.Serial;
import java.io.Serializable;
/**
* 创建消息参数
*
* @author Bull-BCLS
* @since 2023/10/15 19:05
*/
@Data
@Schema(description = "创建消息参数")
public class MessageReq implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 标题
*/
@Schema(description = "标题", example = "欢迎注册 xxx")
@NotBlank(message = "标题不能为空")
@Length(max = 50, message = "标题长度不能超过 {max} 个字符")
private String title;
/**
* 内容
*/
@Schema(description = "内容", example = "尊敬的 xx欢迎注册使用请及时配置您的密码。")
@NotBlank(message = "内容不能为空")
@Length(max = 255, message = "内容长度不能超过 {max} 个字符")
private String content;
/**
* 类型
*/
@Schema(description = "类型1系统消息", example = "1")
@NotNull(message = "类型非法")
private MessageTypeEnum type;
}

View File

@@ -1,77 +0,0 @@
package top.wms.admin.system.model.req;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Future;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import top.wms.admin.system.enums.NoticeScopeEnum;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;
/**
* 创建或修改公告参数
*
* @author Charles7c
* @since 2023/8/20 10:55
*/
@Data
@Schema(description = "创建或修改公告参数")
public class NoticeReq implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 标题
*/
@Schema(description = "标题", example = "这是公告标题")
@NotBlank(message = "标题不能为空")
@Length(max = 150, message = "标题长度不能超过 {max} 个字符")
private String title;
/**
* 内容
*/
@Schema(description = "内容", example = "这是公告内容")
@NotBlank(message = "内容不能为空")
private String content;
/**
* 类型(取值于字典 notice_type
*/
@Schema(description = "类型(取值于字典 notice_type", example = "1")
@NotBlank(message = "类型不能为空")
@Length(max = 30, message = "类型长度不能超过 {max} 个字符")
private String type;
/**
* 生效时间
*/
@Schema(description = "生效时间", example = "2023-08-08 00:00:00", type = "string")
private LocalDateTime effectiveTime;
/**
* 终止时间
*/
@Schema(description = "终止时间", example = "2023-08-08 23:59:59", type = "string")
@Future(message = "终止时间必须是未来时间")
private LocalDateTime terminateTime;
/**
* 通知范围
*/
@Schema(description = "通知范围", example = "2")
@NotNull(message = "通知范围不能为空")
private NoticeScopeEnum noticeScope;
/**
* 指定用户
*/
@Schema(description = "指定用户", example = "[1,2,3]")
private List<String> noticeUsers;
}

View File

@@ -1,74 +0,0 @@
package top.wms.admin.system.model.resp;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import top.wms.admin.common.model.resp.BaseDetailResp;
import top.wms.admin.system.enums.NoticeScopeEnum;
import java.io.Serial;
import java.time.LocalDateTime;
import java.util.List;
/**
* 公告详情信息
*
* @author Charles7c
* @since 2023/8/20 10:55
*/
@Data
@ExcelIgnoreUnannotated
@Schema(description = "公告详情信息")
public class NoticeDetailResp extends BaseDetailResp {
@Serial
private static final long serialVersionUID = 1L;
/**
* 标题
*/
@Schema(description = "标题", example = "这是公告标题")
@ExcelProperty(value = "标题")
private String title;
/**
* 内容
*/
@Schema(description = "内容", example = "这是公告内容")
@ExcelProperty(value = "内容")
private String content;
/**
* 类型(取值于字典 notice_type
*/
@Schema(description = "类型(取值于字典 notice_type", example = "1")
@ExcelProperty(value = "类型")
private String type;
/**
* 生效时间
*/
@Schema(description = "生效时间", example = "2023-08-08 00:00:00", type = "string")
@ExcelProperty(value = "生效时间")
private LocalDateTime effectiveTime;
/**
* 终止时间
*/
@Schema(description = "终止时间", example = "2023-08-08 23:59:59", type = "string")
@ExcelProperty(value = "终止时间")
private LocalDateTime terminateTime;
/**
* 通知范围
*/
@Schema(description = "通知范围", example = "2")
private NoticeScopeEnum noticeScope;
/**
* 指定用户
*/
@Schema(description = "指定用户", example = "[1,2,3]")
private List<String> noticeUsers;
}

View File

@@ -1,71 +0,0 @@
package top.wms.admin.system.model.resp;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import top.wms.admin.common.model.resp.BaseResp;
import top.wms.admin.system.enums.NoticeScopeEnum;
import top.wms.admin.system.enums.NoticeStatusEnum;
import java.io.Serial;
import java.time.LocalDateTime;
import java.util.List;
/**
* 公告信息
*
* @author Charles7c
* @since 2023/8/20 10:55
*/
@Data
@Schema(description = "公告信息")
public class NoticeResp extends BaseResp {
@Serial
private static final long serialVersionUID = 1L;
/**
* 标题
*/
@Schema(description = "标题", example = "这是公告标题")
private String title;
/**
* 类型(取值于字典 notice_type
*/
@Schema(description = "类型(取值于字典 notice_type", example = "1")
private String type;
/**
* 生效时间
*/
@Schema(description = "生效时间", example = "2023-08-08 00:00:00", type = "string")
private LocalDateTime effectiveTime;
/**
* 终止时间
*/
@Schema(description = "终止时间", example = "2023-08-08 23:59:59", type = "string")
private LocalDateTime terminateTime;
/**
* 状态
*
* @return 公告状态
*/
@Schema(description = "状态", example = "1")
public NoticeStatusEnum getStatus() {
return NoticeStatusEnum.getStatus(effectiveTime, terminateTime);
}
/**
* 通知范围
*/
@Schema(description = "通知范围(1.所有人 2.指定用户)", example = "1")
private NoticeScopeEnum noticeScope;
/**
* 指定用户
*/
@Schema(description = "指定用户", example = "[1,2,3]")
private List<String> noticeUsers;
}

View File

@@ -1,43 +0,0 @@
package top.wms.admin.system.model.resp.dashboard;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
/**
* 仪表盘-访问趋势信息
*
* @author Charles7c
* @since 2023/9/9 20:20
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Schema(description = "仪表盘-访问趋势信息")
public class DashboardAccessTrendResp implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 日期
*/
@Schema(description = "日期", example = "2023-08-08")
private String date;
/**
* 浏览量PV
*/
@Schema(description = "浏览量PV", example = "1000")
private Long pvCount;
/**
* IP 数
*/
@Schema(description = "IP 数", example = "500")
private Long ipCount;
}

View File

@@ -1,37 +0,0 @@
package top.wms.admin.system.model.resp.dashboard;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
/**
* 仪表盘-通用图表信息
*
* @author Charles7c
* @since 2024/10/17 21:37
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Schema(description = "仪表盘-通用图表信息")
public class DashboardChartCommonResp implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 名称
*/
@Schema(description = "名称", example = "Windows 10")
private String name;
/**
* 数量
*/
@Schema(description = "数量", example = "1234")
private Long value;
}

View File

@@ -1,39 +0,0 @@
package top.wms.admin.system.model.resp.dashboard;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 仪表盘-公告信息
*
* @author Charles7c
* @since 2023/8/20 10:55
*/
@Data
@Schema(description = "仪表盘-公告信息")
public class DashboardNoticeResp implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* ID
*/
@Schema(description = "ID", example = "1")
private Long id;
/**
* 标题
*/
@Schema(description = "标题", example = "这是公告标题")
private String title;
/**
* 类型(取值于字典 notice_type
*/
@Schema(description = "类型(取值于字典 notice_type", example = "1")
private String type;
}

View File

@@ -1,58 +0,0 @@
package top.wms.admin.system.model.resp.dashboard;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
/**
* 仪表盘-通用总览信息
*
* @author Charles7c
* @since 2024/10/19 12:19
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Schema(description = "仪表盘-通用总览信息")
public class DashboardOverviewCommonResp implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 总数
*/
@Schema(description = "总数", example = "888888")
private Long total;
/**
* 今日数量
*/
@Schema(description = "今日数量", example = "888")
private Long today;
/**
* 较昨日新增(百分比)
*/
@Schema(description = "较昨日新增(百分比)", example = "23.4")
private BigDecimal growth;
/**
* 图表数据
*/
@Schema(description = "图表数据")
private List<DashboardChartCommonResp> dataList;
/**
* 昨日数量
*/
@JsonIgnore
private Long yesterday;
}

View File

@@ -1,53 +0,0 @@
package top.wms.admin.system.model.resp.dashboard;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 仪表盘-总计信息
*
* @author Charles7c
* @since 2023/9/8 21:32
*/
@Data
@Schema(description = "仪表盘-总计信息")
public class DashboardTotalResp implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 浏览量PV
*/
@Schema(description = "浏览量PV", example = "88888")
private Long pvCount;
/**
* IP 数
*/
@Schema(description = "IP 数", example = "66666")
private Long ipCount;
/**
* 今日浏览量PV
*/
@Schema(description = "今日浏览量PV", example = "1234")
private Long todayPvCount;
/**
* 较昨日新增 PV百分比
*/
@Schema(description = "较昨日新增(百分比)", example = "23.4")
private BigDecimal newPvFromYesterday;
/**
* 昨日浏览量PV
*/
@JsonIgnore
private Long yesterdayPvCount;
}

View File

@@ -1,81 +0,0 @@
package top.wms.admin.system.model.resp.message;
import cn.crane4j.annotation.Assemble;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import top.wms.admin.common.constant.ContainerConstants;
import top.wms.admin.system.enums.MessageTypeEnum;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 消息信息
*
* @author Bull-BCLS
* @since 2023/10/15 19:05
*/
@Data
@Schema(description = "消息信息")
public class MessageResp implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* ID
*/
@Schema(description = "ID", example = "1")
private Long id;
/**
* 标题
*/
@Schema(description = "标题", example = "欢迎注册 xxx")
private String title;
/**
* 内容
*/
@Schema(description = "内容", example = "尊敬的 xx欢迎注册使用请及时配置您的密码。")
private String content;
/**
* 类型
*/
@Schema(description = "类型1系统消息", example = "1")
private MessageTypeEnum type;
/**
* 是否已读
*/
@Schema(description = "是否已读", example = "true")
private Boolean isRead;
/**
* 读取时间
*/
@Schema(description = "读取时间", example = "2023-08-08 23:59:59", type = "string")
private LocalDateTime readTime;
/**
* 创建人
*/
@JsonIgnore
@Assemble(prop = ":createUserString", container = ContainerConstants.USER_NICKNAME)
private Long createUser;
/**
* 创建人
*/
@Schema(description = "创建人", example = "超级管理员")
private String createUserString;
/**
* 创建时间
*/
@Schema(description = "创建时间", example = "2023-08-08 08:08:08", type = "string")
private LocalDateTime createTime;
}

View File

@@ -1,34 +0,0 @@
package top.wms.admin.system.model.resp.message;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import top.wms.admin.system.enums.MessageTypeEnum;
import java.io.Serial;
import java.io.Serializable;
/**
* 各类型未读消息信息
*
* @author Charles7c
* @since 2023/11/2 23:00
*/
@Data
@Schema(description = "各类型未读消息信息")
public class MessageTypeUnreadResp implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 类型
*/
@Schema(description = "类型1系统消息", example = "1")
private MessageTypeEnum type;
/**
* 数量
*/
@Schema(description = "数量", example = "10")
private Long count;
}

View File

@@ -1,36 +0,0 @@
package top.wms.admin.system.model.resp.message;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
/**
* 未读消息信息
*
* @author Charles7c
* @since 2023/11/2 23:00
*/
@Data
@Schema(description = "未读消息信息")
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class MessageUnreadResp implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 未读消息数量
*/
@Schema(description = "未读消息数量", example = "20")
private Long total;
/**
* 各类型未读消息数量
*/
@Schema(description = "各类型未读消息数量")
private List<MessageTypeUnreadResp> details;
}

View File

@@ -1,83 +0,0 @@
package top.wms.admin.system.service;
import top.wms.admin.system.model.resp.dashboard.DashboardAccessTrendResp;
import top.wms.admin.system.model.resp.dashboard.DashboardChartCommonResp;
import top.wms.admin.system.model.resp.dashboard.DashboardNoticeResp;
import top.wms.admin.system.model.resp.dashboard.DashboardOverviewCommonResp;
import java.io.IOException;
import java.util.List;
/**
* 仪表盘业务接口
*
* @author Charles7c
* @since 2023/9/8 21:32
*/
public interface DashboardService {
/**
* 查询公告列表
*
* @return 公告列表
*/
List<DashboardNoticeResp> listNotice();
/**
* 查询 PV 总览
*
* @return PV 总览
*/
DashboardOverviewCommonResp getOverviewPv();
/**
* 查询 IP 总览
*
* @return IP 总览
*/
DashboardOverviewCommonResp getOverviewIp();
/**
* 查询地域分析信息
*
* @return 地域分析信息
* @throws IOException /
*/
List<DashboardChartCommonResp> getAnalysisGeo() throws IOException;
/**
* 查询访问趋势信息
*
* @param days 日期数
* @return 访问趋势信息
*/
List<DashboardAccessTrendResp> listAccessTrend(Integer days);
/**
* 查询访问时段分析信息
*
* @return 访问时段分析信息
*/
List<DashboardChartCommonResp> getAnalysisTimeslot();
/**
* 查询模块分析信息
*
* @return 模块分析信息
*/
List<DashboardChartCommonResp> getAnalysisModule();
/**
* 查询终端分析信息
*
* @return 终端分析信息
*/
List<DashboardChartCommonResp> getAnalysisOs();
/**
* 查询浏览器分析信息
*
* @return 浏览器分析信息
*/
List<DashboardChartCommonResp> getAnalysisBrowser();
}

View File

@@ -1,42 +0,0 @@
package top.wms.admin.system.service;
import top.wms.admin.system.model.query.MessageQuery;
import top.wms.admin.system.model.req.MessageReq;
import top.wms.admin.system.model.resp.message.MessageResp;
import top.continew.starter.extension.crud.model.query.PageQuery;
import top.continew.starter.extension.crud.model.resp.PageResp;
import java.util.List;
/**
* 消息业务接口
*
* @author Bull-BCLS
* @since 2023/10/15 19:05
*/
public interface MessageService {
/**
* 分页查询列表
*
* @param query 查询条件
* @param pageQuery 分页查询条件
* @return 分页列表信息
*/
PageResp<MessageResp> page(MessageQuery query, PageQuery pageQuery);
/**
* 新增
*
* @param req 新增信息
* @param userIdList 接收人列表
*/
void add(MessageReq req, List<Long> userIdList);
/**
* 删除
*
* @param ids ID 列表
*/
void delete(List<Long> ids);
}

View File

@@ -1,45 +0,0 @@
package top.wms.admin.system.service;
import top.wms.admin.system.model.resp.message.MessageUnreadResp;
import java.util.List;
/**
* 消息和用户关联业务接口
*
* @author Bull-BCLS
* @since 2023/10/15 19:05
*/
public interface MessageUserService {
/**
* 根据用户 ID 查询未读消息数量
*
* @param userId 用户 ID
* @param isDetail 是否查询详情
* @return 未读消息信息
*/
MessageUnreadResp countUnreadMessageByUserId(Long userId, Boolean isDetail);
/**
* 新增
*
* @param messageId 消息 ID
* @param userIdList 用户 ID 列表
*/
void add(Long messageId, List<Long> userIdList);
/**
* 将消息标记已读
*
* @param ids 消息ID为空则将所有消息标记已读
*/
void readMessage(List<Long> ids);
/**
* 根据消息 ID 删除
*
* @param messageIds 消息 ID 列表
*/
void deleteByMessageIds(List<Long> messageIds);
}

View File

@@ -1,28 +0,0 @@
package top.wms.admin.system.service;
import top.wms.admin.system.model.entity.NoticeDO;
import top.wms.admin.system.model.query.NoticeQuery;
import top.wms.admin.system.model.req.NoticeReq;
import top.wms.admin.system.model.resp.NoticeDetailResp;
import top.wms.admin.system.model.resp.NoticeResp;
import top.wms.admin.system.model.resp.dashboard.DashboardNoticeResp;
import top.continew.starter.data.mp.service.IService;
import top.continew.starter.extension.crud.service.BaseService;
import java.util.List;
/**
* 公告业务接口
*
* @author Charles7c
* @since 2023/8/20 10:55
*/
public interface NoticeService extends BaseService<NoticeResp, NoticeDetailResp, NoticeQuery, NoticeReq>, IService<NoticeDO> {
/**
* 查询仪表盘公告列表
*
* @return 仪表盘公告列表
*/
List<DashboardNoticeResp> listDashboard();
}

View File

@@ -132,6 +132,14 @@ public interface UserService extends BaseService<UserResp, UserDetailResp, UserQ
*/
UserDO getByEmail(String email);
/**
* 根据卡片查询
*
* @param card 卡片
* @return 用户信息
*/
UserDO getByCard(String card);
/**
* 根据部门 ID 列表查询
*

View File

@@ -1,207 +0,0 @@
package top.wms.admin.system.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import top.wms.admin.system.mapper.LogMapper;
import top.wms.admin.system.model.resp.dashboard.DashboardAccessTrendResp;
import top.wms.admin.system.model.resp.dashboard.DashboardChartCommonResp;
import top.wms.admin.system.model.resp.dashboard.DashboardNoticeResp;
import top.wms.admin.system.model.resp.dashboard.DashboardOverviewCommonResp;
import top.wms.admin.system.service.DashboardService;
import top.wms.admin.system.service.NoticeService;
import top.continew.starter.core.constant.StringConstants;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
/**
* 仪表盘业务实现
*
* @author Charles7c
* @since 2023/9/8 21:32
*/
@Service
@RequiredArgsConstructor
public class DashboardServiceImpl implements DashboardService {
private final LogMapper logMapper;
private final NoticeService noticeService;
@Override
public List<DashboardNoticeResp> listNotice() {
return noticeService.listDashboard();
}
@Override
public DashboardOverviewCommonResp getOverviewPv() {
DashboardOverviewCommonResp resp = logMapper.selectDashboardOverviewPv();
resp.setGrowth(this.calcGrowthFromYesterday(resp.getToday(), resp.getYesterday()));
List<String> last12MonthList = this.getLast12Months();
List<DashboardChartCommonResp> dataList = logMapper.selectListDashboardAnalysisPv(last12MonthList);
if (dataList.size() < 12) {
// 填充缺失的数据
this.fillMissingDateData(last12MonthList, dataList);
}
resp.setDataList(dataList);
return resp;
}
@Override
public DashboardOverviewCommonResp getOverviewIp() {
DashboardOverviewCommonResp resp = logMapper.selectDashboardOverviewIp();
resp.setGrowth(this.calcGrowthFromYesterday(resp.getToday(), resp.getYesterday()));
List<String> last12MonthList = this.getLast12Months();
List<DashboardChartCommonResp> dataList = logMapper.selectListDashboardAnalysisIp(last12MonthList);
if (dataList.size() < 12) {
// 填充缺失的数据
this.fillMissingDateData(last12MonthList, dataList);
}
resp.setDataList(dataList);
return resp;
}
@Override
public List<DashboardChartCommonResp> getAnalysisGeo() throws IOException {
List<DashboardChartCommonResp> originList = logMapper.selectListDashboardAnalysisGeo();
List<DashboardChartCommonResp> list = new ArrayList<>(34);
// 获取省份数据
String chinaJson = IoUtil.readUtf8(new ClassPathResource("china.json").getInputStream());
JSONArray jsonArr = JSONUtil.parseObj(chinaJson).getJSONArray("children");
List<String> provinceList = jsonArr.stream().map(item -> {
JSONObject itemJsonObj = JSONUtil.parseObj(item);
return "%s:%s".formatted(itemJsonObj.getStr("name"), itemJsonObj.getStr("fullname"));
}).toList();
// 汇总各省份访问数据
for (String province : provinceList) {
String[] split = province.split(StringConstants.COLON);
String name = split[0];
String fullName = split[1];
long sum = originList.stream()
.filter(item -> item.getName().contains(name))
.mapToLong(DashboardChartCommonResp::getValue)
.sum();
list.add(new DashboardChartCommonResp(fullName, sum));
}
return list;
}
@Override
public List<DashboardAccessTrendResp> listAccessTrend(Integer days) {
DateTime currentDate = DateUtil.date();
Date startTime = DateUtil.beginOfDay(DateUtil.offsetDay(currentDate, -days)).toJdkDate();
Date endTime = DateUtil.endOfDay(DateUtil.offsetDay(currentDate, -1)).toJdkDate();
List<DashboardAccessTrendResp> list = logMapper.selectListDashboardAccessTrend(startTime, endTime);
if (list.size() < days) {
List<String> all = DateUtil.rangeToList(startTime, endTime, DateField.DAY_OF_MONTH)
.stream()
.map(date -> date.toString(DatePattern.NORM_DATE_FORMAT))
.toList();
Collection<String> missings = CollUtil.disjunction(all, list.stream()
.map(DashboardAccessTrendResp::getDate)
.toList());
list.addAll(missings.stream().map(missing -> new DashboardAccessTrendResp(missing, 0L, 0L)).toList());
list.sort(Comparator.comparing(DashboardAccessTrendResp::getDate));
}
return list;
}
@Override
public List<DashboardChartCommonResp> getAnalysisTimeslot() {
List<DashboardChartCommonResp> list = logMapper.selectListDashboardAnalysisTimeslot();
if (list.size() < 12) {
// 获取所有时间段
List<String> allTimeSlotList = new ArrayList<>(12);
for (int hour = 0; hour < 24; hour += 2) {
allTimeSlotList.add(String.format("%02d:00", hour));
}
// 填充缺失的数据
this.fillMissingDateData(allTimeSlotList, list);
}
return list;
}
@Override
public List<DashboardChartCommonResp> getAnalysisModule() {
return logMapper.selectListDashboardAnalysisModule(10);
}
@Override
public List<DashboardChartCommonResp> getAnalysisOs() {
List<DashboardChartCommonResp> list = logMapper.selectListDashboardAnalysisOs(4);
return this.buildOtherPieChartData(list);
}
@Override
public List<DashboardChartCommonResp> getAnalysisBrowser() {
List<DashboardChartCommonResp> list = logMapper.selectListDashboardAnalysisBrowser(4);
return this.buildOtherPieChartData(list);
}
/**
* 计算增长百分比
*
* @param today 今日数量
* @param yesterday 昨日数量
* @return 增长百分比
*/
private BigDecimal calcGrowthFromYesterday(Long today, Long yesterday) {
return (0 == yesterday)
? BigDecimal.valueOf(100)
: NumberUtil.round(NumberUtil.mul(NumberUtil.div(NumberUtil.sub(today, yesterday), yesterday), 100), 1);
}
/**
* 构建其他饼图数据
*
* @param list 饼图数据列表
* @return 饼图数据列表
*/
private List<DashboardChartCommonResp> buildOtherPieChartData(List<DashboardChartCommonResp> list) {
Long totalCount = logMapper.selectTotalCount();
long sumCount = list.stream().mapToLong(DashboardChartCommonResp::getValue).sum();
if (sumCount < totalCount) {
list.add(new DashboardChartCommonResp("其他", totalCount - sumCount));
}
return list;
}
/**
* 填充缺失时间段的数据
*
* @param all 所有时间段
* @param list 待填充数据
*/
private void fillMissingDateData(List<String> all, List<DashboardChartCommonResp> list) {
Collection<String> missings = CollUtil.disjunction(all, list.stream()
.map(DashboardChartCommonResp::getName)
.toList());
list.addAll(missings.stream().map(missing -> new DashboardChartCommonResp(missing, 0L)).toList());
list.sort(Comparator.comparing(DashboardChartCommonResp::getName));
}
/**
* 获取最近12个月的月份列表
*
* @return 月份列表
*/
private List<String> getLast12Months() {
DateTime currentMonth = DateUtil.beginOfMonth(DateUtil.date());
return DateUtil.rangeToList(DateUtil.offsetMonth(currentMonth, -12), DateUtil
.offsetMonth(currentMonth, -1), DateField.MONTH)
.stream()
.map(dateTime -> DateUtil.format(dateTime, DatePattern.NORM_MONTH_FORMAT))
.toList();
}
}

View File

@@ -1,65 +0,0 @@
package top.wms.admin.system.service.impl;
import cn.crane4j.annotation.AutoOperate;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.wms.admin.system.mapper.MessageMapper;
import top.wms.admin.system.model.entity.MessageDO;
import top.wms.admin.system.model.query.MessageQuery;
import top.wms.admin.system.model.req.MessageReq;
import top.wms.admin.system.model.resp.message.MessageResp;
import top.wms.admin.system.service.MessageService;
import top.wms.admin.system.service.MessageUserService;
import top.continew.starter.core.validation.CheckUtils;
import top.continew.starter.data.mp.util.QueryWrapperHelper;
import top.continew.starter.extension.crud.model.query.PageQuery;
import top.continew.starter.extension.crud.model.resp.PageResp;
import java.util.List;
/**
* 消息业务实现
*
* @author Bull-BCLS
* @since 2023/10/15 19:05
*/
@Service
@RequiredArgsConstructor
public class MessageServiceImpl implements MessageService {
private final MessageMapper baseMapper;
private final MessageUserService messageUserService;
@Override
@AutoOperate(type = MessageResp.class, on = "list")
public PageResp<MessageResp> page(MessageQuery query, PageQuery pageQuery) {
QueryWrapper<MessageDO> queryWrapper = QueryWrapperHelper.build(query, pageQuery.getSort());
queryWrapper.apply(null != query.getUserId(), "t2.user_id={0}", query.getUserId())
.apply(null != query.getIsRead(), "t2.is_read={0}", query.getIsRead());
IPage<MessageResp> page = baseMapper.selectPageByUserId(new Page<>(pageQuery.getPage(), pageQuery
.getSize()), queryWrapper);
return PageResp.build(page);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void add(MessageReq req, List<Long> userIdList) {
CheckUtils.throwIf(() -> CollUtil.isEmpty(userIdList), "消息接收人不能为空");
MessageDO message = BeanUtil.copyProperties(req, MessageDO.class);
baseMapper.insert(message);
messageUserService.add(message.getId(), userIdList);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void delete(List<Long> ids) {
baseMapper.deleteByIds(ids);
messageUserService.deleteByMessageIds(ids);
}
}

View File

@@ -1,85 +0,0 @@
package top.wms.admin.system.service.impl;
import cn.hutool.core.collection.CollUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import top.wms.admin.system.enums.MessageTypeEnum;
import top.wms.admin.system.mapper.MessageUserMapper;
import top.wms.admin.system.model.entity.MessageUserDO;
import top.wms.admin.system.model.resp.message.MessageTypeUnreadResp;
import top.wms.admin.system.model.resp.message.MessageUnreadResp;
import top.wms.admin.system.service.MessageUserService;
import top.continew.starter.core.validation.CheckUtils;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
/**
* 消息和用户关联业务实现
*
* @author Bull-BCLS
* @since 2023/10/15 19:05
*/
@Service
@RequiredArgsConstructor
public class MessageUserServiceImpl implements MessageUserService {
private final MessageUserMapper baseMapper;
@Override
public MessageUnreadResp countUnreadMessageByUserId(Long userId, Boolean isDetail) {
MessageUnreadResp result = new MessageUnreadResp();
Long total = 0L;
if (Boolean.TRUE.equals(isDetail)) {
List<MessageTypeUnreadResp> detailList = new ArrayList<>();
for (MessageTypeEnum messageType : MessageTypeEnum.values()) {
MessageTypeUnreadResp resp = new MessageTypeUnreadResp();
resp.setType(messageType);
Long count = baseMapper.selectUnreadCountByUserIdAndType(userId, messageType.getValue());
resp.setCount(count);
detailList.add(resp);
total += count;
}
result.setDetails(detailList);
} else {
total = baseMapper.selectUnreadCountByUserIdAndType(userId, null);
}
result.setTotal(total);
return result;
}
@Override
public void add(Long messageId, List<Long> userIdList) {
CheckUtils.throwIfEmpty(userIdList, "消息接收人不能为空");
List<MessageUserDO> messageUserList = userIdList.stream().map(userId -> {
MessageUserDO messageUser = new MessageUserDO();
messageUser.setUserId(userId);
messageUser.setMessageId(messageId);
messageUser.setIsRead(false);
return messageUser;
}).toList();
baseMapper.insert(messageUserList);
}
@Override
public void readMessage(List<Long> ids) {
if (CollUtil.isEmpty(ids)) {
return;
}
baseMapper.lambdaUpdate()
.set(MessageUserDO::getIsRead, true)
.set(MessageUserDO::getReadTime, LocalDateTime.now())
.eq(MessageUserDO::getIsRead, false)
.in(CollUtil.isNotEmpty(ids), MessageUserDO::getMessageId, ids)
.update();
}
@Override
public void deleteByMessageIds(List<Long> messageIds) {
if (CollUtil.isEmpty(messageIds)) {
return;
}
baseMapper.lambdaUpdate().in(MessageUserDO::getMessageId, messageIds).remove();
}
}

View File

@@ -1,33 +0,0 @@
package top.wms.admin.system.service.impl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import top.wms.admin.common.context.UserContextHolder;
import top.wms.admin.system.mapper.NoticeMapper;
import top.wms.admin.system.model.entity.NoticeDO;
import top.wms.admin.system.model.query.NoticeQuery;
import top.wms.admin.system.model.req.NoticeReq;
import top.wms.admin.system.model.resp.NoticeDetailResp;
import top.wms.admin.system.model.resp.NoticeResp;
import top.wms.admin.system.model.resp.dashboard.DashboardNoticeResp;
import top.wms.admin.system.service.NoticeService;
import top.continew.starter.extension.crud.service.BaseServiceImpl;
import java.util.List;
/**
* 公告业务实现
*
* @author Charles7c
* @since 2023/8/20 10:55
*/
@Service
@RequiredArgsConstructor
public class NoticeServiceImpl extends BaseServiceImpl<NoticeMapper, NoticeDO, NoticeResp, NoticeDetailResp, NoticeQuery, NoticeReq> implements NoticeService {
@Override
public List<DashboardNoticeResp> listDashboard() {
Long userId = UserContextHolder.isAdmin() ? null : UserContextHolder.getUserId();
return baseMapper.selectDashboardList(userId);
}
}

View File

@@ -460,6 +460,11 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, UserDO, UserRes
return baseMapper.selectByEmail(email);
}
@Override
public UserDO getByCard(String card) {
return baseMapper.selectOne(new QueryWrapper<UserDO>().eq("card_no", card));
}
@Override
public Long countByDeptIds(List<Long> deptIds) {
if (CollUtil.isEmpty(deptIds)) {

View File

@@ -0,0 +1,15 @@
package top.wms.admin.weighManage.model.resp;
import lombok.Data;
@Data
public class MaterialResp {
private Long id;
private String materialCode;
private String materialName;
private String materialSpec;
private String weight;
private String imageUrl;
}

View File

@@ -41,115 +41,4 @@
${ew.customSqlSegment}
</select>
<select id="selectDashboardOverviewPv" resultType="top.wms.admin.system.model.resp.dashboard.DashboardOverviewCommonResp">
SELECT
(SELECT COUNT(*) FROM sys_log) AS total,
(SELECT COUNT(*) FROM sys_log WHERE create_time >= CURDATE() AND create_time &lt; DATE_ADD(CURDATE(), INTERVAL 1 DAY)) AS today,
(SELECT COUNT(*) FROM sys_log WHERE create_time >= DATE_SUB(CURDATE(), INTERVAL 1 DAY) AND create_time &lt; CURDATE()) AS yesterday
</select>
<select id="selectDashboardOverviewIp" resultType="top.wms.admin.system.model.resp.dashboard.DashboardOverviewCommonResp">
SELECT
(SELECT COUNT(DISTINCT ip) FROM sys_log) AS total,
(SELECT COUNT(DISTINCT ip) FROM sys_log WHERE create_time >= CURDATE() AND create_time &lt; DATE_ADD(CURDATE(), INTERVAL 1 DAY)) AS today,
(SELECT COUNT(DISTINCT ip) FROM sys_log WHERE create_time >= DATE_SUB(CURDATE(), INTERVAL 1 DAY) AND create_time &lt; CURDATE()) AS yesterday
</select>
<select id="selectListDashboardAnalysisPv"
resultType="top.wms.admin.system.model.resp.dashboard.DashboardChartCommonResp">
SELECT
DATE_FORMAT(create_time, '%Y-%m') AS name,
COUNT(*) AS value
FROM sys_log
WHERE DATE_FORMAT(create_time, '%Y-%m' ) IN
<foreach collection="months" item="month" separator="," open="(" close=")">
#{month}
</foreach>
GROUP BY name
ORDER BY name
</select>
<select id="selectListDashboardAnalysisIp"
resultType="top.wms.admin.system.model.resp.dashboard.DashboardChartCommonResp">
SELECT
DATE_FORMAT(create_time, '%Y-%m') AS name,
COUNT(DISTINCT ip) AS value
FROM sys_log
WHERE DATE_FORMAT(create_time, '%Y-%m' ) IN
<foreach collection="months" item="month" separator="," open="(" close=")">
#{month}
</foreach>
GROUP BY name
ORDER BY name
</select>
<select id="selectListDashboardAnalysisGeo" resultType="top.wms.admin.system.model.resp.dashboard.DashboardChartCommonResp">
SELECT
CASE
WHEN POSITION(' ' IN address) > 0 THEN SUBSTRING(address FROM 1 FOR POSITION(' ' IN address) - 1)
ELSE address
END AS name,
COUNT(*) AS value
FROM sys_log
WHERE address LIKE '中国%'
GROUP BY name
</select>
<select id="selectListDashboardAccessTrend"
resultType="top.wms.admin.system.model.resp.dashboard.DashboardAccessTrendResp">
SELECT
DATE(create_time) AS date,
COUNT(*) AS pvCount,
COUNT(DISTINCT ip) AS ipCount
FROM sys_log
WHERE create_time BETWEEN #{startTime} AND #{endTime}
GROUP BY date
ORDER BY date
</select>
<select id="selectListDashboardAnalysisTimeslot"
resultType="top.wms.admin.system.model.resp.dashboard.DashboardChartCommonResp">
SELECT
LPAD(CONCAT(FLOOR(HOUR(create_time) / 2) * 2, ':00'), 5, '0') AS name,
COUNT(*) AS value
FROM sys_log
GROUP BY name
ORDER BY name
</select>
<select id="selectListDashboardAnalysisModule"
resultType="top.wms.admin.system.model.resp.dashboard.DashboardChartCommonResp">
SELECT
module AS name,
COUNT(*) AS value
FROM sys_log
WHERE module != '验证码' AND module != '登录'
GROUP BY name
ORDER BY value DESC
LIMIT #{top}
</select>
<select id="selectListDashboardAnalysisOs"
resultType="top.wms.admin.system.model.resp.dashboard.DashboardChartCommonResp">
SELECT
os AS name,
COUNT(*) AS value
FROM sys_log
WHERE os IS NOT NULL
GROUP BY name
ORDER BY value DESC
LIMIT #{top}
</select>
<select id="selectListDashboardAnalysisBrowser"
resultType="top.wms.admin.system.model.resp.dashboard.DashboardChartCommonResp">
SELECT
SUBSTRING_INDEX(browser, ' ', 1) AS name,
COUNT(*) AS value
FROM sys_log
WHERE browser IS NOT NULL
GROUP BY name
ORDER BY value DESC
LIMIT #{top}
</select>
</mapper>

View File

@@ -1,14 +0,0 @@
<?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="top.wms.admin.system.mapper.MessageMapper">
<select id="selectPageByUserId" resultType="top.wms.admin.system.model.resp.message.MessageResp">
SELECT
t1.*,
t2.user_id,
t2.is_read,
t2.read_time
FROM sys_message AS t1
LEFT JOIN sys_message_user AS t2 ON t2.message_id = t1.id
${ew.getCustomSqlSegment}
</select>
</mapper>

View File

@@ -1,14 +0,0 @@
<?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="top.wms.admin.system.mapper.MessageUserMapper">
<select id="selectUnreadCountByUserIdAndType" resultType="Long">
SELECT
COUNT(t1.message_id)
FROM sys_message_user AS t1
LEFT JOIN sys_message AS t2 ON t2.id = t1.message_id
WHERE t1.user_id = #{userId} AND t1.is_read = false
<if test="type != null">
AND t2.type = #{type}
</if>
</select>
</mapper>

View File

@@ -1,18 +0,0 @@
<?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="top.wms.admin.system.mapper.NoticeMapper">
<select id="selectDashboardList"
resultType="top.wms.admin.system.model.resp.dashboard.DashboardNoticeResp">
SELECT
id, title, type
FROM sys_notice
WHERE (effective_time IS NULL OR NOW() > effective_time)
AND (terminate_time IS NULL OR terminate_time > NOW())
<if test="userId != null">
AND (notice_scope = 1 OR (notice_scope = 2 AND JSON_EXTRACT(notice_users, "$[0]") = CAST(#{userId} AS CHAR)))
</if>
ORDER BY sort ASC, effective_time DESC
LIMIT 5
</select>
</mapper>

View File

@@ -1,6 +1,5 @@
package top.wms.admin.config.satoken;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.interceptor.SaInterceptor;

View File

@@ -0,0 +1,38 @@
package top.wms.admin.controller.WeighManage;
import cn.dev33.satoken.annotation.SaCheckPermission;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import top.wms.admin.weighManage.model.resp.MaterialResp;
/**
* 部门管理管理 API
*
* @author zc
* @since 2025/03/19 17:46
*/
@Tag(name = "部门管理管理 API")
@RestController
@RequiredArgsConstructor
@RequestMapping("/weighManage/material")
public class WeighController {
/**
* 获取材料详细信息
*/
@SaCheckPermission("Weigh:material:detail")
@GetMapping(value = "/detail")
public MaterialResp getInfo() {
MaterialResp materialResp = new MaterialResp();
materialResp.setId(1L);
materialResp.setMaterialCode("123");
materialResp.setMaterialName("测试材料");
materialResp.setMaterialSpec("测试规格");
materialResp.setWeight("100");
materialResp.setImageUrl("http://example.com/image.jpg");
return materialResp;
}
}

View File

@@ -1,118 +0,0 @@
package top.wms.admin.controller.common;
import com.alicp.jetcache.anno.CachePenetrationProtect;
import com.alicp.jetcache.anno.CacheRefresh;
import com.alicp.jetcache.anno.CacheType;
import com.alicp.jetcache.anno.Cached;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import top.wms.admin.common.constant.CacheConstants;
import top.wms.admin.system.model.resp.dashboard.DashboardAccessTrendResp;
import top.wms.admin.system.model.resp.dashboard.DashboardChartCommonResp;
import top.wms.admin.system.model.resp.dashboard.DashboardNoticeResp;
import top.wms.admin.system.model.resp.dashboard.DashboardOverviewCommonResp;
import top.wms.admin.system.service.DashboardService;
import top.continew.starter.core.validation.ValidationUtils;
import top.continew.starter.log.annotation.Log;
import java.io.IOException;
import java.util.List;
/**
* 仪表盘 API
*
* @author Charles7c
* @since 2023/1/22 21:48
*/
@Tag(name = "仪表盘 API")
@Log(ignore = true)
@Validated
@RestController
@RequiredArgsConstructor
@RequestMapping("/dashboard")
public class DashboardController {
private final DashboardService dashboardService;
@Operation(summary = "查询公告列表", description = "查询公告列表")
@GetMapping("/notice")
public List<DashboardNoticeResp> listNotice() {
return dashboardService.listNotice();
}
@Operation(summary = "查询PV总览", description = "查询PV总览")
@GetMapping("/analysis/overview/pv")
public DashboardOverviewCommonResp getOverviewPv() {
return dashboardService.getOverviewPv();
}
@Operation(summary = "查询IP总览", description = "查询IP总览")
@GetMapping("/analysis/overview/ip")
public DashboardOverviewCommonResp getOverviewIp() {
return dashboardService.getOverviewIp();
}
@Operation(summary = "查询地域分析", description = "查询地域分析")
@GetMapping("/analysis/geo")
@CachePenetrationProtect
@CacheRefresh(refresh = 7200)
@Cached(key = "'GEO'", name = CacheConstants.DASHBOARD_KEY_PREFIX, cacheType = CacheType.BOTH, syncLocal = true)
public List<DashboardChartCommonResp> getAnalysisGeo() throws IOException {
return dashboardService.getAnalysisGeo();
}
@Operation(summary = "查询访问趋势信息", description = "查询访问趋势信息")
@Parameter(name = "days", description = "日期数", example = "30", in = ParameterIn.PATH)
@GetMapping("/access/trend/{days}")
@CachePenetrationProtect
@CacheRefresh(refresh = 7200)
@Cached(key = "#days", name = CacheConstants.DASHBOARD_KEY_PREFIX, cacheType = CacheType.BOTH, syncLocal = true)
public List<DashboardAccessTrendResp> listAccessTrend(@PathVariable Integer days) {
ValidationUtils.throwIf(7 != days && 30 != days, "仅支持查询近 7/30 天访问趋势信息");
return dashboardService.listAccessTrend(days);
}
@Operation(summary = "查询访问时段分析", description = "查询访问时段分析")
@GetMapping("/analysis/timeslot")
@CachePenetrationProtect
@CacheRefresh(refresh = 7200)
@Cached(key = "'TIMESLOT'", name = CacheConstants.DASHBOARD_KEY_PREFIX, cacheType = CacheType.BOTH, syncLocal = true)
public List<DashboardChartCommonResp> getAnalysisTimeslot() {
return dashboardService.getAnalysisTimeslot();
}
@Operation(summary = "查询模块分析", description = "查询模块分析")
@GetMapping("/analysis/module")
@CachePenetrationProtect
@CacheRefresh(refresh = 7200)
@Cached(key = "'MODULE'", name = CacheConstants.DASHBOARD_KEY_PREFIX, cacheType = CacheType.BOTH, syncLocal = true)
public List<DashboardChartCommonResp> getAnalysisModule() {
return dashboardService.getAnalysisModule();
}
@Operation(summary = "查询终端分析", description = "查询终端分析")
@GetMapping("/analysis/os")
@CachePenetrationProtect
@CacheRefresh(refresh = 7200)
@Cached(key = "'OS'", name = CacheConstants.DASHBOARD_KEY_PREFIX, cacheType = CacheType.BOTH, syncLocal = true)
public List<DashboardChartCommonResp> getAnalysisOs() {
return dashboardService.getAnalysisOs();
}
@Operation(summary = "查询浏览器分析", description = "查询浏览器分析")
@GetMapping("/analysis/browser")
@CachePenetrationProtect
@CacheRefresh(refresh = 7200)
@Cached(key = "'BROWSER'", name = CacheConstants.DASHBOARD_KEY_PREFIX, cacheType = CacheType.BOTH, syncLocal = true)
public List<DashboardChartCommonResp> getAnalysisBrowser() {
return dashboardService.getAnalysisBrowser();
}
}

View File

@@ -30,9 +30,6 @@ public class DemoEnvironmentJob {
private final DictItemMapper dictItemMapper;
private final DictMapper dictMapper;
private final StorageMapper storageMapper;
private final NoticeMapper noticeMapper;
private final MessageMapper messageMapper;
private final MessageUserMapper messageUserMapper;
private final UserMapper userMapper;
private final UserRoleMapper userRoleMapper;
private final UserSocialMapper userSocialMapper;
@@ -67,10 +64,6 @@ public class DemoEnvironmentJob {
this.log(dictCount, "字典");
Long storageCount = storageMapper.lambdaQuery().gt(StorageDO::getId, DELETE_FLAG).count();
this.log(storageCount, "存储");
Long noticeCount = noticeMapper.lambdaQuery().gt(NoticeDO::getId, DELETE_FLAG).count();
this.log(noticeCount, "公告");
Long messageCount = messageMapper.lambdaQuery().count();
this.log(messageCount, "通知");
Long userCount = userMapper.lambdaQuery().notIn(UserDO::getId, USER_FLAG).count();
this.log(userCount, "用户");
Long roleCount = roleMapper.lambdaQuery().notIn(RoleDO::getId, ROLE_FLAG).count();
@@ -83,8 +76,6 @@ public class DemoEnvironmentJob {
this.log(clientCount, "终端");
InterceptorIgnoreHelper.handle(IgnoreStrategy.builder().blockAttack(true).build());
SnailJobLog.REMOTE.info("演示环境待清理数据项检测完成,开始执行清理。");
// 清理关联数据
messageUserMapper.lambdaUpdate().gt(MessageUserDO::getMessageId, MESSAGE_FLAG).remove();
userRoleMapper.lambdaUpdate().notIn(UserRoleDO::getRoleId, ROLE_FLAG).remove();
userRoleMapper.lambdaUpdate().notIn(UserRoleDO::getUserId, USER_FLAG).remove();
roleDeptMapper.lambdaUpdate().notIn(RoleDeptDO::getRoleId, ROLE_FLAG).remove();
@@ -100,12 +91,6 @@ public class DemoEnvironmentJob {
this.clean(storageCount, "存储", null, () -> storageMapper.lambdaUpdate()
.gt(StorageDO::getId, DELETE_FLAG)
.remove());
this.clean(noticeCount, "公告", null, () -> noticeMapper.lambdaUpdate()
.gt(NoticeDO::getId, DELETE_FLAG)
.remove());
this.clean(messageCount, "通知", null, () -> messageMapper.lambdaUpdate()
.gt(MessageDO::getId, MESSAGE_FLAG)
.remove());
this.clean(userCount, "用户", null, () -> userMapper.lambdaUpdate().notIn(UserDO::getId, USER_FLAG).remove());
this.clean(roleCount, "角色", null, () -> roleMapper.lambdaUpdate().notIn(RoleDO::getId, ROLE_FLAG).remove());
this.clean(menuCount, "菜单", CacheConstants.ROLE_MENU_KEY_PREFIX, () -> menuMapper.lambdaUpdate()

View File

@@ -1,65 +0,0 @@
package top.wms.admin.controller.system;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import top.wms.admin.common.context.UserContextHolder;
import top.wms.admin.system.model.query.MessageQuery;
import top.wms.admin.system.model.resp.message.MessageResp;
import top.wms.admin.system.model.resp.message.MessageUnreadResp;
import top.wms.admin.system.service.MessageService;
import top.wms.admin.system.service.MessageUserService;
import top.continew.starter.extension.crud.model.query.PageQuery;
import top.continew.starter.extension.crud.model.resp.PageResp;
import top.continew.starter.log.annotation.Log;
import java.util.List;
/**
* 消息管理 API
*
* @author Bull-BCLS
* @since 2023/10/15 19:05
*/
@Tag(name = "消息管理 API")
@RestController
@RequiredArgsConstructor
@RequestMapping("/system/message")
public class MessageController {
private final MessageService baseService;
private final MessageUserService messageUserService;
@Operation(summary = "分页查询列表", description = "分页查询列表")
@GetMapping
public PageResp<MessageResp> page(MessageQuery query, @Validated PageQuery pageQuery) {
query.setUserId(UserContextHolder.getUserId());
return baseService.page(query, pageQuery);
}
@Operation(summary = "删除数据", description = "删除数据")
@Parameter(name = "ids", description = "ID 列表", example = "1,2", in = ParameterIn.PATH)
@DeleteMapping("/{ids}")
public void delete(@PathVariable List<Long> ids) {
baseService.delete(ids);
}
@Operation(summary = "标记已读", description = "将消息标记为已读状态")
@Parameter(name = "ids", description = "消息ID列表", example = "1,2", in = ParameterIn.QUERY)
@PatchMapping("/read")
public void readMessage(@RequestParam(required = false) List<Long> ids) {
messageUserService.readMessage(ids);
}
@Log(ignore = true)
@Operation(summary = "查询未读消息数量", description = "查询当前用户的未读消息数量")
@Parameter(name = "isDetail", description = "是否查询详情", example = "true", in = ParameterIn.QUERY)
@GetMapping("/unread")
public MessageUnreadResp countUnreadMessage(@RequestParam(required = false) Boolean detail) {
return messageUserService.countUnreadMessageByUserId(UserContextHolder.getUserId(), detail);
}
}

View File

@@ -1,50 +0,0 @@
package top.wms.admin.controller.system;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.RestController;
import top.wms.admin.common.controller.BaseController;
import top.wms.admin.system.enums.NoticeScopeEnum;
import top.wms.admin.system.model.query.NoticeQuery;
import top.wms.admin.system.model.req.NoticeReq;
import top.wms.admin.system.model.resp.NoticeDetailResp;
import top.wms.admin.system.model.resp.NoticeResp;
import top.wms.admin.system.service.NoticeService;
import top.continew.starter.core.validation.ValidationUtils;
import top.continew.starter.extension.crud.annotation.CrudApi;
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
import top.continew.starter.extension.crud.enums.Api;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
/**
* 公告管理 API
*
* @author Charles7c
* @since 2023/8/20 10:55
*/
@Tag(name = "公告管理 API")
@RestController
@CrudRequestMapping(value = "/system/notice", api = {Api.PAGE, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE})
public class NoticeController extends BaseController<NoticeService, NoticeResp, NoticeDetailResp, NoticeQuery, NoticeReq> {
@Override
public void preHandle(CrudApi crudApi, Object[] args, Method targetMethod, Class<?> targetClass) throws Exception {
super.preHandle(crudApi, args, targetMethod, targetClass);
Api api = crudApi.value();
if (!(Api.ADD.equals(api) || Api.UPDATE.equals(api))) {
return;
}
NoticeReq req = (NoticeReq)args[0];
// 校验生效时间
LocalDateTime effectiveTime = req.getEffectiveTime();
LocalDateTime terminateTime = req.getTerminateTime();
if (null != effectiveTime && null != terminateTime) {
ValidationUtils.throwIf(terminateTime.isBefore(effectiveTime), "终止时间必须晚于生效时间");
}
// 校验通知范围
if (NoticeScopeEnum.USER.equals(req.getNoticeScope())) {
ValidationUtils.throwIfEmpty(req.getNoticeUsers(), "通知用户不能为空");
}
}
}