fix: 修复SMS sendMessage编译错误,重构login方法,使用Assert类替换直接抛出的BizException,添加favorite、history、create、has字段到登录返回结果,修复前端接口乱码问题,为所有实体类添加createBy和updateBy字段,确保CmsCategoryController#getPageList可无登录访问
This commit is contained in:
parent
730f18e932
commit
9d53c5e2de
|
|
@ -0,0 +1,7 @@
|
||||||
|
-- 给account表添加create_by和update_by字段
|
||||||
|
-- 作者: 王志维
|
||||||
|
-- 创建时间: 2026-01-26
|
||||||
|
|
||||||
|
ALTER TABLE `account`
|
||||||
|
ADD COLUMN `create_by` varchar(50) DEFAULT NULL COMMENT '创建人' AFTER `update_time`,
|
||||||
|
ADD COLUMN `update_by` varchar(50) DEFAULT NULL COMMENT '更新人' AFTER `create_by`;
|
||||||
|
|
@ -0,0 +1,90 @@
|
||||||
|
-- 为所有表添加create_by和update_by字段
|
||||||
|
-- 作者: 王志维
|
||||||
|
-- 创建时间: 2026-01-26
|
||||||
|
|
||||||
|
SET NAMES utf8mb4;
|
||||||
|
SET FOREIGN_KEY_CHECKS = 0;
|
||||||
|
|
||||||
|
-- 1. 账户表
|
||||||
|
ALTER TABLE `account`
|
||||||
|
ADD COLUMN `create_by` varchar(50) DEFAULT NULL COMMENT '创建人' AFTER `update_time`,
|
||||||
|
ADD COLUMN `update_by` varchar(50) DEFAULT NULL COMMENT '更新人' AFTER `create_by`;
|
||||||
|
|
||||||
|
-- 2. 积分账户表
|
||||||
|
ALTER TABLE `points_account`
|
||||||
|
ADD COLUMN `create_by` varchar(50) DEFAULT NULL COMMENT '创建人' AFTER `update_time`,
|
||||||
|
ADD COLUMN `update_by` varchar(50) DEFAULT NULL COMMENT '更新人' AFTER `create_by`;
|
||||||
|
|
||||||
|
-- 3. 客户表
|
||||||
|
ALTER TABLE `customer`
|
||||||
|
ADD COLUMN `create_by` varchar(50) DEFAULT NULL COMMENT '创建人' AFTER `update_time`,
|
||||||
|
ADD COLUMN `update_by` varchar(50) DEFAULT NULL COMMENT '更新人' AFTER `create_by`;
|
||||||
|
|
||||||
|
-- 4. 内容购买记录表
|
||||||
|
ALTER TABLE `content_purchase`
|
||||||
|
ADD COLUMN `create_by` varchar(50) DEFAULT NULL COMMENT '创建人' AFTER `update_time`,
|
||||||
|
ADD COLUMN `update_by` varchar(50) DEFAULT NULL COMMENT '更新人' AFTER `create_by`;
|
||||||
|
|
||||||
|
-- 5. 用户角色关联表
|
||||||
|
ALTER TABLE `sys_user_role`
|
||||||
|
ADD COLUMN `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间' AFTER `user_id`,
|
||||||
|
ADD COLUMN `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间' AFTER `create_time`,
|
||||||
|
ADD COLUMN `delete_flag` tinyint(1) DEFAULT '0' COMMENT '是否删除 :0 未删除,1已删除' AFTER `update_time`,
|
||||||
|
ADD COLUMN `create_by` varchar(50) DEFAULT NULL COMMENT '创建人' AFTER `delete_flag`,
|
||||||
|
ADD COLUMN `update_by` varchar(50) DEFAULT NULL COMMENT '更新人' AFTER `create_by`;
|
||||||
|
|
||||||
|
-- 6. 系统菜单表
|
||||||
|
ALTER TABLE `sys_menu`
|
||||||
|
ADD COLUMN `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间' AFTER `delete_flag`,
|
||||||
|
ADD COLUMN `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间' AFTER `create_time`,
|
||||||
|
ADD COLUMN `create_by` varchar(50) DEFAULT NULL COMMENT '创建人' AFTER `update_time`,
|
||||||
|
ADD COLUMN `update_by` varchar(50) DEFAULT NULL COMMENT '更新人' AFTER `create_by`;
|
||||||
|
|
||||||
|
-- 7. 系统角色表
|
||||||
|
ALTER TABLE `sys_role`
|
||||||
|
ADD COLUMN `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间' AFTER `create_time`,
|
||||||
|
ADD COLUMN `create_by` varchar(50) DEFAULT NULL COMMENT '创建人' AFTER `delete_flag`,
|
||||||
|
ADD COLUMN `update_by` varchar(50) DEFAULT NULL COMMENT '更新人' AFTER `create_by`;
|
||||||
|
|
||||||
|
-- 8. 支付订单表
|
||||||
|
ALTER TABLE `payment_order`
|
||||||
|
ADD COLUMN `create_by` varchar(50) DEFAULT NULL COMMENT '创建人' AFTER `delete_flag`,
|
||||||
|
ADD COLUMN `update_by` varchar(50) DEFAULT NULL COMMENT '更新人' AFTER `create_by`;
|
||||||
|
|
||||||
|
-- 9. 系统日志表
|
||||||
|
ALTER TABLE `sys_log`
|
||||||
|
ADD COLUMN `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间' AFTER `note`,
|
||||||
|
ADD COLUMN `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间' AFTER `create_time`,
|
||||||
|
ADD COLUMN `delete_flag` tinyint(1) DEFAULT '0' COMMENT '是否删除 :0 未删除,1已删除' AFTER `update_time`,
|
||||||
|
ADD COLUMN `create_by` varchar(50) DEFAULT NULL COMMENT '创建人' AFTER `delete_flag`,
|
||||||
|
ADD COLUMN `update_by` varchar(50) DEFAULT NULL COMMENT '更新人' AFTER `create_by`;
|
||||||
|
|
||||||
|
-- 10. 系统用户表
|
||||||
|
ALTER TABLE `sys_user`
|
||||||
|
ADD COLUMN `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间' AFTER `create_time`,
|
||||||
|
ADD COLUMN `create_by` varchar(50) DEFAULT NULL COMMENT '创建人' AFTER `delete_flag`,
|
||||||
|
ADD COLUMN `update_by` varchar(50) DEFAULT NULL COMMENT '更新人' AFTER `create_by`;
|
||||||
|
|
||||||
|
-- 11. 供应商表
|
||||||
|
ALTER TABLE `supplier`
|
||||||
|
ADD COLUMN `create_by` varchar(50) DEFAULT NULL COMMENT '创建人' AFTER `update_time`,
|
||||||
|
ADD COLUMN `update_by` varchar(50) DEFAULT NULL COMMENT '更新人' AFTER `create_by`;
|
||||||
|
|
||||||
|
-- 12. 系统字典表
|
||||||
|
ALTER TABLE `sys_dict`
|
||||||
|
ADD COLUMN `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间' AFTER `create_time`,
|
||||||
|
ADD COLUMN `delete_flag` tinyint(1) DEFAULT '0' COMMENT '是否删除 :0 未删除,1已删除' AFTER `update_time`,
|
||||||
|
ADD COLUMN `create_by` varchar(50) DEFAULT NULL COMMENT '创建人' AFTER `delete_flag`,
|
||||||
|
ADD COLUMN `update_by` varchar(50) DEFAULT NULL COMMENT '更新人' AFTER `create_by`;
|
||||||
|
|
||||||
|
-- 13. 内容点赞记录表
|
||||||
|
ALTER TABLE `cms_content_like`
|
||||||
|
ADD COLUMN `create_by` varchar(50) DEFAULT NULL COMMENT '创建人' AFTER `delete_flag`,
|
||||||
|
ADD COLUMN `update_by` varchar(50) DEFAULT NULL COMMENT '更新人' AFTER `create_by`;
|
||||||
|
|
||||||
|
-- 14. 内容查看记录表
|
||||||
|
ALTER TABLE `cms_content_view`
|
||||||
|
ADD COLUMN `create_by` varchar(50) DEFAULT NULL COMMENT '创建人' AFTER `delete_flag`,
|
||||||
|
ADD COLUMN `update_by` varchar(50) DEFAULT NULL COMMENT '更新人' AFTER `create_by`;
|
||||||
|
|
||||||
|
SET FOREIGN_KEY_CHECKS = 1;
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
-- 创建cms_content_like表(用户点赞记录)
|
||||||
|
CREATE TABLE `cms_content_like` (
|
||||||
|
`like_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '点赞记录ID',
|
||||||
|
`user_id` bigint(20) NOT NULL COMMENT '用户ID',
|
||||||
|
`user_name` varchar(50) NOT NULL COMMENT '用户名',
|
||||||
|
`content_id` bigint(20) NOT NULL COMMENT '内容ID',
|
||||||
|
`content_title` varchar(200) NOT NULL COMMENT '内容标题',
|
||||||
|
`like_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '点赞时间',
|
||||||
|
`delete_flag` tinyint(4) NOT NULL DEFAULT '0' COMMENT '删除标志:0未删除,1已删除',
|
||||||
|
PRIMARY KEY (`like_id`),
|
||||||
|
KEY `idx_user_id` (`user_id`),
|
||||||
|
KEY `idx_content_id` (`content_id`),
|
||||||
|
KEY `idx_like_time` (`like_time`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='CMS内容点赞记录表';
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
-- 创建cms_content_view表(用户查看记录)
|
||||||
|
CREATE TABLE `cms_content_view` (
|
||||||
|
`view_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '查看记录ID',
|
||||||
|
`user_id` bigint(20) NOT NULL COMMENT '用户ID',
|
||||||
|
`user_name` varchar(50) NOT NULL COMMENT '用户名',
|
||||||
|
`content_id` bigint(20) NOT NULL COMMENT '内容ID',
|
||||||
|
`content_title` varchar(200) NOT NULL COMMENT '内容标题',
|
||||||
|
`view_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '查看时间',
|
||||||
|
`delete_flag` tinyint(4) NOT NULL DEFAULT '0' COMMENT '删除标志:0未删除,1已删除',
|
||||||
|
PRIMARY KEY (`view_id`),
|
||||||
|
KEY `idx_user_id` (`user_id`),
|
||||||
|
KEY `idx_content_id` (`content_id`),
|
||||||
|
KEY `idx_view_time` (`view_time`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='CMS内容查看记录表';
|
||||||
8
pom.xml
8
pom.xml
|
|
@ -241,6 +241,13 @@
|
||||||
<version>2.12.0</version>
|
<version>2.12.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- SMS4J 短信发送框架 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.dromara.sms4j</groupId>
|
||||||
|
<artifactId>sms4j-spring-boot-starter</artifactId>
|
||||||
|
<version>3.3.5</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
@ -270,6 +277,7 @@
|
||||||
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED</arg>
|
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED</arg>
|
||||||
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED</arg>
|
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED</arg>
|
||||||
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED</arg>
|
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED</arg>
|
||||||
|
<arg>-parameters</arg>
|
||||||
</compilerArgs>
|
</compilerArgs>
|
||||||
<annotationProcessorPaths>
|
<annotationProcessorPaths>
|
||||||
<path>
|
<path>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,299 @@
|
||||||
|
package com.kexue.skills.common;
|
||||||
|
|
||||||
|
import com.kexue.skills.exception.BizException;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言工具类,用于封装业务异常的抛出
|
||||||
|
* 参考continue-admin的实现方式
|
||||||
|
*
|
||||||
|
* @author 王志维
|
||||||
|
* @since 2026-01-26
|
||||||
|
*/
|
||||||
|
public class Assert {
|
||||||
|
|
||||||
|
private Assert() {
|
||||||
|
// 私有构造方法,禁止实例化
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言表达式为true,如果为false则抛出BizException
|
||||||
|
*
|
||||||
|
* @param expression 表达式
|
||||||
|
* @param message 异常信息
|
||||||
|
*/
|
||||||
|
public static void isTrue(boolean expression, String message) {
|
||||||
|
if (!expression) {
|
||||||
|
throw new BizException(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言表达式为true,如果为false则抛出BizException
|
||||||
|
*
|
||||||
|
* @param expression 表达式
|
||||||
|
* @param errorCode 错误码
|
||||||
|
* @param message 异常信息
|
||||||
|
*/
|
||||||
|
public static void isTrue(boolean expression, long errorCode, String message) {
|
||||||
|
if (!expression) {
|
||||||
|
throw new BizException(errorCode, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言表达式为false,如果为true则抛出BizException
|
||||||
|
*
|
||||||
|
* @param expression 表达式
|
||||||
|
* @param message 异常信息
|
||||||
|
*/
|
||||||
|
public static void isFalse(boolean expression, String message) {
|
||||||
|
if (expression) {
|
||||||
|
throw new BizException(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言表达式为false,如果为true则抛出BizException
|
||||||
|
*
|
||||||
|
* @param expression 表达式
|
||||||
|
* @param errorCode 错误码
|
||||||
|
* @param message 异常信息
|
||||||
|
*/
|
||||||
|
public static void isFalse(boolean expression, long errorCode, String message) {
|
||||||
|
if (expression) {
|
||||||
|
throw new BizException(errorCode, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言对象不为null,如果为null则抛出BizException
|
||||||
|
*
|
||||||
|
* @param object 对象
|
||||||
|
* @param message 异常信息
|
||||||
|
*/
|
||||||
|
public static void notNull(Object object, String message) {
|
||||||
|
if (object == null) {
|
||||||
|
throw new BizException(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言对象不为null,如果为null则抛出BizException
|
||||||
|
*
|
||||||
|
* @param object 对象
|
||||||
|
* @param errorCode 错误码
|
||||||
|
* @param message 异常信息
|
||||||
|
*/
|
||||||
|
public static void notNull(Object object, long errorCode, String message) {
|
||||||
|
if (object == null) {
|
||||||
|
throw new BizException(errorCode, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言对象为null,如果不为null则抛出BizException
|
||||||
|
*
|
||||||
|
* @param object 对象
|
||||||
|
* @param message 异常信息
|
||||||
|
*/
|
||||||
|
public static void isNull(Object object, String message) {
|
||||||
|
if (object != null) {
|
||||||
|
throw new BizException(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言对象为null,如果不为null则抛出BizException
|
||||||
|
*
|
||||||
|
* @param object 对象
|
||||||
|
* @param errorCode 错误码
|
||||||
|
* @param message 异常信息
|
||||||
|
*/
|
||||||
|
public static void isNull(Object object, long errorCode, String message) {
|
||||||
|
if (object != null) {
|
||||||
|
throw new BizException(errorCode, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言字符串不为空,如果为空则抛出BizException
|
||||||
|
*
|
||||||
|
* @param str 字符串
|
||||||
|
* @param message 异常信息
|
||||||
|
*/
|
||||||
|
public static void notEmpty(String str, String message) {
|
||||||
|
if (str == null || str.isEmpty()) {
|
||||||
|
throw new BizException(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言字符串不为空,如果为空则抛出BizException
|
||||||
|
*
|
||||||
|
* @param str 字符串
|
||||||
|
* @param errorCode 错误码
|
||||||
|
* @param message 异常信息
|
||||||
|
*/
|
||||||
|
public static void notEmpty(String str, long errorCode, String message) {
|
||||||
|
if (str == null || str.isEmpty()) {
|
||||||
|
throw new BizException(errorCode, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言字符串不为空白,如果为空白则抛出BizException
|
||||||
|
*
|
||||||
|
* @param str 字符串
|
||||||
|
* @param message 异常信息
|
||||||
|
*/
|
||||||
|
public static void notBlank(String str, String message) {
|
||||||
|
if (str == null || str.trim().isEmpty()) {
|
||||||
|
throw new BizException(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言字符串不为空白,如果为空白则抛出BizException
|
||||||
|
*
|
||||||
|
* @param str 字符串
|
||||||
|
* @param errorCode 错误码
|
||||||
|
* @param message 异常信息
|
||||||
|
*/
|
||||||
|
public static void notBlank(String str, long errorCode, String message) {
|
||||||
|
if (str == null || str.trim().isEmpty()) {
|
||||||
|
throw new BizException(errorCode, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言集合不为空,如果为空则抛出BizException
|
||||||
|
*
|
||||||
|
* @param collection 集合
|
||||||
|
* @param message 异常信息
|
||||||
|
*/
|
||||||
|
public static void notEmpty(Collection<?> collection, String message) {
|
||||||
|
if (collection == null || collection.isEmpty()) {
|
||||||
|
throw new BizException(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言集合不为空,如果为空则抛出BizException
|
||||||
|
*
|
||||||
|
* @param collection 集合
|
||||||
|
* @param errorCode 错误码
|
||||||
|
* @param message 异常信息
|
||||||
|
*/
|
||||||
|
public static void notEmpty(Collection<?> collection, long errorCode, String message) {
|
||||||
|
if (collection == null || collection.isEmpty()) {
|
||||||
|
throw new BizException(errorCode, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言Map不为空,如果为空则抛出BizException
|
||||||
|
*
|
||||||
|
* @param map Map
|
||||||
|
* @param message 异常信息
|
||||||
|
*/
|
||||||
|
public static void notEmpty(Map<?, ?> map, String message) {
|
||||||
|
if (map == null || map.isEmpty()) {
|
||||||
|
throw new BizException(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言Map不为空,如果为空则抛出BizException
|
||||||
|
*
|
||||||
|
* @param map Map
|
||||||
|
* @param errorCode 错误码
|
||||||
|
* @param message 异常信息
|
||||||
|
*/
|
||||||
|
public static void notEmpty(Map<?, ?> map, long errorCode, String message) {
|
||||||
|
if (map == null || map.isEmpty()) {
|
||||||
|
throw new BizException(errorCode, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言数组不为空,如果为空则抛出BizException
|
||||||
|
*
|
||||||
|
* @param array 数组
|
||||||
|
* @param message 异常信息
|
||||||
|
*/
|
||||||
|
public static void notEmpty(Object[] array, String message) {
|
||||||
|
if (array == null || array.length == 0) {
|
||||||
|
throw new BizException(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言数组不为空,如果为空则抛出BizException
|
||||||
|
*
|
||||||
|
* @param array 数组
|
||||||
|
* @param errorCode 错误码
|
||||||
|
* @param message 异常信息
|
||||||
|
*/
|
||||||
|
public static void notEmpty(Object[] array, long errorCode, String message) {
|
||||||
|
if (array == null || array.length == 0) {
|
||||||
|
throw new BizException(errorCode, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言两个对象相等,如果不相等则抛出BizException
|
||||||
|
*
|
||||||
|
* @param obj1 对象1
|
||||||
|
* @param obj2 对象2
|
||||||
|
* @param message 异常信息
|
||||||
|
*/
|
||||||
|
public static void equals(Object obj1, Object obj2, String message) {
|
||||||
|
if (!obj1.equals(obj2)) {
|
||||||
|
throw new BizException(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言两个对象相等,如果不相等则抛出BizException
|
||||||
|
*
|
||||||
|
* @param obj1 对象1
|
||||||
|
* @param obj2 对象2
|
||||||
|
* @param errorCode 错误码
|
||||||
|
* @param message 异常信息
|
||||||
|
*/
|
||||||
|
public static void equals(Object obj1, Object obj2, long errorCode, String message) {
|
||||||
|
if (!obj1.equals(obj2)) {
|
||||||
|
throw new BizException(errorCode, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言两个对象不相等,如果相等则抛出BizException
|
||||||
|
*
|
||||||
|
* @param obj1 对象1
|
||||||
|
* @param obj2 对象2
|
||||||
|
* @param message 异常信息
|
||||||
|
*/
|
||||||
|
public static void notEquals(Object obj1, Object obj2, String message) {
|
||||||
|
if (obj1.equals(obj2)) {
|
||||||
|
throw new BizException(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言两个对象不相等,如果相等则抛出BizException
|
||||||
|
*
|
||||||
|
* @param obj1 对象1
|
||||||
|
* @param obj2 对象2
|
||||||
|
* @param errorCode 错误码
|
||||||
|
* @param message 异常信息
|
||||||
|
*/
|
||||||
|
public static void notEquals(Object obj1, Object obj2, long errorCode, String message) {
|
||||||
|
if (obj1.equals(obj2)) {
|
||||||
|
throw new BizException(errorCode, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
package com.kexue.skills.config;
|
||||||
|
|
||||||
|
import com.kexue.skills.interceptor.CorsFilter;
|
||||||
|
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 过滤器配置类
|
||||||
|
* 用于注册自定义过滤器
|
||||||
|
*
|
||||||
|
* @author 王志维
|
||||||
|
* @since 2026-01-26
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class FilterConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册CORS过滤器
|
||||||
|
*
|
||||||
|
* @return FilterRegistrationBean
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public FilterRegistrationBean<CorsFilter> corsFilterRegistrationBean() {
|
||||||
|
FilterRegistrationBean<CorsFilter> registrationBean = new FilterRegistrationBean<>();
|
||||||
|
registrationBean.setFilter(new CorsFilter());
|
||||||
|
registrationBean.addUrlPatterns("/*");
|
||||||
|
registrationBean.setOrder(1);
|
||||||
|
return registrationBean;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,11 +1,17 @@
|
||||||
package com.kexue.skills.config;
|
package com.kexue.skills.config;
|
||||||
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.http.converter.HttpMessageConverter;
|
||||||
|
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||||
|
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||||
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
|
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/** mvc配置,例如:资源映射、视图解析、拦截器等
|
/** mvc配置,例如:资源映射、视图解析、拦截器等
|
||||||
*
|
*
|
||||||
**/
|
**/
|
||||||
|
|
@ -53,6 +59,17 @@ public class WebMvcConfig implements WebMvcConfigurer {
|
||||||
registry.addViewController("/submitJournalUpload").setViewName("submitJournalUpload");*/
|
registry.addViewController("/submitJournalUpload").setViewName("submitJournalUpload");*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
|
||||||
|
// 配置字符串转换器,使用UTF-8编码
|
||||||
|
StringHttpMessageConverter stringConverter = new StringHttpMessageConverter(StandardCharsets.UTF_8);
|
||||||
|
converters.add(stringConverter);
|
||||||
|
|
||||||
|
// 配置JSON转换器,使用UTF-8编码
|
||||||
|
MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
|
||||||
|
jsonConverter.setDefaultCharset(StandardCharsets.UTF_8);
|
||||||
|
converters.add(jsonConverter);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addInterceptors(InterceptorRegistry registry) {
|
public void addInterceptors(InterceptorRegistry registry) {
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ public class CaptchaController {
|
||||||
*/
|
*/
|
||||||
@PostMapping("/verify")
|
@PostMapping("/verify")
|
||||||
@Operation(summary = "验证验证码", description = "验证验证码")
|
@Operation(summary = "验证验证码", description = "验证验证码")
|
||||||
public CommonResult<Boolean> verifyCaptcha(@RequestParam String captchaId, @RequestParam String captchaValue) {
|
public CommonResult<Boolean> verifyCaptcha(@RequestParam("captchaId") String captchaId, @RequestParam("captchaValue") String captchaValue) {
|
||||||
// 验证码开关逻辑:只有启用时才验证验证码
|
// 验证码开关逻辑:只有启用时才验证验证码
|
||||||
if (!captchaConfig.isEnabled()) {
|
if (!captchaConfig.isEnabled()) {
|
||||||
return CommonResult.success(true);
|
return CommonResult.success(true);
|
||||||
|
|
|
||||||
|
|
@ -106,11 +106,11 @@ public class CmsContentController {
|
||||||
@PostMapping("/updateAuditStatus")
|
@PostMapping("/updateAuditStatus")
|
||||||
@Operation(summary = "更新审核状态", description = "更新审核状态")
|
@Operation(summary = "更新审核状态", description = "更新审核状态")
|
||||||
@RequireAuth
|
@RequireAuth
|
||||||
public CommonResult<Boolean> updateAuditStatus(@RequestParam Long contentId,
|
public CommonResult<Boolean> updateAuditStatus(@RequestParam("contentId") Long contentId,
|
||||||
@RequestParam Integer auditStatus,
|
@RequestParam("auditStatus") Integer auditStatus,
|
||||||
@RequestParam Long reviewerId,
|
@RequestParam("reviewerId") Long reviewerId,
|
||||||
@RequestParam String reviewerName,
|
@RequestParam("reviewerName") String reviewerName,
|
||||||
@RequestParam(required = false) String auditComment) {
|
@RequestParam(value = "auditComment", required = false) String auditComment) {
|
||||||
return CommonResult.success(cmsContentService.updateAuditStatus(contentId, auditStatus, reviewerId, reviewerName, auditComment, reviewerName) > 0);
|
return CommonResult.success(cmsContentService.updateAuditStatus(contentId, auditStatus, reviewerId, reviewerName, auditComment, reviewerName) > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -126,10 +126,10 @@ public class CmsContentController {
|
||||||
@PostMapping("/updatePublishStatus")
|
@PostMapping("/updatePublishStatus")
|
||||||
@Operation(summary = "更新发布状态", description = "更新发布状态")
|
@Operation(summary = "更新发布状态", description = "更新发布状态")
|
||||||
@RequireAuth
|
@RequireAuth
|
||||||
public CommonResult<Boolean> updatePublishStatus(@RequestParam Long contentId,
|
public CommonResult<Boolean> updatePublishStatus(@RequestParam("contentId") Long contentId,
|
||||||
@RequestParam Integer publishStatus,
|
@RequestParam("publishStatus") Integer publishStatus,
|
||||||
@RequestParam(required = false) String publishTime,
|
@RequestParam(value = "publishTime", required = false) String publishTime,
|
||||||
@RequestParam String updateBy) {
|
@RequestParam("updateBy") String updateBy) {
|
||||||
return CommonResult.success(cmsContentService.updatePublishStatus(contentId, publishStatus, publishTime, updateBy) > 0);
|
return CommonResult.success(cmsContentService.updatePublishStatus(contentId, publishStatus, publishTime, updateBy) > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@ package com.kexue.skills.controller;
|
||||||
|
|
||||||
import com.kexue.skills.annotation.PreventDuplicateSubmission;
|
import com.kexue.skills.annotation.PreventDuplicateSubmission;
|
||||||
import com.kexue.skills.common.CommonResult;
|
import com.kexue.skills.common.CommonResult;
|
||||||
import com.kexue.skills.entity.SysUser;
|
|
||||||
import com.kexue.skills.entity.request.LoginDto;
|
import com.kexue.skills.entity.request.LoginDto;
|
||||||
import com.kexue.skills.entity.request.LoginUserDto;
|
import com.kexue.skills.entity.request.LoginUserDto;
|
||||||
|
import com.kexue.skills.entity.request.PhoneLoginDto;
|
||||||
import com.kexue.skills.service.SysUserService;
|
import com.kexue.skills.service.SysUserService;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
|
@ -35,7 +35,7 @@ public class LoginController {
|
||||||
* @param loginDto 登录信息
|
* @param loginDto 登录信息
|
||||||
* @return 登录结果
|
* @return 登录结果
|
||||||
*/
|
*/
|
||||||
@PostMapping("/do")
|
@PostMapping("/accountLogin")
|
||||||
@Operation(summary = "用户登录", description = "用户登录")
|
@Operation(summary = "用户登录", description = "用户登录")
|
||||||
@PreventDuplicateSubmission
|
@PreventDuplicateSubmission
|
||||||
public CommonResult<LoginUserDto> login(@RequestBody LoginDto loginDto) {
|
public CommonResult<LoginUserDto> login(@RequestBody LoginDto loginDto) {
|
||||||
|
|
@ -47,7 +47,7 @@ public class LoginController {
|
||||||
*
|
*
|
||||||
* @return 登出结果
|
* @return 登出结果
|
||||||
*/
|
*/
|
||||||
@PostMapping("/logout")
|
@PostMapping("/accountLogout")
|
||||||
@Operation(summary = "用户登出", description = "用户登出")
|
@Operation(summary = "用户登出", description = "用户登出")
|
||||||
public CommonResult<String> logout() {
|
public CommonResult<String> logout() {
|
||||||
// 使用Sa-Token登出
|
// 使用Sa-Token登出
|
||||||
|
|
@ -55,5 +55,34 @@ public class LoginController {
|
||||||
return CommonResult.success("登出成功");
|
return CommonResult.success("登出成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送手机验证码
|
||||||
|
*
|
||||||
|
* @param phone 手机号
|
||||||
|
* @return 发送结果
|
||||||
|
*/
|
||||||
|
@PostMapping("/sendCode")
|
||||||
|
@Operation(summary = "发送手机验证码", description = "向指定手机号发送登录验证码")
|
||||||
|
public CommonResult<String> sendCode(@RequestParam("phone") String phone) {
|
||||||
|
boolean success = sysUserService.sendSmsCode(phone);
|
||||||
|
if (success) {
|
||||||
|
return CommonResult.success("验证码发送成功");
|
||||||
|
} else {
|
||||||
|
return CommonResult.failed("验证码发送失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手机号登录
|
||||||
|
*
|
||||||
|
* @param phoneLoginDto 手机号登录信息
|
||||||
|
* @return 登录结果
|
||||||
|
*/
|
||||||
|
@PostMapping("/phoneLogin")
|
||||||
|
@Operation(summary = "手机号登录", description = "使用手机号和验证码登录")
|
||||||
|
public CommonResult<LoginUserDto> phoneLogin(@RequestBody PhoneLoginDto phoneLoginDto) {
|
||||||
|
return CommonResult.success(sysUserService.phoneLogin(phoneLoginDto));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,4 +46,10 @@ public class Account extends BaseEntity implements Serializable {
|
||||||
@Schema(description ="是否删除 :0 未删除,1已删除")
|
@Schema(description ="是否删除 :0 未删除,1已删除")
|
||||||
private Integer deleteFlag;
|
private Integer deleteFlag;
|
||||||
|
|
||||||
|
@Schema(description ="创建人")
|
||||||
|
private String createBy;
|
||||||
|
|
||||||
|
@Schema(description ="更新人")
|
||||||
|
private String updateBy;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,129 @@
|
||||||
|
package com.kexue.skills.entity;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CMS内容点赞记录实体类
|
||||||
|
*
|
||||||
|
* @author 王志维
|
||||||
|
* @since 2026-01-26
|
||||||
|
*/
|
||||||
|
public class CmsContentLike {
|
||||||
|
/**
|
||||||
|
* 点赞记录ID
|
||||||
|
*/
|
||||||
|
private Long likeId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户ID
|
||||||
|
*/
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户名
|
||||||
|
*/
|
||||||
|
private String userName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 内容ID
|
||||||
|
*/
|
||||||
|
private Long contentId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 内容标题
|
||||||
|
*/
|
||||||
|
private String contentTitle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 点赞时间
|
||||||
|
*/
|
||||||
|
private Date likeTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除标志:0未删除,1已删除
|
||||||
|
*/
|
||||||
|
private Integer deleteFlag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建人
|
||||||
|
*/
|
||||||
|
private String createBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新人
|
||||||
|
*/
|
||||||
|
private String updateBy;
|
||||||
|
|
||||||
|
// getter和setter方法
|
||||||
|
public Long getLikeId() {
|
||||||
|
return likeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLikeId(Long likeId) {
|
||||||
|
this.likeId = likeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getUserId() {
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserId(Long userId) {
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUserName() {
|
||||||
|
return userName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserName(String userName) {
|
||||||
|
this.userName = userName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getContentId() {
|
||||||
|
return contentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContentId(Long contentId) {
|
||||||
|
this.contentId = contentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContentTitle() {
|
||||||
|
return contentTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContentTitle(String contentTitle) {
|
||||||
|
this.contentTitle = contentTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getLikeTime() {
|
||||||
|
return likeTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLikeTime(Date likeTime) {
|
||||||
|
this.likeTime = likeTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getDeleteFlag() {
|
||||||
|
return deleteFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeleteFlag(Integer deleteFlag) {
|
||||||
|
this.deleteFlag = deleteFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCreateBy() {
|
||||||
|
return createBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreateBy(String createBy) {
|
||||||
|
this.createBy = createBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUpdateBy() {
|
||||||
|
return updateBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdateBy(String updateBy) {
|
||||||
|
this.updateBy = updateBy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,129 @@
|
||||||
|
package com.kexue.skills.entity;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CMS内容查看记录实体类
|
||||||
|
*
|
||||||
|
* @author 王志维
|
||||||
|
* @since 2026-01-26
|
||||||
|
*/
|
||||||
|
public class CmsContentView {
|
||||||
|
/**
|
||||||
|
* 查看记录ID
|
||||||
|
*/
|
||||||
|
private Long viewId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户ID
|
||||||
|
*/
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户名
|
||||||
|
*/
|
||||||
|
private String userName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 内容ID
|
||||||
|
*/
|
||||||
|
private Long contentId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 内容标题
|
||||||
|
*/
|
||||||
|
private String contentTitle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查看时间
|
||||||
|
*/
|
||||||
|
private Date viewTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除标志:0未删除,1已删除
|
||||||
|
*/
|
||||||
|
private Integer deleteFlag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建人
|
||||||
|
*/
|
||||||
|
private String createBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新人
|
||||||
|
*/
|
||||||
|
private String updateBy;
|
||||||
|
|
||||||
|
// getter和setter方法
|
||||||
|
public Long getViewId() {
|
||||||
|
return viewId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setViewId(Long viewId) {
|
||||||
|
this.viewId = viewId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getUserId() {
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserId(Long userId) {
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUserName() {
|
||||||
|
return userName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserName(String userName) {
|
||||||
|
this.userName = userName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getContentId() {
|
||||||
|
return contentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContentId(Long contentId) {
|
||||||
|
this.contentId = contentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContentTitle() {
|
||||||
|
return contentTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContentTitle(String contentTitle) {
|
||||||
|
this.contentTitle = contentTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getViewTime() {
|
||||||
|
return viewTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setViewTime(Date viewTime) {
|
||||||
|
this.viewTime = viewTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getDeleteFlag() {
|
||||||
|
return deleteFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeleteFlag(Integer deleteFlag) {
|
||||||
|
this.deleteFlag = deleteFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCreateBy() {
|
||||||
|
return createBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreateBy(String createBy) {
|
||||||
|
this.createBy = createBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUpdateBy() {
|
||||||
|
return updateBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdateBy(String updateBy) {
|
||||||
|
this.updateBy = updateBy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -61,4 +61,10 @@ public class ContentPurchase extends BaseEntity implements Serializable {
|
||||||
@Schema(description ="是否删除 :0 未删除,1已删除")
|
@Schema(description ="是否删除 :0 未删除,1已删除")
|
||||||
private Integer deleteFlag;
|
private Integer deleteFlag;
|
||||||
|
|
||||||
|
@Schema(description ="创建人")
|
||||||
|
private String createBy;
|
||||||
|
|
||||||
|
@Schema(description ="更新人")
|
||||||
|
private String updateBy;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -50,4 +50,10 @@ public class Customer extends BaseEntity implements Serializable {
|
||||||
@Schema(description ="是否删除 :0 未删除,1已删除")
|
@Schema(description ="是否删除 :0 未删除,1已删除")
|
||||||
private Integer deleteFlag;
|
private Integer deleteFlag;
|
||||||
|
|
||||||
|
@Schema(description ="创建人")
|
||||||
|
private String createBy;
|
||||||
|
|
||||||
|
@Schema(description ="更新人")
|
||||||
|
private String updateBy;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -84,4 +84,10 @@ public class PaymentOrder extends BaseEntity implements Serializable {
|
||||||
@Schema(description ="是否删除 :0 未删除,1已删除")
|
@Schema(description ="是否删除 :0 未删除,1已删除")
|
||||||
private Integer deleteFlag;
|
private Integer deleteFlag;
|
||||||
|
|
||||||
|
@Schema(description ="创建人")
|
||||||
|
private String createBy;
|
||||||
|
|
||||||
|
@Schema(description ="更新人")
|
||||||
|
private String updateBy;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -48,4 +48,10 @@ public class PointsAccount extends BaseEntity implements Serializable {
|
||||||
@Schema(description ="是否删除 :0 未删除,1已删除")
|
@Schema(description ="是否删除 :0 未删除,1已删除")
|
||||||
private Integer deleteFlag;
|
private Integer deleteFlag;
|
||||||
|
|
||||||
|
@Schema(description ="创建人")
|
||||||
|
private String createBy;
|
||||||
|
|
||||||
|
@Schema(description ="更新人")
|
||||||
|
private String updateBy;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -50,4 +50,10 @@ public class Supplier extends BaseEntity implements Serializable {
|
||||||
@Schema(description ="是否删除 :0 未删除,1已删除")
|
@Schema(description ="是否删除 :0 未删除,1已删除")
|
||||||
private Integer deleteFlag;
|
private Integer deleteFlag;
|
||||||
|
|
||||||
|
@Schema(description ="创建人")
|
||||||
|
private String createBy;
|
||||||
|
|
||||||
|
@Schema(description ="更新人")
|
||||||
|
private String updateBy;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -44,4 +44,17 @@ public class SysDict extends BaseEntity implements Serializable {
|
||||||
@Schema(description ="创建时间")
|
@Schema(description ="创建时间")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
|
@Schema(description ="更新时间")
|
||||||
|
private Date updateTime;
|
||||||
|
|
||||||
|
@Schema(description ="是否删除 :0 未删除,1已删除")
|
||||||
|
private Integer deleteFlag;
|
||||||
|
|
||||||
|
@Schema(description ="创建人")
|
||||||
|
private String createBy;
|
||||||
|
|
||||||
|
@Schema(description ="更新人")
|
||||||
|
private String updateBy;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ package com.kexue.skills.entity;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import com.kexue.skills.entity.base.BaseEntity;
|
import com.kexue.skills.entity.base.BaseEntity;
|
||||||
import com.kexue.skills.entity.base.BaseQueryDto;
|
import com.kexue.skills.entity.base.BaseQueryDto;
|
||||||
|
import java.util.Date;
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
@ -45,4 +46,21 @@ public class SysLog extends BaseEntity implements Serializable {
|
||||||
@Schema(description ="备注")
|
@Schema(description ="备注")
|
||||||
private String note;
|
private String note;
|
||||||
|
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
|
@Schema(description ="创建时间")
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
|
@Schema(description ="更新时间")
|
||||||
|
private Date updateTime;
|
||||||
|
|
||||||
|
@Schema(description ="是否删除 :0 未删除,1已删除")
|
||||||
|
private Integer deleteFlag;
|
||||||
|
|
||||||
|
@Schema(description ="创建人")
|
||||||
|
private String createBy;
|
||||||
|
|
||||||
|
@Schema(description ="更新人")
|
||||||
|
private String updateBy;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ package com.kexue.skills.entity;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import com.kexue.skills.entity.base.BaseEntity;
|
import com.kexue.skills.entity.base.BaseEntity;
|
||||||
import com.kexue.skills.entity.base.BaseQueryDto;
|
import com.kexue.skills.entity.base.BaseQueryDto;
|
||||||
|
import java.util.Date;
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
@ -45,4 +46,18 @@ public class SysMenu extends BaseEntity implements Serializable {
|
||||||
@Schema(description ="删除标记")
|
@Schema(description ="删除标记")
|
||||||
private Object deleteFlag;
|
private Object deleteFlag;
|
||||||
|
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
|
@Schema(description ="创建时间")
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
|
@Schema(description ="更新时间")
|
||||||
|
private Date updateTime;
|
||||||
|
|
||||||
|
@Schema(description ="创建人")
|
||||||
|
private String createBy;
|
||||||
|
|
||||||
|
@Schema(description ="更新人")
|
||||||
|
private String updateBy;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,10 +32,20 @@ public class SysRole extends BaseEntity implements Serializable {
|
||||||
@Schema(description ="创建时间")
|
@Schema(description ="创建时间")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
|
@Schema(description ="更新时间")
|
||||||
|
private Date updateTime;
|
||||||
|
|
||||||
@Schema(description ="备注")
|
@Schema(description ="备注")
|
||||||
private String remark;
|
private String remark;
|
||||||
|
|
||||||
@Schema(description ="删除标记")
|
@Schema(description ="删除标记")
|
||||||
private String deleteFlag;
|
private String deleteFlag;
|
||||||
|
|
||||||
|
@Schema(description ="创建人")
|
||||||
|
private String createBy;
|
||||||
|
|
||||||
|
@Schema(description ="更新人")
|
||||||
|
private String updateBy;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,10 +47,20 @@ public class SysUser extends BaseEntity implements Serializable {
|
||||||
@Schema(description ="创建时间")
|
@Schema(description ="创建时间")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
|
@Schema(description ="更新时间")
|
||||||
|
private Date updateTime;
|
||||||
|
|
||||||
@Schema(description ="是否启用(1启用,2禁用)")
|
@Schema(description ="是否启用(1启用,2禁用)")
|
||||||
private Integer enable;
|
private Integer enable;
|
||||||
|
|
||||||
@Schema(description ="是否删除 :0 未删除,1已删除")
|
@Schema(description ="是否删除 :0 未删除,1已删除")
|
||||||
private Integer deleteFlag;
|
private Integer deleteFlag;
|
||||||
|
|
||||||
|
@Schema(description ="创建人")
|
||||||
|
private String createBy;
|
||||||
|
|
||||||
|
@Schema(description ="更新人")
|
||||||
|
private String updateBy;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ package com.kexue.skills.entity;
|
||||||
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
import com.kexue.skills.entity.base.BaseEntity;
|
import com.kexue.skills.entity.base.BaseEntity;
|
||||||
import com.kexue.skills.entity.base.BaseQueryDto;
|
import com.kexue.skills.entity.base.BaseQueryDto;
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
|
@ -24,4 +26,21 @@ public class SysUserRole extends BaseEntity implements Serializable {
|
||||||
@Schema(description ="用户ID")
|
@Schema(description ="用户ID")
|
||||||
private Long userId;
|
private Long userId;
|
||||||
|
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
|
@Schema(description ="创建时间")
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
|
@Schema(description ="更新时间")
|
||||||
|
private Date updateTime;
|
||||||
|
|
||||||
|
@Schema(description ="是否删除 :0 未删除,1已删除")
|
||||||
|
private Integer deleteFlag;
|
||||||
|
|
||||||
|
@Schema(description ="创建人")
|
||||||
|
private String createBy;
|
||||||
|
|
||||||
|
@Schema(description ="更新人")
|
||||||
|
private String updateBy;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,4 +44,24 @@ public class LoginUser {
|
||||||
* token
|
* token
|
||||||
*/
|
*/
|
||||||
private String token;
|
private String token;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最近点赞的20条记录
|
||||||
|
*/
|
||||||
|
private List<Long> favorites;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最近查看的20条记录
|
||||||
|
*/
|
||||||
|
private List<Long> history;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最近创建的20条记录
|
||||||
|
*/
|
||||||
|
private List<Long> create;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最近购买的20条记录
|
||||||
|
*/
|
||||||
|
private List<Long> has;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ import com.kexue.skills.entity.SysUser;
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.annotations.ApiModel;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author 维哥
|
* @author 维哥
|
||||||
* @Description
|
* @Description
|
||||||
|
|
@ -13,4 +15,24 @@ import lombok.Data;
|
||||||
@ApiModel(value = "登录用户信息")
|
@ApiModel(value = "登录用户信息")
|
||||||
public class LoginUserDto extends SysUser {
|
public class LoginUserDto extends SysUser {
|
||||||
String token;
|
String token;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最近点赞的20条记录
|
||||||
|
*/
|
||||||
|
List<Long> favorites;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最近查看的20条记录
|
||||||
|
*/
|
||||||
|
List<Long> history;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最近创建的20条记录
|
||||||
|
*/
|
||||||
|
List<Long> create;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最近购买的20条记录
|
||||||
|
*/
|
||||||
|
List<Long> has;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
package com.kexue.skills.entity.request;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手机号登录请求DTO
|
||||||
|
*
|
||||||
|
* @author 王志维
|
||||||
|
* @since 2026-01-22
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@ApiModel(value = "手机号登录信息")
|
||||||
|
public class PhoneLoginDto implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description ="手机号")
|
||||||
|
private String phone;
|
||||||
|
|
||||||
|
@Schema(description ="验证码")
|
||||||
|
private String code;
|
||||||
|
}
|
||||||
|
|
@ -12,6 +12,11 @@ public class CorsFilter implements Filter {
|
||||||
HttpServletRequest request = (HttpServletRequest) req;
|
HttpServletRequest request = (HttpServletRequest) req;
|
||||||
HttpServletResponse response = (HttpServletResponse) res;
|
HttpServletResponse response = (HttpServletResponse) res;
|
||||||
|
|
||||||
|
// 设置字符编码
|
||||||
|
request.setCharacterEncoding("UTF-8");
|
||||||
|
response.setCharacterEncoding("UTF-8");
|
||||||
|
response.setContentType("application/json;charset=UTF-8");
|
||||||
|
|
||||||
// 允许所有来源
|
// 允许所有来源
|
||||||
response.setHeader("Access-Control-Allow-Origin", "*");
|
response.setHeader("Access-Control-Allow-Origin", "*");
|
||||||
response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
|
response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
package com.kexue.skills.mapper;
|
||||||
|
|
||||||
|
import com.kexue.skills.entity.CmsContentLike;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CMS内容点赞记录Mapper接口
|
||||||
|
*
|
||||||
|
* @author 王志维
|
||||||
|
* @since 2026-01-26
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface CmsContentLikeMapper {
|
||||||
|
/**
|
||||||
|
* 新增点赞记录
|
||||||
|
*
|
||||||
|
* @param cmsContentLike 点赞记录对象
|
||||||
|
* @return 受影响的行数
|
||||||
|
*/
|
||||||
|
int insert(CmsContentLike cmsContentLike);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除点赞记录
|
||||||
|
*
|
||||||
|
* @param likeId 点赞记录ID
|
||||||
|
* @return 受影响的行数
|
||||||
|
*/
|
||||||
|
int deleteById(Long likeId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新点赞记录
|
||||||
|
*
|
||||||
|
* @param cmsContentLike 点赞记录对象
|
||||||
|
* @return 受影响的行数
|
||||||
|
*/
|
||||||
|
int update(CmsContentLike cmsContentLike);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询点赞记录
|
||||||
|
*
|
||||||
|
* @param likeId 点赞记录ID
|
||||||
|
* @return 点赞记录对象
|
||||||
|
*/
|
||||||
|
CmsContentLike queryById(Long likeId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询用户是否已点赞该内容
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @param contentId 内容ID
|
||||||
|
* @return 点赞记录对象,不存在则返回null
|
||||||
|
*/
|
||||||
|
CmsContentLike queryByUserIdAndContentId(@Param("userId") Long userId, @Param("contentId") Long contentId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询用户最近的点赞记录
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @param limit 查询数量
|
||||||
|
* @return 点赞记录列表
|
||||||
|
*/
|
||||||
|
List<Long> queryRecentLikesByUserId(@Param("userId") Long userId, @Param("limit") int limit);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询内容的点赞记录数量
|
||||||
|
*
|
||||||
|
* @param contentId 内容ID
|
||||||
|
* @return 点赞记录数量
|
||||||
|
*/
|
||||||
|
int countByContentId(Long contentId);
|
||||||
|
}
|
||||||
|
|
@ -108,4 +108,13 @@ public interface CmsContentMapper {
|
||||||
* @return 影响行数
|
* @return 影响行数
|
||||||
*/
|
*/
|
||||||
int increaseViewCount(Long contentId);
|
int increaseViewCount(Long contentId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询用户最近创建的内容ID列表
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @param limit 查询数量
|
||||||
|
* @return 内容ID列表
|
||||||
|
*/
|
||||||
|
List<Long> queryRecentCreatedByUserId(@Param("userId") Long userId, @Param("limit") int limit);
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
package com.kexue.skills.mapper;
|
||||||
|
|
||||||
|
import com.kexue.skills.entity.CmsContentView;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CMS内容查看记录Mapper接口
|
||||||
|
*
|
||||||
|
* @author 王志维
|
||||||
|
* @since 2026-01-26
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface CmsContentViewMapper {
|
||||||
|
/**
|
||||||
|
* 新增查看记录
|
||||||
|
*
|
||||||
|
* @param cmsContentView 查看记录对象
|
||||||
|
* @return 受影响的行数
|
||||||
|
*/
|
||||||
|
int insert(CmsContentView cmsContentView);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除查看记录
|
||||||
|
*
|
||||||
|
* @param viewId 查看记录ID
|
||||||
|
* @return 受影响的行数
|
||||||
|
*/
|
||||||
|
int deleteById(Long viewId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新查看记录
|
||||||
|
*
|
||||||
|
* @param cmsContentView 查看记录对象
|
||||||
|
* @return 受影响的行数
|
||||||
|
*/
|
||||||
|
int update(CmsContentView cmsContentView);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询查看记录
|
||||||
|
*
|
||||||
|
* @param viewId 查看记录ID
|
||||||
|
* @return 查看记录对象
|
||||||
|
*/
|
||||||
|
CmsContentView queryById(Long viewId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询用户最近的查看记录
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @param limit 查询数量
|
||||||
|
* @return 查看记录列表
|
||||||
|
*/
|
||||||
|
List<Long> queryRecentViewsByUserId(@Param("userId") Long userId, @Param("limit") int limit);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询内容的查看记录数量
|
||||||
|
*
|
||||||
|
* @param contentId 内容ID
|
||||||
|
* @return 查看记录数量
|
||||||
|
*/
|
||||||
|
int countByContentId(Long contentId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询用户是否已查看该内容
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @param contentId 内容ID
|
||||||
|
* @return 查看记录对象,不存在则返回null
|
||||||
|
*/
|
||||||
|
CmsContentView queryByUserIdAndContentId(@Param("userId") Long userId, @Param("contentId") Long contentId);
|
||||||
|
}
|
||||||
|
|
@ -84,4 +84,6 @@ public interface SysUserMapper {
|
||||||
|
|
||||||
SysUser getByUsername(String userName);
|
SysUser getByUsername(String userName);
|
||||||
|
|
||||||
|
SysUser getByTel(String tel);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import com.kexue.skills.entity.SysUser;
|
||||||
import com.kexue.skills.entity.dto.SysUserDto;
|
import com.kexue.skills.entity.dto.SysUserDto;
|
||||||
import com.kexue.skills.entity.request.LoginDto;
|
import com.kexue.skills.entity.request.LoginDto;
|
||||||
import com.kexue.skills.entity.request.LoginUserDto;
|
import com.kexue.skills.entity.request.LoginUserDto;
|
||||||
|
import com.kexue.skills.entity.request.PhoneLoginDto;
|
||||||
import com.kexue.skills.entity.request.ResetPasswordDto;
|
import com.kexue.skills.entity.request.ResetPasswordDto;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -83,4 +84,20 @@ public interface SysUserService extends BaseService {
|
||||||
* @return 是否成功
|
* @return 是否成功
|
||||||
*/
|
*/
|
||||||
boolean resetPwd(Long userId, String newPassword, String operator);
|
boolean resetPwd(Long userId, String newPassword, String operator);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送手机验证码
|
||||||
|
*
|
||||||
|
* @param phone 手机号
|
||||||
|
* @return 是否发送成功
|
||||||
|
*/
|
||||||
|
boolean sendSmsCode(String phone);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手机号登录
|
||||||
|
*
|
||||||
|
* @param phoneLoginDto 手机号登录信息
|
||||||
|
* @return 登录结果
|
||||||
|
*/
|
||||||
|
LoginUserDto phoneLogin(PhoneLoginDto phoneLoginDto);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import com.github.pagehelper.PageInfo;
|
||||||
import com.kexue.skills.entity.Account;
|
import com.kexue.skills.entity.Account;
|
||||||
import com.kexue.skills.entity.AccountTransaction;
|
import com.kexue.skills.entity.AccountTransaction;
|
||||||
import com.kexue.skills.entity.dto.AccountDto;
|
import com.kexue.skills.entity.dto.AccountDto;
|
||||||
|
import com.kexue.skills.common.Assert;
|
||||||
import com.kexue.skills.exception.BizException;
|
import com.kexue.skills.exception.BizException;
|
||||||
import com.kexue.skills.mapper.AccountMapper;
|
import com.kexue.skills.mapper.AccountMapper;
|
||||||
import com.kexue.skills.mapper.AccountTransactionMapper;
|
import com.kexue.skills.mapper.AccountTransactionMapper;
|
||||||
|
|
@ -177,14 +178,10 @@ public class AccountServiceImpl implements AccountService {
|
||||||
public int reduceBalance(Long userId, BigDecimal amount, String transactionNo, Long businessId, String businessType, String remark) {
|
public int reduceBalance(Long userId, BigDecimal amount, String transactionNo, Long businessId, String businessType, String remark) {
|
||||||
// 1. 查询账户信息
|
// 1. 查询账户信息
|
||||||
Account account = this.queryByUserId(userId);
|
Account account = this.queryByUserId(userId);
|
||||||
if (account == null) {
|
Assert.notNull(account, "账户不存在");
|
||||||
throw new BizException("账户不存在");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. 检查余额是否足够
|
// 2. 检查余额是否足够
|
||||||
if (account.getBalance().compareTo(amount) < 0) {
|
Assert.isTrue(account.getBalance().compareTo(amount) >= 0, "账户余额不足");
|
||||||
throw new BizException("账户余额不足");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. 保存交易记录
|
// 3. 保存交易记录
|
||||||
AccountTransaction transaction = new AccountTransaction();
|
AccountTransaction transaction = new AccountTransaction();
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import com.github.pagehelper.PageInfo;
|
||||||
import com.kexue.skills.entity.CmsContent;
|
import com.kexue.skills.entity.CmsContent;
|
||||||
import com.kexue.skills.entity.ContentPurchase;
|
import com.kexue.skills.entity.ContentPurchase;
|
||||||
import com.kexue.skills.entity.dto.ContentPurchaseDto;
|
import com.kexue.skills.entity.dto.ContentPurchaseDto;
|
||||||
|
import com.kexue.skills.common.Assert;
|
||||||
import com.kexue.skills.exception.BizException;
|
import com.kexue.skills.exception.BizException;
|
||||||
import com.kexue.skills.mapper.ContentPurchaseMapper;
|
import com.kexue.skills.mapper.ContentPurchaseMapper;
|
||||||
import com.kexue.skills.service.AccountService;
|
import com.kexue.skills.service.AccountService;
|
||||||
|
|
@ -169,15 +170,10 @@ public class ContentPurchaseServiceImpl implements ContentPurchaseService {
|
||||||
public ContentPurchase purchaseContent(Long userId, Long contentId, Integer payType) {
|
public ContentPurchase purchaseContent(Long userId, Long contentId, Integer payType) {
|
||||||
// 1. 查询内容信息
|
// 1. 查询内容信息
|
||||||
CmsContent content = this.cmsContentService.queryById(contentId);
|
CmsContent content = this.cmsContentService.queryById(contentId);
|
||||||
if (content == null) {
|
Assert.notNull(content, "内容不存在");
|
||||||
throw new BizException("内容不存在");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. 检查内容是否需要付费
|
// 2. 检查内容是否需要付费
|
||||||
if (content.getIsPaid() == 0) {
|
Assert.isTrue(content.getIsPaid() != 0, "该内容为免费内容,无需购买");
|
||||||
// 免费内容,无需购买
|
|
||||||
throw new BizException("该内容为免费内容,无需购买");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. 检查用户是否已经购买过该内容
|
// 3. 检查用户是否已经购买过该内容
|
||||||
ContentPurchase existingPurchase = this.queryByUserIdAndContentId(userId, contentId);
|
ContentPurchase existingPurchase = this.queryByUserIdAndContentId(userId, contentId);
|
||||||
|
|
@ -209,9 +205,7 @@ public class ContentPurchaseServiceImpl implements ContentPurchaseService {
|
||||||
this.accountService.reduceBalance(userId, price, transactionNo, contentId, "purchase_content", "购买内容:" + content.getTitle());
|
this.accountService.reduceBalance(userId, price, transactionNo, contentId, "purchase_content", "购买内容:" + content.getTitle());
|
||||||
} else if (payType == 2) {
|
} else if (payType == 2) {
|
||||||
// 积分支付
|
// 积分支付
|
||||||
if (content.getSupportPointsPay() != 1) {
|
Assert.isTrue(content.getSupportPointsPay() == 1, "该内容不支持积分支付");
|
||||||
throw new BizException("该内容不支持积分支付");
|
|
||||||
}
|
|
||||||
|
|
||||||
Integer points = content.getRequiredPoints();
|
Integer points = content.getRequiredPoints();
|
||||||
purchase.setAmount(BigDecimal.ZERO);
|
purchase.setAmount(BigDecimal.ZERO);
|
||||||
|
|
@ -220,7 +214,7 @@ public class ContentPurchaseServiceImpl implements ContentPurchaseService {
|
||||||
// 扣除用户积分
|
// 扣除用户积分
|
||||||
this.pointsAccountService.reducePoints(userId, points, transactionNo, contentId, "purchase_content", "购买内容:" + content.getTitle());
|
this.pointsAccountService.reducePoints(userId, points, transactionNo, contentId, "purchase_content", "购买内容:" + content.getTitle());
|
||||||
} else {
|
} else {
|
||||||
throw new BizException("不支持的支付方式");
|
Assert.isTrue(false, "不支持的支付方式");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6. 更新购买记录状态
|
// 6. 更新购买记录状态
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import com.github.pagehelper.PageInfo;
|
||||||
import com.kexue.skills.entity.PointsAccount;
|
import com.kexue.skills.entity.PointsAccount;
|
||||||
import com.kexue.skills.entity.PointsTransaction;
|
import com.kexue.skills.entity.PointsTransaction;
|
||||||
import com.kexue.skills.entity.dto.PointsAccountDto;
|
import com.kexue.skills.entity.dto.PointsAccountDto;
|
||||||
|
import com.kexue.skills.common.Assert;
|
||||||
import com.kexue.skills.exception.BizException;
|
import com.kexue.skills.exception.BizException;
|
||||||
import com.kexue.skills.mapper.PointsAccountMapper;
|
import com.kexue.skills.mapper.PointsAccountMapper;
|
||||||
import com.kexue.skills.mapper.PointsTransactionMapper;
|
import com.kexue.skills.mapper.PointsTransactionMapper;
|
||||||
|
|
@ -179,14 +180,10 @@ public class PointsAccountServiceImpl implements PointsAccountService {
|
||||||
public int reducePoints(Long userId, Integer points, String transactionNo, Long businessId, String businessType, String remark) {
|
public int reducePoints(Long userId, Integer points, String transactionNo, Long businessId, String businessType, String remark) {
|
||||||
// 1. 查询积分账户信息
|
// 1. 查询积分账户信息
|
||||||
PointsAccount account = this.queryByUserId(userId);
|
PointsAccount account = this.queryByUserId(userId);
|
||||||
if (account == null) {
|
Assert.notNull(account, "积分账户不存在");
|
||||||
throw new BizException("积分账户不存在");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. 检查积分是否足够
|
// 2. 检查积分是否足够
|
||||||
if (account.getAvailablePoints() < points) {
|
Assert.isTrue(account.getAvailablePoints() >= points, "积分不足");
|
||||||
throw new BizException("积分不足");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. 保存积分交易记录
|
// 3. 保存积分交易记录
|
||||||
PointsTransaction transaction = new PointsTransaction();
|
PointsTransaction transaction = new PointsTransaction();
|
||||||
|
|
|
||||||
|
|
@ -4,33 +4,30 @@ import cn.hutool.core.bean.BeanUtil;
|
||||||
import com.alicp.jetcache.anno.CacheInvalidate;
|
import com.alicp.jetcache.anno.CacheInvalidate;
|
||||||
import com.alicp.jetcache.anno.CachePenetrationProtect;
|
import com.alicp.jetcache.anno.CachePenetrationProtect;
|
||||||
import com.alicp.jetcache.anno.Cached;
|
import com.alicp.jetcache.anno.Cached;
|
||||||
import com.kexue.skills.common.CacheManager;
|
|
||||||
import com.kexue.skills.common.Const;
|
|
||||||
import com.kexue.skills.entity.*;
|
|
||||||
import com.kexue.skills.entity.dto.ContentPurchaseDto;
|
|
||||||
import com.kexue.skills.entity.request.LoginUser;
|
|
||||||
import com.kexue.skills.entity.request.LoginUserDto;
|
|
||||||
import com.kexue.skills.entity.request.ResetPasswordDto;
|
|
||||||
import com.kexue.skills.mapper.*;
|
|
||||||
import com.kexue.skills.utils.MD5Util;
|
|
||||||
import com.kexue.skills.entity.dto.SysUserDto;
|
|
||||||
import com.kexue.skills.entity.request.LoginDto;
|
|
||||||
import com.kexue.skills.exception.BizException;
|
|
||||||
import com.kexue.skills.service.SysUserService;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import com.github.pagehelper.PageHelper;
|
import com.github.pagehelper.PageHelper;
|
||||||
import com.github.pagehelper.PageInfo;
|
import com.github.pagehelper.PageInfo;
|
||||||
|
import com.kexue.skills.common.Assert;
|
||||||
|
import com.kexue.skills.common.CacheManager;
|
||||||
|
import com.kexue.skills.common.Const;
|
||||||
|
import com.kexue.skills.config.CaptchaConfig;
|
||||||
|
import com.kexue.skills.entity.*;
|
||||||
|
import com.kexue.skills.entity.dto.ContentPurchaseDto;
|
||||||
|
import com.kexue.skills.entity.dto.SysUserDto;
|
||||||
|
import com.kexue.skills.entity.request.*;
|
||||||
|
import com.kexue.skills.mapper.*;
|
||||||
|
import com.kexue.skills.service.SysUserService;
|
||||||
|
import com.kexue.skills.utils.MD5Util;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.dromara.sms4j.api.SmsBlend;
|
||||||
|
import org.dromara.sms4j.core.factory.SmsFactory;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Random;
|
||||||
import com.kexue.skills.config.CaptchaConfig;
|
|
||||||
import com.kexue.skills.service.AccountService;
|
|
||||||
import com.kexue.skills.service.PointsAccountService;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (SysUser)表服务实现类
|
* (SysUser)表服务实现类
|
||||||
|
|
@ -63,6 +60,15 @@ public class SysUserServiceImpl implements SysUserService {
|
||||||
@Resource
|
@Resource
|
||||||
private ContentPurchaseMapper contentPurchaseMapper;
|
private ContentPurchaseMapper contentPurchaseMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private CmsContentLikeMapper cmsContentLikeMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private CmsContentViewMapper cmsContentViewMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private CmsContentMapper cmsContentMapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分页查询数据
|
* 分页查询数据
|
||||||
*
|
*
|
||||||
|
|
@ -119,9 +125,7 @@ public class SysUserServiceImpl implements SysUserService {
|
||||||
@Override
|
@Override
|
||||||
public SysUser insert(SysUser sysUser) {
|
public SysUser insert(SysUser sysUser) {
|
||||||
SysUser byUsername = getByUsername(sysUser.getUserName());
|
SysUser byUsername = getByUsername(sysUser.getUserName());
|
||||||
if (Objects.nonNull(byUsername)){
|
Assert.isNull(byUsername, "用户名已存在");
|
||||||
throw new BizException("用户名已存在");
|
|
||||||
}
|
|
||||||
sysUser.setEnable(Const.USER_STATUS_NORMAL);
|
sysUser.setEnable(Const.USER_STATUS_NORMAL);
|
||||||
sysUser.setDeleteFlag(Const.DELETE_FLAG_NO);
|
sysUser.setDeleteFlag(Const.DELETE_FLAG_NO);
|
||||||
//写一个salt生成方法
|
//写一个salt生成方法
|
||||||
|
|
@ -173,9 +177,7 @@ public class SysUserServiceImpl implements SysUserService {
|
||||||
// 校验用户名是否已经存在
|
// 校验用户名是否已经存在
|
||||||
if (sysUser.getUserName() != null && !sysUser.getUserName().isEmpty()) {
|
if (sysUser.getUserName() != null && !sysUser.getUserName().isEmpty()) {
|
||||||
SysUser existingUser = sysUserMapper.getByUsername(sysUser.getUserName());
|
SysUser existingUser = sysUserMapper.getByUsername(sysUser.getUserName());
|
||||||
if (existingUser != null && !existingUser.getUserId().equals(sysUser.getUserId())) {
|
Assert.isTrue(existingUser == null || existingUser.getUserId().equals(sysUser.getUserId()), "用户名已存在");
|
||||||
throw new BizException("用户名已存在");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
sysUserMapper.update(sysUser);
|
sysUserMapper.update(sysUser);
|
||||||
}else {
|
}else {
|
||||||
|
|
@ -196,9 +198,7 @@ public class SysUserServiceImpl implements SysUserService {
|
||||||
|
|
||||||
SysUser sysUser = queryById(userId);
|
SysUser sysUser = queryById(userId);
|
||||||
//管理员不允许删除
|
//管理员不允许删除
|
||||||
if (Const.ADMIN_USER_LIST.contains(sysUser.getUserName().toLowerCase())){
|
Assert.isFalse(Const.ADMIN_USER_LIST.contains(sysUser.getUserName().toLowerCase()), "该用户是管理员,不能删除");
|
||||||
throw new BizException("该用户是管理员,不能删除");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除用户名缓存
|
// 删除用户名缓存
|
||||||
redisTemplate.delete("sysUser:username:" + sysUser.getUserName());
|
redisTemplate.delete("sysUser:username:" + sysUser.getUserName());
|
||||||
|
|
@ -208,43 +208,494 @@ public class SysUserServiceImpl implements SysUserService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LoginUserDto login(LoginDto loginDto) {
|
public LoginUserDto login(LoginDto loginDto) {
|
||||||
if (Objects.isNull(loginDto.getUsername())){
|
// 参数验证
|
||||||
throw new BizException("用户名不能位空");
|
validateLoginParams(loginDto);
|
||||||
}
|
|
||||||
if (Objects.isNull(loginDto.getPassword())){
|
// 验证码验证
|
||||||
throw new BizException("密码不能位空");
|
validateCaptcha(loginDto);
|
||||||
|
|
||||||
|
// 查询用户
|
||||||
|
SysUser sysUser = getUserByUsername(loginDto.getUsername());
|
||||||
|
|
||||||
|
// 密码验证
|
||||||
|
validatePassword(loginDto.getPassword(), sysUser);
|
||||||
|
|
||||||
|
// 生成token
|
||||||
|
String token = generateToken(sysUser.getUserId());
|
||||||
|
|
||||||
|
// 构建登录用户信息
|
||||||
|
LoginUser loginUser = buildLoginUser(sysUser, token);
|
||||||
|
|
||||||
|
// 存储登录信息到Redis
|
||||||
|
saveLoginUserToRedis(token, loginUser);
|
||||||
|
|
||||||
|
// 构建返回对象
|
||||||
|
LoginUserDto sysUserDto = buildLoginUserDto(loginUser);
|
||||||
|
|
||||||
|
log.info("用户:{}登录成功,token:{}", loginDto.getUsername(), token);
|
||||||
|
|
||||||
|
return sysUserDto;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 验证码开关逻辑:只有启用时才验证验证码
|
/**
|
||||||
|
* 参数验证
|
||||||
|
*
|
||||||
|
* @param loginDto 登录请求参数
|
||||||
|
*/
|
||||||
|
private void validateLoginParams(LoginDto loginDto) {
|
||||||
|
Assert.notNull(loginDto.getUsername(), "用户名不能位空");
|
||||||
|
Assert.notNull(loginDto.getPassword(), "密码不能位空");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证码验证
|
||||||
|
*
|
||||||
|
* @param loginDto 登录请求参数
|
||||||
|
*/
|
||||||
|
private void validateCaptcha(LoginDto loginDto) {
|
||||||
if (captchaConfig.isEnabled()) {
|
if (captchaConfig.isEnabled()) {
|
||||||
if (Objects.isNull(loginDto.getCaptchaId()) || Objects.isNull(loginDto.getCaptchaValue())) {
|
Assert.notNull(loginDto.getCaptchaId(), "验证码不能为空");
|
||||||
throw new BizException("验证码不能为空");
|
Assert.notNull(loginDto.getCaptchaValue(), "验证码不能为空");
|
||||||
}
|
|
||||||
|
|
||||||
// 验证验证码
|
|
||||||
String captchaKey = "captcha:" + loginDto.getCaptchaId();
|
String captchaKey = "captcha:" + loginDto.getCaptchaId();
|
||||||
String captchaText = redisTemplate.opsForValue().get(captchaKey);
|
String captchaText = redisTemplate.opsForValue().get(captchaKey);
|
||||||
if (captchaText == null) {
|
Assert.notNull(captchaText, "验证码已过期");
|
||||||
throw new BizException("验证码已过期");
|
Assert.equals(captchaText, loginDto.getCaptchaValue().toLowerCase(), "验证码错误");
|
||||||
}
|
|
||||||
if (!captchaText.equals(loginDto.getCaptchaValue().toLowerCase())) {
|
|
||||||
throw new BizException("验证码错误");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 验证成功后,删除验证码
|
|
||||||
redisTemplate.delete(captchaKey);
|
redisTemplate.delete(captchaKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
SysUser sysUser = sysUserMapper.getByUsername(loginDto.getUsername());
|
|
||||||
if (Objects.isNull(sysUser)) {
|
|
||||||
throw new BizException("用户名不存在");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据用户名查询用户
|
||||||
|
*
|
||||||
|
* @param username 用户名
|
||||||
|
* @return 用户对象
|
||||||
|
*/
|
||||||
|
private SysUser getUserByUsername(String username) {
|
||||||
|
SysUser sysUser = sysUserMapper.getByUsername(username);
|
||||||
|
Assert.notNull(sysUser, "用户名不存在");
|
||||||
|
return sysUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密码验证
|
||||||
|
*
|
||||||
|
* @param password 密码
|
||||||
|
* @param sysUser 用户对象
|
||||||
|
*/
|
||||||
|
private void validatePassword(String password, SysUser sysUser) {
|
||||||
try {
|
try {
|
||||||
// 假设客户端已经对密码进行了一次MD5加密,服务端使用双重加密验证
|
// 假设客户端已经对密码进行了一次MD5加密,服务端使用双重加密验证
|
||||||
// 这样密码在传输过程中不是明文,提高安全性
|
String encryptedPwd = MD5Util.doubleEncrypt(password, sysUser.getSalt());
|
||||||
String encryptedPwd = MD5Util.doubleEncrypt(loginDto.getPassword(), sysUser.getSalt());
|
Assert.equals(encryptedPwd, sysUser.getPwd(), "密码不正确");
|
||||||
if (encryptedPwd.equals(sysUser.getPwd())) {
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成token
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @return token
|
||||||
|
*/
|
||||||
|
private String generateToken(Long userId) {
|
||||||
|
cn.dev33.satoken.stp.StpUtil.login(userId);
|
||||||
|
return cn.dev33.satoken.stp.StpUtil.getTokenValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建登录用户信息
|
||||||
|
*
|
||||||
|
* @param sysUser 用户对象
|
||||||
|
* @param token token
|
||||||
|
* @return 登录用户信息
|
||||||
|
*/
|
||||||
|
private LoginUser buildLoginUser(SysUser sysUser, String token) {
|
||||||
|
LoginUser loginUser = new LoginUser();
|
||||||
|
|
||||||
|
// 设置用户基本信息
|
||||||
|
sysUser.setPwd(null);
|
||||||
|
loginUser.setUserInfo(sysUser);
|
||||||
|
|
||||||
|
// 查询并设置用户角色列表
|
||||||
|
loginUser.setRoles(queryUserRoles(sysUser.getUserId()));
|
||||||
|
|
||||||
|
// 查询并设置用户已购买的内容ID列表
|
||||||
|
loginUser.setPurchasedContentIds(queryPurchasedContentIds(sysUser.getUserId()));
|
||||||
|
|
||||||
|
// 查询并设置用户账户信息
|
||||||
|
loginUser.setAccount(queryUserAccount(sysUser.getUserId()));
|
||||||
|
|
||||||
|
// 查询并设置用户积分信息
|
||||||
|
loginUser.setPointsAccount(queryUserPointsAccount(sysUser.getUserId()));
|
||||||
|
|
||||||
|
// 查询并设置用户最近点赞记录
|
||||||
|
loginUser.setFavorites(queryRecentFavorites(sysUser.getUserId()));
|
||||||
|
|
||||||
|
// 查询并设置用户最近查看记录
|
||||||
|
loginUser.setHistory(queryRecentViews(sysUser.getUserId()));
|
||||||
|
|
||||||
|
// 查询并设置用户最近创建记录
|
||||||
|
loginUser.setCreate(queryRecentCreatedContent(sysUser.getUserId()));
|
||||||
|
|
||||||
|
// 查询并设置用户最近购买记录
|
||||||
|
loginUser.setHas(queryRecentPurchases(sysUser.getUserId()));
|
||||||
|
|
||||||
|
// 设置token
|
||||||
|
loginUser.setToken(token);
|
||||||
|
|
||||||
|
return loginUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询用户角色列表
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @return 角色列表
|
||||||
|
*/
|
||||||
|
private List<String> queryUserRoles(Long userId) {
|
||||||
|
List<String> roles = new java.util.ArrayList<>();
|
||||||
|
try {
|
||||||
|
SysUserRole userRole = new SysUserRole();
|
||||||
|
userRole.setUserId(userId);
|
||||||
|
List<SysUserRole> userRoles = sysUserRoleMapper.queryAll(userRole);
|
||||||
|
|
||||||
|
for (SysUserRole ur : userRoles) {
|
||||||
|
roles.add("ROLE_" + ur.getRoleId());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("查询用户角色列表失败:{}", e.getMessage());
|
||||||
|
roles = java.util.Collections.emptyList();
|
||||||
|
}
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询用户已购买的内容ID列表
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @return 内容ID列表
|
||||||
|
*/
|
||||||
|
private List<Long> queryPurchasedContentIds(Long userId) {
|
||||||
|
List<Long> purchasedContentIds = new java.util.ArrayList<>();
|
||||||
|
try {
|
||||||
|
ContentPurchaseDto purchaseDto = new ContentPurchaseDto();
|
||||||
|
purchaseDto.setUserId(userId);
|
||||||
|
List<ContentPurchase> purchases = contentPurchaseMapper.getList(purchaseDto);
|
||||||
|
|
||||||
|
for (ContentPurchase purchase : purchases) {
|
||||||
|
purchasedContentIds.add(purchase.getContentId());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("查询用户已购买内容列表失败:{}", e.getMessage());
|
||||||
|
purchasedContentIds = java.util.Collections.emptyList();
|
||||||
|
}
|
||||||
|
return purchasedContentIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询用户账户信息
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @return 账户信息
|
||||||
|
*/
|
||||||
|
private Account queryUserAccount(Long userId) {
|
||||||
|
return accountMapper.queryByUserId(userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询用户积分信息
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @return 积分信息
|
||||||
|
*/
|
||||||
|
private PointsAccount queryUserPointsAccount(Long userId) {
|
||||||
|
return pointsAccountMapper.queryByUserId(userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询用户最近点赞记录
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @return 最近点赞记录
|
||||||
|
*/
|
||||||
|
private List<Long> queryRecentFavorites(Long userId) {
|
||||||
|
try {
|
||||||
|
return cmsContentLikeMapper.queryRecentLikesByUserId(userId, 20);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("查询用户最近点赞记录失败:{}", e.getMessage());
|
||||||
|
return java.util.Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询用户最近查看记录
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @return 最近查看记录
|
||||||
|
*/
|
||||||
|
private List<Long> queryRecentViews(Long userId) {
|
||||||
|
try {
|
||||||
|
return cmsContentViewMapper.queryRecentViewsByUserId(userId, 20);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("查询用户最近查看记录失败:{}", e.getMessage());
|
||||||
|
return java.util.Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询用户最近创建记录
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @return 最近创建记录
|
||||||
|
*/
|
||||||
|
private List<Long> queryRecentCreatedContent(Long userId) {
|
||||||
|
try {
|
||||||
|
return cmsContentMapper.queryRecentCreatedByUserId(userId, 20);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("查询用户最近创建记录失败:{}", e.getMessage());
|
||||||
|
return java.util.Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询用户最近购买记录
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @return 最近购买记录
|
||||||
|
*/
|
||||||
|
private List<Long> queryRecentPurchases(Long userId) {
|
||||||
|
List<Long> has = new java.util.ArrayList<>();
|
||||||
|
try {
|
||||||
|
ContentPurchaseDto purchaseDto = new ContentPurchaseDto();
|
||||||
|
purchaseDto.setUserId(userId);
|
||||||
|
List<ContentPurchase> purchases = contentPurchaseMapper.getList(purchaseDto);
|
||||||
|
if (purchases != null && !purchases.isEmpty()) {
|
||||||
|
java.util.LinkedHashSet<Long> contentIdSet = new java.util.LinkedHashSet<>();
|
||||||
|
for (ContentPurchase purchase : purchases) {
|
||||||
|
if (contentIdSet.size() < 20) {
|
||||||
|
contentIdSet.add(purchase.getContentId());
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
has.addAll(contentIdSet);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("查询用户最近购买记录失败:{}", e.getMessage());
|
||||||
|
has = java.util.Collections.emptyList();
|
||||||
|
}
|
||||||
|
return has;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 存储登录信息到Redis
|
||||||
|
*
|
||||||
|
* @param token token
|
||||||
|
* @param loginUser 登录用户信息
|
||||||
|
*/
|
||||||
|
private void saveLoginUserToRedis(String token, LoginUser loginUser) {
|
||||||
|
redisTemplate.opsForValue().set(
|
||||||
|
"loginUser:" + token,
|
||||||
|
cn.hutool.json.JSONUtil.toJsonStr(loginUser),
|
||||||
|
3600,
|
||||||
|
java.util.concurrent.TimeUnit.SECONDS
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建登录用户返回对象
|
||||||
|
*
|
||||||
|
* @param loginUser 登录用户信息
|
||||||
|
* @return 登录用户返回对象
|
||||||
|
*/
|
||||||
|
private LoginUserDto buildLoginUserDto(LoginUser loginUser) {
|
||||||
|
LoginUserDto sysUserDto = new LoginUserDto();
|
||||||
|
BeanUtil.copyProperties(loginUser.getUserInfo(), sysUserDto);
|
||||||
|
sysUserDto.setToken(loginUser.getToken());
|
||||||
|
sysUserDto.setFavorites(loginUser.getFavorites());
|
||||||
|
sysUserDto.setHistory(loginUser.getHistory());
|
||||||
|
sysUserDto.setCreate(loginUser.getCreate());
|
||||||
|
sysUserDto.setHas(loginUser.getHas());
|
||||||
|
return sysUserDto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean resetPassword(ResetPasswordDto resetPasswordDto) {
|
||||||
|
Assert.notNull(resetPasswordDto.getUserName(), "用户名不能位空");
|
||||||
|
Assert.notNull(resetPasswordDto.getOldPassword(), "旧密码不能位空");
|
||||||
|
Assert.notNull(resetPasswordDto.getNewPassword(), "新密码不能位空");
|
||||||
|
|
||||||
|
SysUser sysUser = sysUserMapper.getByUsername(resetPasswordDto.getUserName());
|
||||||
|
Assert.notNull(sysUser, "用户名不存在");
|
||||||
|
|
||||||
|
try {
|
||||||
|
String oldMd5Pwd = MD5Util.encryptToHex(resetPasswordDto.getOldPassword() + sysUser.getSalt());
|
||||||
|
Assert.equals(oldMd5Pwd, sysUser.getPwd(), "旧密码不正确");
|
||||||
|
|
||||||
|
String newMd5Pwd = MD5Util.encryptToHex(resetPasswordDto.getNewPassword() + sysUser.getSalt());
|
||||||
|
sysUser.setPwd(newMd5Pwd);
|
||||||
|
sysUserMapper.update(sysUser);
|
||||||
|
|
||||||
|
// 清除旧的token
|
||||||
|
CacheManager.removeTokenFromCache(resetPasswordDto.getUserName());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean resetPasswordByAdmin(ResetPasswordDto resetPasswordDto) {
|
||||||
|
Assert.notNull(resetPasswordDto.getUserName(), "用户名不能位空");
|
||||||
|
Assert.notNull(resetPasswordDto.getNewPassword(), "新密码不能位空");
|
||||||
|
|
||||||
|
SysUser sysUser = sysUserMapper.getByUsername(resetPasswordDto.getUserName());
|
||||||
|
Assert.notNull(sysUser, "用户名不存在");
|
||||||
|
|
||||||
|
try {
|
||||||
|
String newMd5Pwd = MD5Util.encryptToHex(resetPasswordDto.getNewPassword() + sysUser.getSalt());
|
||||||
|
sysUser.setPwd(newMd5Pwd);
|
||||||
|
sysUserMapper.update(sysUser);
|
||||||
|
|
||||||
|
// 清除旧的token
|
||||||
|
CacheManager.removeTokenFromCache(resetPasswordDto.getUserName());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Cached(name = "sysUser:username:", key = "#username", expire = 3600, cacheType = com.alicp.jetcache.anno.CacheType.BOTH)
|
||||||
|
@CachePenetrationProtect
|
||||||
|
public SysUser getByUsername(String username) {
|
||||||
|
if (Objects.nonNull(username)){
|
||||||
|
SysUser sysUser = sysUserMapper.getByUsername(username);
|
||||||
|
if (sysUser != null) {
|
||||||
|
sysUser.setPwd(null);
|
||||||
|
}
|
||||||
|
return sysUser;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean resetPwd(Long userId, String newPassword, String operator) {
|
||||||
|
// 检查操作人是否为管理员
|
||||||
|
Assert.isTrue(Const.ADMIN_USER_LIST.contains(operator.toLowerCase()), "只有管理员才能执行此操作");
|
||||||
|
|
||||||
|
// 查询用户是否存在
|
||||||
|
SysUser sysUser = sysUserMapper.queryById(userId);
|
||||||
|
Assert.notNull(sysUser, "用户不存在");
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 生成新的加密密码
|
||||||
|
String newMd5Pwd = MD5Util.encryptToHex(newPassword + sysUser.getSalt());
|
||||||
|
sysUser.setPwd(newMd5Pwd);
|
||||||
|
|
||||||
|
// 更新用户密码
|
||||||
|
sysUserMapper.update(sysUser);
|
||||||
|
|
||||||
|
// 清除旧的token
|
||||||
|
CacheManager.removeTokenFromCache(sysUser.getUserName());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送手机验证码
|
||||||
|
*
|
||||||
|
* @param phone 手机号
|
||||||
|
* @return 是否发送成功
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean sendSmsCode(String phone) {
|
||||||
|
try {
|
||||||
|
// 参数校验
|
||||||
|
Assert.notBlank(phone, "手机号不能为空");
|
||||||
|
|
||||||
|
// 生成6位随机验证码
|
||||||
|
String code = generateSmsCode();
|
||||||
|
|
||||||
|
// 存储验证码到Redis,有效期5分钟
|
||||||
|
redisTemplate.opsForValue().set("sms_code:" + phone, code, 300, java.util.concurrent.TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
// 获取默认的短信发送器
|
||||||
|
SmsBlend sms = SmsFactory.getSmsBlend();
|
||||||
|
|
||||||
|
Assert.notNull(sms, "短信服务未正确配置");
|
||||||
|
log.info("获取短信发送器成功");
|
||||||
|
|
||||||
|
// 发送验证码 - 使用模板方式发送,避免直接文本发送可能导致的参数缺失
|
||||||
|
java.util.Map<String, String> params = new java.util.HashMap<>();
|
||||||
|
params.put("code", code); // 参数名需要与阿里云模板中的变量名匹配
|
||||||
|
|
||||||
|
// 发送短信,使用配置文件中定义的模板
|
||||||
|
// 根据API文档和用户需求,使用单个手机号发送的方法:sendMessage(String phone, Map<String, String> params)
|
||||||
|
// 系统会自动从配置中读取template-id
|
||||||
|
sms.sendMessage(phone, code);
|
||||||
|
|
||||||
|
log.info("向手机号 {} 发送验证码:{}", phone, code);
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("向手机号 {} 发送验证码失败:{}", phone, e.getMessage());
|
||||||
|
log.error("详细错误信息:", e);
|
||||||
|
|
||||||
|
// 如果短信服务不可用,可以记录错误并返回false而不是抛出异常
|
||||||
|
// 或者根据业务需求决定是否继续
|
||||||
|
Assert.isTrue(false, "发送验证码失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成6位随机验证码
|
||||||
|
*
|
||||||
|
* @return 6位随机验证码
|
||||||
|
*/
|
||||||
|
private String generateSmsCode() {
|
||||||
|
Random random = new Random();
|
||||||
|
return String.format("%06d", random.nextInt(1000000));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手机号登录
|
||||||
|
*
|
||||||
|
* @param phoneLoginDto 手机号登录信息
|
||||||
|
* @return 登录结果
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public LoginUserDto phoneLogin(PhoneLoginDto phoneLoginDto) {
|
||||||
|
String phone = phoneLoginDto.getPhone();
|
||||||
|
String code = phoneLoginDto.getCode();
|
||||||
|
|
||||||
|
Assert.notBlank(phone, "手机号不能为空");
|
||||||
|
Assert.notBlank(code, "验证码不能为空");
|
||||||
|
|
||||||
|
// 验证验证码
|
||||||
|
String cachedCode = redisTemplate.opsForValue().get("sms_code:" + phone);
|
||||||
|
Assert.notNull(cachedCode, "验证码已过期");
|
||||||
|
Assert.equals(cachedCode, code, "验证码错误");
|
||||||
|
|
||||||
|
// 验证成功后,删除验证码
|
||||||
|
redisTemplate.delete("sms_code:" + phone);
|
||||||
|
|
||||||
|
// 查询用户是否存在
|
||||||
|
SysUser sysUser = sysUserMapper.getByTel(phone);
|
||||||
|
|
||||||
|
// 如果用户不存在,自动创建账号
|
||||||
|
if (sysUser == null) {
|
||||||
|
sysUser = createUserByPhone(phone);
|
||||||
|
}
|
||||||
|
|
||||||
// 使用Sa-Token登录,生成token
|
// 使用Sa-Token登录,生成token
|
||||||
cn.dev33.satoken.stp.StpUtil.login(sysUser.getUserId());
|
cn.dev33.satoken.stp.StpUtil.login(sysUser.getUserId());
|
||||||
// 获取生成的token
|
// 获取生成的token
|
||||||
|
|
@ -266,8 +717,6 @@ public class SysUserServiceImpl implements SysUserService {
|
||||||
List<SysUserRole> userRoles = sysUserRoleMapper.queryAll(userRole);
|
List<SysUserRole> userRoles = sysUserRoleMapper.queryAll(userRole);
|
||||||
|
|
||||||
// 遍历角色关联记录,获取角色名称
|
// 遍历角色关联记录,获取角色名称
|
||||||
// 注意:这里需要根据角色ID查询角色名称,当前系统中没有直接的方法,所以暂时使用角色ID作为角色名称
|
|
||||||
// 实际项目中应该查询sys_role表获取角色名称
|
|
||||||
for (SysUserRole ur : userRoles) {
|
for (SysUserRole ur : userRoles) {
|
||||||
roles.add("ROLE_" + ur.getRoleId());
|
roles.add("ROLE_" + ur.getRoleId());
|
||||||
}
|
}
|
||||||
|
|
@ -303,6 +752,18 @@ public class SysUserServiceImpl implements SysUserService {
|
||||||
PointsAccount pointsAccount = pointsAccountMapper.queryByUserId(sysUser.getUserId());
|
PointsAccount pointsAccount = pointsAccountMapper.queryByUserId(sysUser.getUserId());
|
||||||
loginUser.setPointsAccount(pointsAccount);
|
loginUser.setPointsAccount(pointsAccount);
|
||||||
|
|
||||||
|
// 查询并设置用户最近点赞记录
|
||||||
|
loginUser.setFavorites(queryRecentFavorites(sysUser.getUserId()));
|
||||||
|
|
||||||
|
// 查询并设置用户最近查看记录
|
||||||
|
loginUser.setHistory(queryRecentViews(sysUser.getUserId()));
|
||||||
|
|
||||||
|
// 查询并设置用户最近创建记录
|
||||||
|
loginUser.setCreate(queryRecentCreatedContent(sysUser.getUserId()));
|
||||||
|
|
||||||
|
// 查询并设置用户最近购买记录
|
||||||
|
loginUser.setHas(queryRecentPurchases(sysUser.getUserId()));
|
||||||
|
|
||||||
// 设置token
|
// 设置token
|
||||||
loginUser.setToken(token);
|
loginUser.setToken(token);
|
||||||
|
|
||||||
|
|
@ -310,129 +771,46 @@ public class SysUserServiceImpl implements SysUserService {
|
||||||
redisTemplate.opsForValue().set("loginUser:" + token, cn.hutool.json.JSONUtil.toJsonStr(loginUser), 3600, java.util.concurrent.TimeUnit.SECONDS);
|
redisTemplate.opsForValue().set("loginUser:" + token, cn.hutool.json.JSONUtil.toJsonStr(loginUser), 3600, java.util.concurrent.TimeUnit.SECONDS);
|
||||||
|
|
||||||
// 创建LoginUserDto返回对象
|
// 创建LoginUserDto返回对象
|
||||||
LoginUserDto sysUserDto = new LoginUserDto();
|
LoginUserDto sysUserDto = buildLoginUserDto(loginUser);
|
||||||
BeanUtil.copyProperties(sysUser, sysUserDto);
|
|
||||||
sysUserDto.setToken(token);
|
|
||||||
|
|
||||||
log.info("用户:{}登录成功,token:{}",loginDto.getUsername(),token);
|
log.info("用户:{} 手机号登录成功,token:{}", phone, token);
|
||||||
|
|
||||||
// 密码匹配成功
|
|
||||||
return sysUserDto;
|
return sysUserDto;
|
||||||
}else {
|
|
||||||
throw new BizException("密码不正确");
|
|
||||||
}
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public boolean resetPassword(ResetPasswordDto resetPasswordDto) {
|
* 根据手机号创建用户
|
||||||
if (Objects.isNull(resetPasswordDto.getUserName())) {
|
*
|
||||||
throw new BizException("用户名不能位空");
|
* @param phone 手机号
|
||||||
}
|
* @return 创建的用户对象
|
||||||
if (Objects.isNull(resetPasswordDto.getOldPassword())) {
|
*/
|
||||||
throw new BizException("旧密码不能位空");
|
private SysUser createUserByPhone(String phone) {
|
||||||
}
|
SysUser sysUser = new SysUser();
|
||||||
if (Objects.isNull(resetPasswordDto.getNewPassword())) {
|
|
||||||
throw new BizException("新密码不能位空");
|
// 设置用户名(使用手机号作为用户名)
|
||||||
|
sysUser.setUserName(phone);
|
||||||
|
sysUser.setTel(phone);
|
||||||
|
|
||||||
|
// 生成随机密码
|
||||||
|
String randomPassword = generateRandomPassword();
|
||||||
|
sysUser.setPwd(randomPassword);
|
||||||
|
|
||||||
|
// 调用insert方法创建用户
|
||||||
|
return insert(sysUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
SysUser sysUser = sysUserMapper.getByUsername(resetPasswordDto.getUserName());
|
/**
|
||||||
if (Objects.isNull(sysUser)) {
|
* 生成随机密码
|
||||||
throw new BizException("用户名不存在");
|
*
|
||||||
}
|
* @return 随机密码
|
||||||
|
*/
|
||||||
try {
|
private String generateRandomPassword() {
|
||||||
String oldMd5Pwd = MD5Util.encryptToHex(resetPasswordDto.getOldPassword() + sysUser.getSalt());
|
String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||||
if (!oldMd5Pwd.equals(sysUser.getPwd())) {
|
Random random = new Random();
|
||||||
throw new BizException("旧密码不正确");
|
StringBuilder sb = new StringBuilder(12);
|
||||||
}
|
for (int i = 0; i < 12; i++) {
|
||||||
|
sb.append(characters.charAt(random.nextInt(characters.length())));
|
||||||
String newMd5Pwd = MD5Util.encryptToHex(resetPasswordDto.getNewPassword() + sysUser.getSalt());
|
|
||||||
sysUser.setPwd(newMd5Pwd);
|
|
||||||
sysUserMapper.update(sysUser);
|
|
||||||
|
|
||||||
// 清除旧的token
|
|
||||||
CacheManager.removeTokenFromCache(resetPasswordDto.getUserName());
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean resetPasswordByAdmin(ResetPasswordDto resetPasswordDto) {
|
|
||||||
if (Objects.isNull(resetPasswordDto.getUserName())) {
|
|
||||||
throw new BizException("用户名不能位空");
|
|
||||||
}
|
|
||||||
if (Objects.isNull(resetPasswordDto.getNewPassword())) {
|
|
||||||
throw new BizException("新密码不能位空");
|
|
||||||
}
|
|
||||||
|
|
||||||
SysUser sysUser = sysUserMapper.getByUsername(resetPasswordDto.getUserName());
|
|
||||||
if (Objects.isNull(sysUser)) {
|
|
||||||
throw new BizException("用户名不存在");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
String newMd5Pwd = MD5Util.encryptToHex(resetPasswordDto.getNewPassword() + sysUser.getSalt());
|
|
||||||
sysUser.setPwd(newMd5Pwd);
|
|
||||||
sysUserMapper.update(sysUser);
|
|
||||||
|
|
||||||
// 清除旧的token
|
|
||||||
CacheManager.removeTokenFromCache(resetPasswordDto.getUserName());
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Cached(name = "sysUser:username:", key = "#username", expire = 3600, cacheType = com.alicp.jetcache.anno.CacheType.BOTH)
|
|
||||||
@CachePenetrationProtect
|
|
||||||
public SysUser getByUsername(String username) {
|
|
||||||
if (Objects.nonNull(username)){
|
|
||||||
SysUser sysUser = sysUserMapper.getByUsername(username);
|
|
||||||
if (sysUser != null) {
|
|
||||||
sysUser.setPwd(null);
|
|
||||||
}
|
|
||||||
return sysUser;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean resetPwd(Long userId, String newPassword, String operator) {
|
|
||||||
// 检查操作人是否为管理员
|
|
||||||
if (!Const.ADMIN_USER_LIST.contains(operator.toLowerCase())) {
|
|
||||||
throw new BizException("只有管理员才能执行此操作");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询用户是否存在
|
|
||||||
SysUser sysUser = sysUserMapper.queryById(userId);
|
|
||||||
if (sysUser == null) {
|
|
||||||
throw new BizException("用户不存在");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 生成新的加密密码
|
|
||||||
String newMd5Pwd = MD5Util.encryptToHex(newPassword + sysUser.getSalt());
|
|
||||||
sysUser.setPwd(newMd5Pwd);
|
|
||||||
|
|
||||||
// 更新用户密码
|
|
||||||
sysUserMapper.update(sysUser);
|
|
||||||
|
|
||||||
// 清除旧的token
|
|
||||||
CacheManager.removeTokenFromCache(sysUser.getUserName());
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
}
|
||||||
|
return sb.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,11 @@ spring:
|
||||||
mode: HTML
|
mode: HTML
|
||||||
prefix: classpath:/templates/
|
prefix: classpath:/templates/
|
||||||
suffix: .html
|
suffix: .html
|
||||||
|
http:
|
||||||
|
encoding:
|
||||||
|
charset: UTF-8
|
||||||
|
enabled: true
|
||||||
|
force: true
|
||||||
servlet:
|
servlet:
|
||||||
multipart:
|
multipart:
|
||||||
max-request-size: 20MB
|
max-request-size: 20MB
|
||||||
|
|
@ -44,3 +49,23 @@ pagehelper:
|
||||||
supportMethodsArguments: true
|
supportMethodsArguments: true
|
||||||
params: count=countSql
|
params: count=countSql
|
||||||
|
|
||||||
|
# SMS4J 短信发送配置
|
||||||
|
sms:
|
||||||
|
# 从 YAML 读取配置
|
||||||
|
config-type: YAML
|
||||||
|
http-log: true
|
||||||
|
is-print: false
|
||||||
|
blends:
|
||||||
|
alibaba:
|
||||||
|
# 短信厂商
|
||||||
|
supplier: alibaba
|
||||||
|
requestUrl: dysmsapi.aliyuncs.com
|
||||||
|
access-key-id: LTAI5t8rsaBDrno4xd4F6EwE
|
||||||
|
access-key-secret: QNmjxatrgzBYukAKr8BZ4r7gd37SHw
|
||||||
|
signature: 武汉可学智能科技
|
||||||
|
# 阿里云短信模板ID,需要替换为实际申请的模板ID
|
||||||
|
template-id: SMS_493720484 # 实际使用时请替换为真实模板ID
|
||||||
|
# 短信模板变量名,对应验证码的变量
|
||||||
|
template-param-name: code
|
||||||
|
template-cache: true
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
<?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.kexue.skills.mapper.CmsContentLikeMapper">
|
||||||
|
|
||||||
|
<resultMap type="com.kexue.skills.entity.CmsContentLike" id="CmsContentLikeResult">
|
||||||
|
<result property="likeId" column="like_id"/>
|
||||||
|
<result property="userId" column="user_id"/>
|
||||||
|
<result property="userName" column="user_name"/>
|
||||||
|
<result property="contentId" column="content_id"/>
|
||||||
|
<result property="contentTitle" column="content_title"/>
|
||||||
|
<result property="likeTime" column="like_time"/>
|
||||||
|
<result property="deleteFlag" column="delete_flag"/>
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<insert id="insert" parameterType="com.kexue.skills.entity.CmsContentLike">
|
||||||
|
INSERT INTO cms_content_like (
|
||||||
|
user_id, user_name, content_id, content_title, like_time, delete_flag
|
||||||
|
) VALUES (
|
||||||
|
#{userId}, #{userName}, #{contentId}, #{contentTitle}, NOW(), #{deleteFlag, jdbcType=INTEGER}
|
||||||
|
)
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
<update id="update" parameterType="com.kexue.skills.entity.CmsContentLike">
|
||||||
|
UPDATE cms_content_like
|
||||||
|
<set>
|
||||||
|
<if test="userId != null">user_id = #{userId},</if>
|
||||||
|
<if test="userName != null and userName != ''">user_name = #{userName},</if>
|
||||||
|
<if test="contentId != null">content_id = #{contentId},</if>
|
||||||
|
<if test="contentTitle != null and contentTitle != ''">content_title = #{contentTitle},</if>
|
||||||
|
<if test="likeTime != null">like_time = #{likeTime},</if>
|
||||||
|
<if test="deleteFlag != null">delete_flag = #{deleteFlag},</if>
|
||||||
|
</set>
|
||||||
|
WHERE like_id = #{likeId}
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<delete id="deleteById" parameterType="Long">
|
||||||
|
DELETE FROM cms_content_like WHERE like_id = #{likeId}
|
||||||
|
</delete>
|
||||||
|
|
||||||
|
<select id="queryById" parameterType="Long" resultMap="CmsContentLikeResult">
|
||||||
|
SELECT * FROM cms_content_like WHERE like_id = #{likeId}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="queryByUserIdAndContentId" resultMap="CmsContentLikeResult">
|
||||||
|
SELECT * FROM cms_content_like
|
||||||
|
WHERE user_id = #{userId} AND content_id = #{contentId} AND delete_flag = 0
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="queryRecentLikesByUserId" resultType="Long">
|
||||||
|
SELECT DISTINCT content_id FROM cms_content_like
|
||||||
|
WHERE user_id = #{userId} AND delete_flag = 0
|
||||||
|
ORDER BY like_time DESC
|
||||||
|
LIMIT #{limit}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="countByContentId" parameterType="Long" resultType="int">
|
||||||
|
SELECT COUNT(*) FROM cms_content_like
|
||||||
|
WHERE content_id = #{contentId} AND delete_flag = 0
|
||||||
|
</select>
|
||||||
|
</mapper>
|
||||||
|
|
@ -270,4 +270,12 @@
|
||||||
where content_id = #{contentId}
|
where content_id = #{contentId}
|
||||||
</update>
|
</update>
|
||||||
|
|
||||||
|
<!--查询用户最近创建的内容ID列表-->
|
||||||
|
<select id="queryRecentCreatedByUserId" resultType="Long">
|
||||||
|
select distinct content_id from cms_content
|
||||||
|
where author_id = #{userId} and delete_flag = 0
|
||||||
|
order by create_time desc
|
||||||
|
limit #{limit}
|
||||||
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
<?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.kexue.skills.mapper.CmsContentViewMapper">
|
||||||
|
|
||||||
|
<resultMap type="com.kexue.skills.entity.CmsContentView" id="CmsContentViewResult">
|
||||||
|
<result property="viewId" column="view_id"/>
|
||||||
|
<result property="userId" column="user_id"/>
|
||||||
|
<result property="userName" column="user_name"/>
|
||||||
|
<result property="contentId" column="content_id"/>
|
||||||
|
<result property="contentTitle" column="content_title"/>
|
||||||
|
<result property="viewTime" column="view_time"/>
|
||||||
|
<result property="deleteFlag" column="delete_flag"/>
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<insert id="insert" parameterType="com.kexue.skills.entity.CmsContentView">
|
||||||
|
INSERT INTO cms_content_view (
|
||||||
|
user_id, user_name, content_id, content_title, view_time, delete_flag
|
||||||
|
) VALUES (
|
||||||
|
#{userId}, #{userName}, #{contentId}, #{contentTitle}, NOW(), #{deleteFlag, jdbcType=INTEGER}
|
||||||
|
)
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
<update id="update" parameterType="com.kexue.skills.entity.CmsContentView">
|
||||||
|
UPDATE cms_content_view
|
||||||
|
<set>
|
||||||
|
<if test="userId != null">user_id = #{userId},</if>
|
||||||
|
<if test="userName != null and userName != ''">user_name = #{userName},</if>
|
||||||
|
<if test="contentId != null">content_id = #{contentId},</if>
|
||||||
|
<if test="contentTitle != null and contentTitle != ''">content_title = #{contentTitle},</if>
|
||||||
|
<if test="viewTime != null">view_time = #{viewTime},</if>
|
||||||
|
<if test="deleteFlag != null">delete_flag = #{deleteFlag},</if>
|
||||||
|
</set>
|
||||||
|
WHERE view_id = #{viewId}
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<delete id="deleteById" parameterType="Long">
|
||||||
|
DELETE FROM cms_content_view WHERE view_id = #{viewId}
|
||||||
|
</delete>
|
||||||
|
|
||||||
|
<select id="queryById" parameterType="Long" resultMap="CmsContentViewResult">
|
||||||
|
SELECT * FROM cms_content_view WHERE view_id = #{viewId}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="queryByUserIdAndContentId" resultMap="CmsContentViewResult">
|
||||||
|
SELECT * FROM cms_content_view
|
||||||
|
WHERE user_id = #{userId} AND content_id = #{contentId} AND delete_flag = 0
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="queryRecentViewsByUserId" resultType="Long">
|
||||||
|
SELECT DISTINCT content_id FROM cms_content_view
|
||||||
|
WHERE user_id = #{userId} AND delete_flag = 0
|
||||||
|
ORDER BY view_time DESC
|
||||||
|
LIMIT #{limit}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="countByContentId" parameterType="Long" resultType="int">
|
||||||
|
SELECT COUNT(*) FROM cms_content_view
|
||||||
|
WHERE content_id = #{contentId} AND delete_flag = 0
|
||||||
|
</select>
|
||||||
|
</mapper>
|
||||||
|
|
@ -107,6 +107,7 @@
|
||||||
and delete_flag = #{deleteFlag}
|
and delete_flag = #{deleteFlag}
|
||||||
</if>
|
</if>
|
||||||
</where>
|
</where>
|
||||||
|
order by purchase_time desc
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<!--新增数据-->
|
<!--新增数据-->
|
||||||
|
|
|
||||||
|
|
@ -196,4 +196,13 @@
|
||||||
limit 1
|
limit 1
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="getByTel" resultMap="SysUserMap">
|
||||||
|
select
|
||||||
|
user_id, user_name, pwd, real_name, tel, email, salt, remark, create_time, enable, delete_flag
|
||||||
|
from sys_user
|
||||||
|
where tel = #{tel}
|
||||||
|
and delete_flag = 0
|
||||||
|
limit 1
|
||||||
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue