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
|
|
@ -240,6 +240,13 @@
|
|||
<artifactId>commons-pool2</artifactId>
|
||||
<version>2.12.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- SMS4J 短信发送框架 -->
|
||||
<dependency>
|
||||
<groupId>org.dromara.sms4j</groupId>
|
||||
<artifactId>sms4j-spring-boot-starter</artifactId>
|
||||
<version>3.3.5</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
<dependencyManagement>
|
||||
|
|
@ -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.tree=ALL-UNNAMED</arg>
|
||||
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED</arg>
|
||||
<arg>-parameters</arg>
|
||||
</compilerArgs>
|
||||
<annotationProcessorPaths>
|
||||
<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;
|
||||
|
||||
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.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
|
||||
/** mvc配置,例如:资源映射、视图解析、拦截器等
|
||||
*
|
||||
**/
|
||||
|
|
@ -53,6 +59,17 @@ public class WebMvcConfig implements WebMvcConfigurer {
|
|||
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
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ public class CaptchaController {
|
|||
*/
|
||||
@PostMapping("/verify")
|
||||
@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()) {
|
||||
return CommonResult.success(true);
|
||||
|
|
|
|||
|
|
@ -106,11 +106,11 @@ public class CmsContentController {
|
|||
@PostMapping("/updateAuditStatus")
|
||||
@Operation(summary = "更新审核状态", description = "更新审核状态")
|
||||
@RequireAuth
|
||||
public CommonResult<Boolean> updateAuditStatus(@RequestParam Long contentId,
|
||||
@RequestParam Integer auditStatus,
|
||||
@RequestParam Long reviewerId,
|
||||
@RequestParam String reviewerName,
|
||||
@RequestParam(required = false) String auditComment) {
|
||||
public CommonResult<Boolean> updateAuditStatus(@RequestParam("contentId") Long contentId,
|
||||
@RequestParam("auditStatus") Integer auditStatus,
|
||||
@RequestParam("reviewerId") Long reviewerId,
|
||||
@RequestParam("reviewerName") String reviewerName,
|
||||
@RequestParam(value = "auditComment", required = false) String auditComment) {
|
||||
return CommonResult.success(cmsContentService.updateAuditStatus(contentId, auditStatus, reviewerId, reviewerName, auditComment, reviewerName) > 0);
|
||||
}
|
||||
|
||||
|
|
@ -126,10 +126,10 @@ public class CmsContentController {
|
|||
@PostMapping("/updatePublishStatus")
|
||||
@Operation(summary = "更新发布状态", description = "更新发布状态")
|
||||
@RequireAuth
|
||||
public CommonResult<Boolean> updatePublishStatus(@RequestParam Long contentId,
|
||||
@RequestParam Integer publishStatus,
|
||||
@RequestParam(required = false) String publishTime,
|
||||
@RequestParam String updateBy) {
|
||||
public CommonResult<Boolean> updatePublishStatus(@RequestParam("contentId") Long contentId,
|
||||
@RequestParam("publishStatus") Integer publishStatus,
|
||||
@RequestParam(value = "publishTime", required = false) String publishTime,
|
||||
@RequestParam("updateBy") String updateBy) {
|
||||
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.common.CommonResult;
|
||||
import com.kexue.skills.entity.SysUser;
|
||||
import com.kexue.skills.entity.request.LoginDto;
|
||||
import com.kexue.skills.entity.request.LoginUserDto;
|
||||
import com.kexue.skills.entity.request.PhoneLoginDto;
|
||||
import com.kexue.skills.service.SysUserService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
|
@ -35,7 +35,7 @@ public class LoginController {
|
|||
* @param loginDto 登录信息
|
||||
* @return 登录结果
|
||||
*/
|
||||
@PostMapping("/do")
|
||||
@PostMapping("/accountLogin")
|
||||
@Operation(summary = "用户登录", description = "用户登录")
|
||||
@PreventDuplicateSubmission
|
||||
public CommonResult<LoginUserDto> login(@RequestBody LoginDto loginDto) {
|
||||
|
|
@ -47,13 +47,42 @@ public class LoginController {
|
|||
*
|
||||
* @return 登出结果
|
||||
*/
|
||||
@PostMapping("/logout")
|
||||
@PostMapping("/accountLogout")
|
||||
@Operation(summary = "用户登出", description = "用户登出")
|
||||
public CommonResult<String> logout() {
|
||||
// 使用Sa-Token登出
|
||||
cn.dev33.satoken.stp.StpUtil.logout();
|
||||
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已删除")
|
||||
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已删除")
|
||||
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已删除")
|
||||
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已删除")
|
||||
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已删除")
|
||||
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已删除")
|
||||
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 ="创建时间")
|
||||
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 com.kexue.skills.entity.base.BaseEntity;
|
||||
import com.kexue.skills.entity.base.BaseQueryDto;
|
||||
import java.util.Date;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
|
@ -45,4 +46,21 @@ public class SysLog extends BaseEntity implements Serializable {
|
|||
@Schema(description ="备注")
|
||||
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 com.kexue.skills.entity.base.BaseEntity;
|
||||
import com.kexue.skills.entity.base.BaseQueryDto;
|
||||
import java.util.Date;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
|
@ -45,4 +46,18 @@ public class SysMenu extends BaseEntity implements Serializable {
|
|||
@Schema(description ="删除标记")
|
||||
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 ="创建时间")
|
||||
private Date createTime;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description ="更新时间")
|
||||
private Date updateTime;
|
||||
|
||||
@Schema(description ="备注")
|
||||
private String remark;
|
||||
|
||||
@Schema(description ="删除标记")
|
||||
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 ="创建时间")
|
||||
private Date createTime;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description ="更新时间")
|
||||
private Date updateTime;
|
||||
|
||||
@Schema(description ="是否启用(1启用,2禁用)")
|
||||
private Integer enable;
|
||||
|
||||
@Schema(description ="是否删除 :0 未删除,1已删除")
|
||||
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.util.Date;
|
||||
|
||||
import com.kexue.skills.entity.base.BaseEntity;
|
||||
import com.kexue.skills.entity.base.BaseQueryDto;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
|
|
@ -24,4 +26,21 @@ public class SysUserRole extends BaseEntity implements Serializable {
|
|||
@Schema(description ="用户ID")
|
||||
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
|
||||
*/
|
||||
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 lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author 维哥
|
||||
* @Description
|
||||
|
|
@ -13,4 +15,24 @@ import lombok.Data;
|
|||
@ApiModel(value = "登录用户信息")
|
||||
public class LoginUserDto extends SysUser {
|
||||
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;
|
||||
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-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 影响行数
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
|
@ -83,5 +83,7 @@ public interface SysUserMapper {
|
|||
int deleteById(Long userId);
|
||||
|
||||
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.request.LoginDto;
|
||||
import com.kexue.skills.entity.request.LoginUserDto;
|
||||
import com.kexue.skills.entity.request.PhoneLoginDto;
|
||||
import com.kexue.skills.entity.request.ResetPasswordDto;
|
||||
|
||||
import java.util.List;
|
||||
|
|
@ -83,4 +84,20 @@ public interface SysUserService extends BaseService {
|
|||
* @return 是否成功
|
||||
*/
|
||||
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.AccountTransaction;
|
||||
import com.kexue.skills.entity.dto.AccountDto;
|
||||
import com.kexue.skills.common.Assert;
|
||||
import com.kexue.skills.exception.BizException;
|
||||
import com.kexue.skills.mapper.AccountMapper;
|
||||
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) {
|
||||
// 1. 查询账户信息
|
||||
Account account = this.queryByUserId(userId);
|
||||
if (account == null) {
|
||||
throw new BizException("账户不存在");
|
||||
}
|
||||
Assert.notNull(account, "账户不存在");
|
||||
|
||||
// 2. 检查余额是否足够
|
||||
if (account.getBalance().compareTo(amount) < 0) {
|
||||
throw new BizException("账户余额不足");
|
||||
}
|
||||
Assert.isTrue(account.getBalance().compareTo(amount) >= 0, "账户余额不足");
|
||||
|
||||
// 3. 保存交易记录
|
||||
AccountTransaction transaction = new AccountTransaction();
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import com.github.pagehelper.PageInfo;
|
|||
import com.kexue.skills.entity.CmsContent;
|
||||
import com.kexue.skills.entity.ContentPurchase;
|
||||
import com.kexue.skills.entity.dto.ContentPurchaseDto;
|
||||
import com.kexue.skills.common.Assert;
|
||||
import com.kexue.skills.exception.BizException;
|
||||
import com.kexue.skills.mapper.ContentPurchaseMapper;
|
||||
import com.kexue.skills.service.AccountService;
|
||||
|
|
@ -169,15 +170,10 @@ public class ContentPurchaseServiceImpl implements ContentPurchaseService {
|
|||
public ContentPurchase purchaseContent(Long userId, Long contentId, Integer payType) {
|
||||
// 1. 查询内容信息
|
||||
CmsContent content = this.cmsContentService.queryById(contentId);
|
||||
if (content == null) {
|
||||
throw new BizException("内容不存在");
|
||||
}
|
||||
Assert.notNull(content, "内容不存在");
|
||||
|
||||
// 2. 检查内容是否需要付费
|
||||
if (content.getIsPaid() == 0) {
|
||||
// 免费内容,无需购买
|
||||
throw new BizException("该内容为免费内容,无需购买");
|
||||
}
|
||||
Assert.isTrue(content.getIsPaid() != 0, "该内容为免费内容,无需购买");
|
||||
|
||||
// 3. 检查用户是否已经购买过该内容
|
||||
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());
|
||||
} else if (payType == 2) {
|
||||
// 积分支付
|
||||
if (content.getSupportPointsPay() != 1) {
|
||||
throw new BizException("该内容不支持积分支付");
|
||||
}
|
||||
Assert.isTrue(content.getSupportPointsPay() == 1, "该内容不支持积分支付");
|
||||
|
||||
Integer points = content.getRequiredPoints();
|
||||
purchase.setAmount(BigDecimal.ZERO);
|
||||
|
|
@ -220,7 +214,7 @@ public class ContentPurchaseServiceImpl implements ContentPurchaseService {
|
|||
// 扣除用户积分
|
||||
this.pointsAccountService.reducePoints(userId, points, transactionNo, contentId, "purchase_content", "购买内容:" + content.getTitle());
|
||||
} else {
|
||||
throw new BizException("不支持的支付方式");
|
||||
Assert.isTrue(false, "不支持的支付方式");
|
||||
}
|
||||
|
||||
// 6. 更新购买记录状态
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import com.github.pagehelper.PageInfo;
|
|||
import com.kexue.skills.entity.PointsAccount;
|
||||
import com.kexue.skills.entity.PointsTransaction;
|
||||
import com.kexue.skills.entity.dto.PointsAccountDto;
|
||||
import com.kexue.skills.common.Assert;
|
||||
import com.kexue.skills.exception.BizException;
|
||||
import com.kexue.skills.mapper.PointsAccountMapper;
|
||||
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) {
|
||||
// 1. 查询积分账户信息
|
||||
PointsAccount account = this.queryByUserId(userId);
|
||||
if (account == null) {
|
||||
throw new BizException("积分账户不存在");
|
||||
}
|
||||
Assert.notNull(account, "积分账户不存在");
|
||||
|
||||
// 2. 检查积分是否足够
|
||||
if (account.getAvailablePoints() < points) {
|
||||
throw new BizException("积分不足");
|
||||
}
|
||||
Assert.isTrue(account.getAvailablePoints() >= points, "积分不足");
|
||||
|
||||
// 3. 保存积分交易记录
|
||||
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.CachePenetrationProtect;
|
||||
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.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 java.math.BigDecimal;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import com.kexue.skills.config.CaptchaConfig;
|
||||
import com.kexue.skills.service.AccountService;
|
||||
import com.kexue.skills.service.PointsAccountService;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* (SysUser)表服务实现类
|
||||
|
|
@ -62,6 +59,15 @@ public class SysUserServiceImpl implements SysUserService {
|
|||
|
||||
@Resource
|
||||
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
|
||||
public SysUser insert(SysUser sysUser) {
|
||||
SysUser byUsername = getByUsername(sysUser.getUserName());
|
||||
if (Objects.nonNull(byUsername)){
|
||||
throw new BizException("用户名已存在");
|
||||
}
|
||||
Assert.isNull(byUsername, "用户名已存在");
|
||||
sysUser.setEnable(Const.USER_STATUS_NORMAL);
|
||||
sysUser.setDeleteFlag(Const.DELETE_FLAG_NO);
|
||||
//写一个salt生成方法
|
||||
|
|
@ -173,9 +177,7 @@ public class SysUserServiceImpl implements SysUserService {
|
|||
// 校验用户名是否已经存在
|
||||
if (sysUser.getUserName() != null && !sysUser.getUserName().isEmpty()) {
|
||||
SysUser existingUser = sysUserMapper.getByUsername(sysUser.getUserName());
|
||||
if (existingUser != null && !existingUser.getUserId().equals(sysUser.getUserId())) {
|
||||
throw new BizException("用户名已存在");
|
||||
}
|
||||
Assert.isTrue(existingUser == null || existingUser.getUserId().equals(sysUser.getUserId()), "用户名已存在");
|
||||
}
|
||||
sysUserMapper.update(sysUser);
|
||||
}else {
|
||||
|
|
@ -196,9 +198,7 @@ public class SysUserServiceImpl implements SysUserService {
|
|||
|
||||
SysUser sysUser = queryById(userId);
|
||||
//管理员不允许删除
|
||||
if (Const.ADMIN_USER_LIST.contains(sysUser.getUserName().toLowerCase())){
|
||||
throw new BizException("该用户是管理员,不能删除");
|
||||
}
|
||||
Assert.isFalse(Const.ADMIN_USER_LIST.contains(sysUser.getUserName().toLowerCase()), "该用户是管理员,不能删除");
|
||||
|
||||
// 删除用户名缓存
|
||||
redisTemplate.delete("sysUser:username:" + sysUser.getUserName());
|
||||
|
|
@ -208,148 +208,332 @@ public class SysUserServiceImpl implements SysUserService {
|
|||
|
||||
@Override
|
||||
public LoginUserDto login(LoginDto loginDto) {
|
||||
if (Objects.isNull(loginDto.getUsername())){
|
||||
throw new BizException("用户名不能位空");
|
||||
}
|
||||
if (Objects.isNull(loginDto.getPassword())){
|
||||
throw new BizException("密码不能位空");
|
||||
}
|
||||
// 参数验证
|
||||
validateLoginParams(loginDto);
|
||||
|
||||
// 验证码开关逻辑:只有启用时才验证验证码
|
||||
// 验证码验证
|
||||
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 (Objects.isNull(loginDto.getCaptchaId()) || Objects.isNull(loginDto.getCaptchaValue())) {
|
||||
throw new BizException("验证码不能为空");
|
||||
}
|
||||
Assert.notNull(loginDto.getCaptchaId(), "验证码不能为空");
|
||||
Assert.notNull(loginDto.getCaptchaValue(), "验证码不能为空");
|
||||
|
||||
// 验证验证码
|
||||
String captchaKey = "captcha:" + loginDto.getCaptchaId();
|
||||
String captchaText = redisTemplate.opsForValue().get(captchaKey);
|
||||
if (captchaText == null) {
|
||||
throw new BizException("验证码已过期");
|
||||
}
|
||||
if (!captchaText.equals(loginDto.getCaptchaValue().toLowerCase())) {
|
||||
throw new BizException("验证码错误");
|
||||
}
|
||||
Assert.notNull(captchaText, "验证码已过期");
|
||||
Assert.equals(captchaText, loginDto.getCaptchaValue().toLowerCase(), "验证码错误");
|
||||
|
||||
// 验证成功后,删除验证码
|
||||
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 {
|
||||
// 假设客户端已经对密码进行了一次MD5加密,服务端使用双重加密验证
|
||||
// 这样密码在传输过程中不是明文,提高安全性
|
||||
String encryptedPwd = MD5Util.doubleEncrypt(loginDto.getPassword(), sysUser.getSalt());
|
||||
if (encryptedPwd.equals(sysUser.getPwd())) {
|
||||
// 使用Sa-Token登录,生成token
|
||||
cn.dev33.satoken.stp.StpUtil.login(sysUser.getUserId());
|
||||
// 获取生成的token
|
||||
String token = cn.dev33.satoken.stp.StpUtil.getTokenValue();
|
||||
|
||||
// 创建LoginUser对象
|
||||
LoginUser loginUser = new LoginUser();
|
||||
|
||||
// 设置用户基本信息
|
||||
sysUser.setPwd(null);
|
||||
loginUser.setUserInfo(sysUser);
|
||||
|
||||
// 查询用户角色列表
|
||||
List<String> roles = new java.util.ArrayList<>();
|
||||
try {
|
||||
// 创建查询条件,查询用户的角色关联记录
|
||||
SysUserRole userRole = new SysUserRole();
|
||||
userRole.setUserId(sysUser.getUserId());
|
||||
List<SysUserRole> userRoles = sysUserRoleMapper.queryAll(userRole);
|
||||
|
||||
// 遍历角色关联记录,获取角色名称
|
||||
// 注意:这里需要根据角色ID查询角色名称,当前系统中没有直接的方法,所以暂时使用角色ID作为角色名称
|
||||
// 实际项目中应该查询sys_role表获取角色名称
|
||||
for (SysUserRole ur : userRoles) {
|
||||
roles.add("ROLE_" + ur.getRoleId());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("查询用户角色列表失败:{}", e.getMessage());
|
||||
roles = java.util.Collections.emptyList();
|
||||
}
|
||||
loginUser.setRoles(roles);
|
||||
|
||||
// 查询用户已购买的内容ID列表
|
||||
List<Long> purchasedContentIds = new java.util.ArrayList<>();
|
||||
try {
|
||||
// 创建查询条件,查询用户的购买记录
|
||||
ContentPurchaseDto purchaseDto = new ContentPurchaseDto();
|
||||
purchaseDto.setUserId(sysUser.getUserId());
|
||||
List<ContentPurchase> purchases = contentPurchaseMapper.getList(purchaseDto);
|
||||
|
||||
// 遍历购买记录,获取内容ID
|
||||
for (ContentPurchase purchase : purchases) {
|
||||
purchasedContentIds.add(purchase.getContentId());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("查询用户已购买内容列表失败:{}", e.getMessage());
|
||||
purchasedContentIds = java.util.Collections.emptyList();
|
||||
}
|
||||
loginUser.setPurchasedContentIds(purchasedContentIds);
|
||||
|
||||
// 查询用户账户信息
|
||||
Account account = accountMapper.queryByUserId(sysUser.getUserId());
|
||||
loginUser.setAccount(account);
|
||||
|
||||
// 查询用户积分信息
|
||||
PointsAccount pointsAccount = pointsAccountMapper.queryByUserId(sysUser.getUserId());
|
||||
loginUser.setPointsAccount(pointsAccount);
|
||||
|
||||
// 设置token
|
||||
loginUser.setToken(token);
|
||||
|
||||
// 将LoginUser对象存储到Redis缓存中,使用token作为key
|
||||
redisTemplate.opsForValue().set("loginUser:" + token, cn.hutool.json.JSONUtil.toJsonStr(loginUser), 3600, java.util.concurrent.TimeUnit.SECONDS);
|
||||
|
||||
// 创建LoginUserDto返回对象
|
||||
LoginUserDto sysUserDto = new LoginUserDto();
|
||||
BeanUtil.copyProperties(sysUser, sysUserDto);
|
||||
sysUserDto.setToken(token);
|
||||
|
||||
log.info("用户:{}登录成功,token:{}",loginDto.getUsername(),token);
|
||||
|
||||
// 密码匹配成功
|
||||
return sysUserDto;
|
||||
}else {
|
||||
throw new BizException("密码不正确");
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
throw new RuntimeException(e);
|
||||
String encryptedPwd = MD5Util.doubleEncrypt(password, sysUser.getSalt());
|
||||
Assert.equals(encryptedPwd, 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) {
|
||||
if (Objects.isNull(resetPasswordDto.getUserName())) {
|
||||
throw new BizException("用户名不能位空");
|
||||
}
|
||||
if (Objects.isNull(resetPasswordDto.getOldPassword())) {
|
||||
throw new BizException("旧密码不能位空");
|
||||
}
|
||||
if (Objects.isNull(resetPasswordDto.getNewPassword())) {
|
||||
throw new BizException("新密码不能位空");
|
||||
}
|
||||
Assert.notNull(resetPasswordDto.getUserName(), "用户名不能位空");
|
||||
Assert.notNull(resetPasswordDto.getOldPassword(), "旧密码不能位空");
|
||||
Assert.notNull(resetPasswordDto.getNewPassword(), "新密码不能位空");
|
||||
|
||||
SysUser sysUser = sysUserMapper.getByUsername(resetPasswordDto.getUserName());
|
||||
if (Objects.isNull(sysUser)) {
|
||||
throw new BizException("用户名不存在");
|
||||
}
|
||||
Assert.notNull(sysUser, "用户名不存在");
|
||||
|
||||
try {
|
||||
String oldMd5Pwd = MD5Util.encryptToHex(resetPasswordDto.getOldPassword() + sysUser.getSalt());
|
||||
if (!oldMd5Pwd.equals(sysUser.getPwd())) {
|
||||
throw new BizException("旧密码不正确");
|
||||
}
|
||||
Assert.equals(oldMd5Pwd, sysUser.getPwd(), "旧密码不正确");
|
||||
|
||||
String newMd5Pwd = MD5Util.encryptToHex(resetPasswordDto.getNewPassword() + sysUser.getSalt());
|
||||
sysUser.setPwd(newMd5Pwd);
|
||||
|
|
@ -366,17 +550,11 @@ public class SysUserServiceImpl implements SysUserService {
|
|||
|
||||
@Override
|
||||
public boolean resetPasswordByAdmin(ResetPasswordDto resetPasswordDto) {
|
||||
if (Objects.isNull(resetPasswordDto.getUserName())) {
|
||||
throw new BizException("用户名不能位空");
|
||||
}
|
||||
if (Objects.isNull(resetPasswordDto.getNewPassword())) {
|
||||
throw new BizException("新密码不能位空");
|
||||
}
|
||||
Assert.notNull(resetPasswordDto.getUserName(), "用户名不能位空");
|
||||
Assert.notNull(resetPasswordDto.getNewPassword(), "新密码不能位空");
|
||||
|
||||
SysUser sysUser = sysUserMapper.getByUsername(resetPasswordDto.getUserName());
|
||||
if (Objects.isNull(sysUser)) {
|
||||
throw new BizException("用户名不存在");
|
||||
}
|
||||
Assert.notNull(sysUser, "用户名不存在");
|
||||
|
||||
try {
|
||||
String newMd5Pwd = MD5Util.encryptToHex(resetPasswordDto.getNewPassword() + sysUser.getSalt());
|
||||
|
|
@ -409,15 +587,11 @@ public class SysUserServiceImpl implements SysUserService {
|
|||
@Override
|
||||
public boolean resetPwd(Long userId, String newPassword, String operator) {
|
||||
// 检查操作人是否为管理员
|
||||
if (!Const.ADMIN_USER_LIST.contains(operator.toLowerCase())) {
|
||||
throw new BizException("只有管理员才能执行此操作");
|
||||
}
|
||||
Assert.isTrue(Const.ADMIN_USER_LIST.contains(operator.toLowerCase()), "只有管理员才能执行此操作");
|
||||
|
||||
// 查询用户是否存在
|
||||
SysUser sysUser = sysUserMapper.queryById(userId);
|
||||
if (sysUser == null) {
|
||||
throw new BizException("用户不存在");
|
||||
}
|
||||
Assert.notNull(sysUser, "用户不存在");
|
||||
|
||||
try {
|
||||
// 生成新的加密密码
|
||||
|
|
@ -435,4 +609,208 @@ public class SysUserServiceImpl implements SysUserService {
|
|||
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
|
||||
cn.dev33.satoken.stp.StpUtil.login(sysUser.getUserId());
|
||||
// 获取生成的token
|
||||
String token = cn.dev33.satoken.stp.StpUtil.getTokenValue();
|
||||
|
||||
// 创建LoginUser对象
|
||||
LoginUser loginUser = new LoginUser();
|
||||
|
||||
// 设置用户基本信息
|
||||
sysUser.setPwd(null);
|
||||
loginUser.setUserInfo(sysUser);
|
||||
|
||||
// 查询用户角色列表
|
||||
List<String> roles = new java.util.ArrayList<>();
|
||||
try {
|
||||
// 创建查询条件,查询用户的角色关联记录
|
||||
SysUserRole userRole = new SysUserRole();
|
||||
userRole.setUserId(sysUser.getUserId());
|
||||
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();
|
||||
}
|
||||
loginUser.setRoles(roles);
|
||||
|
||||
// 查询用户已购买的内容ID列表
|
||||
List<Long> purchasedContentIds = new java.util.ArrayList<>();
|
||||
try {
|
||||
// 创建查询条件,查询用户的购买记录
|
||||
ContentPurchaseDto purchaseDto = new ContentPurchaseDto();
|
||||
purchaseDto.setUserId(sysUser.getUserId());
|
||||
List<ContentPurchase> purchases = contentPurchaseMapper.getList(purchaseDto);
|
||||
|
||||
// 遍历购买记录,获取内容ID
|
||||
for (ContentPurchase purchase : purchases) {
|
||||
purchasedContentIds.add(purchase.getContentId());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("查询用户已购买内容列表失败:{}", e.getMessage());
|
||||
purchasedContentIds = java.util.Collections.emptyList();
|
||||
}
|
||||
loginUser.setPurchasedContentIds(purchasedContentIds);
|
||||
|
||||
// 查询用户账户信息
|
||||
Account account = accountMapper.queryByUserId(sysUser.getUserId());
|
||||
loginUser.setAccount(account);
|
||||
|
||||
// 查询用户积分信息
|
||||
PointsAccount pointsAccount = pointsAccountMapper.queryByUserId(sysUser.getUserId());
|
||||
loginUser.setPointsAccount(pointsAccount);
|
||||
|
||||
// 查询并设置用户最近点赞记录
|
||||
loginUser.setFavorites(queryRecentFavorites(sysUser.getUserId()));
|
||||
|
||||
// 查询并设置用户最近查看记录
|
||||
loginUser.setHistory(queryRecentViews(sysUser.getUserId()));
|
||||
|
||||
// 查询并设置用户最近创建记录
|
||||
loginUser.setCreate(queryRecentCreatedContent(sysUser.getUserId()));
|
||||
|
||||
// 查询并设置用户最近购买记录
|
||||
loginUser.setHas(queryRecentPurchases(sysUser.getUserId()));
|
||||
|
||||
// 设置token
|
||||
loginUser.setToken(token);
|
||||
|
||||
// 将LoginUser对象存储到Redis缓存中,使用token作为key
|
||||
redisTemplate.opsForValue().set("loginUser:" + token, cn.hutool.json.JSONUtil.toJsonStr(loginUser), 3600, java.util.concurrent.TimeUnit.SECONDS);
|
||||
|
||||
// 创建LoginUserDto返回对象
|
||||
LoginUserDto sysUserDto = buildLoginUserDto(loginUser);
|
||||
|
||||
log.info("用户:{} 手机号登录成功,token:{}", phone, token);
|
||||
|
||||
return sysUserDto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据手机号创建用户
|
||||
*
|
||||
* @param phone 手机号
|
||||
* @return 创建的用户对象
|
||||
*/
|
||||
private SysUser createUserByPhone(String phone) {
|
||||
SysUser sysUser = new SysUser();
|
||||
|
||||
// 设置用户名(使用手机号作为用户名)
|
||||
sysUser.setUserName(phone);
|
||||
sysUser.setTel(phone);
|
||||
|
||||
// 生成随机密码
|
||||
String randomPassword = generateRandomPassword();
|
||||
sysUser.setPwd(randomPassword);
|
||||
|
||||
// 调用insert方法创建用户
|
||||
return insert(sysUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成随机密码
|
||||
*
|
||||
* @return 随机密码
|
||||
*/
|
||||
private String generateRandomPassword() {
|
||||
String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
Random random = new Random();
|
||||
StringBuilder sb = new StringBuilder(12);
|
||||
for (int i = 0; i < 12; i++) {
|
||||
sb.append(characters.charAt(random.nextInt(characters.length())));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,11 @@ spring:
|
|||
mode: HTML
|
||||
prefix: classpath:/templates/
|
||||
suffix: .html
|
||||
http:
|
||||
encoding:
|
||||
charset: UTF-8
|
||||
enabled: true
|
||||
force: true
|
||||
servlet:
|
||||
multipart:
|
||||
max-request-size: 20MB
|
||||
|
|
@ -44,3 +49,23 @@ pagehelper:
|
|||
supportMethodsArguments: true
|
||||
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>
|
||||
|
|
@ -269,5 +269,13 @@
|
|||
set view_count = view_count + 1
|
||||
where content_id = #{contentId}
|
||||
</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>
|
||||
|
|
@ -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}
|
||||
</if>
|
||||
</where>
|
||||
order by purchase_time desc
|
||||
</select>
|
||||
|
||||
<!--新增数据-->
|
||||
|
|
|
|||
|
|
@ -195,5 +195,14 @@
|
|||
and delete_flag = 0
|
||||
limit 1
|
||||
</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>
|
||||
|
|
|
|||
Loading…
Reference in New Issue