修复了一些 bug,添加了一些功能

修复了一些 bug,添加了一些功能
This commit is contained in:
ronger 2021-04-06 14:34:35 +08:00 committed by GitHub
commit 7be6107653
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
52 changed files with 715 additions and 244 deletions

11
pom.xml
View File

@ -172,7 +172,7 @@
<dependency> <dependency>
<groupId>com.github.binarywang</groupId> <groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-open</artifactId> <artifactId>weixin-java-open</artifactId>
<version>3.9.0</version> <version>4.0.0</version>
<exclusions> <exclusions>
<exclusion> <exclusion>
<groupId>commons-codec</groupId> <groupId>commons-codec</groupId>
@ -182,8 +182,17 @@
<groupId>commons-io</groupId> <groupId>commons-io</groupId>
<artifactId>commons-io</artifactId> <artifactId>commons-io</artifactId>
</exclusion> </exclusion>
<exclusion>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
</exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.16</version>
</dependency>
<dependency> <dependency>
<groupId>com.github.jedis-lock</groupId> <groupId>com.github.jedis-lock</groupId>
<artifactId>jedis-lock</artifactId> <artifactId>jedis-lock</artifactId>

View File

@ -3,6 +3,9 @@ package com.rymcu.forest;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author ronger
*/
@SpringBootApplication @SpringBootApplication
public class ForestApplication { public class ForestApplication {

View File

@ -3,8 +3,10 @@ package com.rymcu.forest.answer;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.rymcu.forest.core.result.GlobalResult; import com.rymcu.forest.core.result.GlobalResult;
import com.rymcu.forest.core.result.GlobalResultGenerator; import com.rymcu.forest.core.result.GlobalResultGenerator;
import com.rymcu.forest.core.service.log.annotation.TransactionLogger;
import com.rymcu.forest.dto.AnswerDTO; import com.rymcu.forest.dto.AnswerDTO;
import com.rymcu.forest.entity.User; import com.rymcu.forest.entity.User;
import com.rymcu.forest.enumerate.TransactionEnum;
import com.rymcu.forest.util.HttpUtils; import com.rymcu.forest.util.HttpUtils;
import com.rymcu.forest.util.UserUtils; import com.rymcu.forest.util.UserUtils;
import com.rymcu.forest.web.api.exception.BaseApiException; import com.rymcu.forest.web.api.exception.BaseApiException;
@ -30,6 +32,7 @@ public class AnswerController {
} }
@PostMapping("/answer") @PostMapping("/answer")
@TransactionLogger(transactionType = TransactionEnum.Answer)
public GlobalResult answer(@RequestBody AnswerDTO answerDTO) throws BaseApiException { public GlobalResult answer(@RequestBody AnswerDTO answerDTO) throws BaseApiException {
User user = UserUtils.getCurrentUserByToken(); User user = UserUtils.getCurrentUserByToken();
Map params = new HashMap<>(3); Map params = new HashMap<>(3);

View File

@ -2,8 +2,10 @@ package com.rymcu.forest.config;
import com.alibaba.fastjson.support.spring.FastJsonJsonView; import com.alibaba.fastjson.support.spring.FastJsonJsonView;
import com.rymcu.forest.core.exception.ServiceException; import com.rymcu.forest.core.exception.ServiceException;
import com.rymcu.forest.core.exception.TransactionException;
import com.rymcu.forest.core.result.GlobalResult; import com.rymcu.forest.core.result.GlobalResult;
import com.rymcu.forest.core.result.ResultCode; import com.rymcu.forest.core.result.ResultCode;
import com.rymcu.forest.enumerate.TransactionCode;
import com.rymcu.forest.web.api.exception.BaseApiException; import com.rymcu.forest.web.api.exception.BaseApiException;
import org.apache.shiro.authz.UnauthenticatedException; import org.apache.shiro.authz.UnauthenticatedException;
import org.apache.shiro.authz.UnauthorizedException; import org.apache.shiro.authz.UnauthorizedException;
@ -25,7 +27,7 @@ import java.util.Map;
* 全局异常处理器 * 全局异常处理器
* *
* @author ronger * @author ronger
* */ */
@RestControllerAdvice @RestControllerAdvice
public class BaseExceptionHandler { public class BaseExceptionHandler {
@ -33,10 +35,10 @@ public class BaseExceptionHandler {
@SuppressWarnings("Duplicates") @SuppressWarnings("Duplicates")
@ExceptionHandler(Exception.class) @ExceptionHandler(Exception.class)
public Object errorHandler(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex){ public Object errorHandler(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
if(isAjax(request)){ if (isAjax(request)) {
GlobalResult result = new GlobalResult(); GlobalResult result = new GlobalResult();
if (ex instanceof BaseApiException){ if (ex instanceof BaseApiException) {
result.setCode(401); result.setCode(401);
result.setMessage("用户未登录"); result.setMessage("用户未登录");
logger.info("用户未登录"); logger.info("用户未登录");
@ -48,7 +50,7 @@ public class BaseExceptionHandler {
result.setCode(1000002); result.setCode(1000002);
result.setMessage("用户无权限"); result.setMessage("用户无权限");
logger.info("用户无权限"); logger.info("用户无权限");
}else if (ex instanceof ServiceException) { } else if (ex instanceof ServiceException) {
//业务失败的异常账号或密码错误 //业务失败的异常账号或密码错误
result.setCode(((ServiceException) ex).getCode()); result.setCode(((ServiceException) ex).getCode());
result.setMessage(ex.getMessage()); result.setMessage(ex.getMessage());
@ -59,7 +61,10 @@ public class BaseExceptionHandler {
} else if (ex instanceof ServletException) { } else if (ex instanceof ServletException) {
result.setCode(ResultCode.FAIL.getCode()); result.setCode(ResultCode.FAIL.getCode());
result.setMessage(ex.getMessage()); result.setMessage(ex.getMessage());
}else { } else if (ex instanceof TransactionException) {
result.setCode(TransactionCode.InsufficientBalance.getCode());
result.setMessage(ex.getMessage());
} else {
//系统内部异常,不返回给客户端,内部记录错误日志 //系统内部异常,不返回给客户端,内部记录错误日志
result.setCode(ResultCode.INTERNAL_SERVER_ERROR.getCode()); result.setCode(ResultCode.INTERNAL_SERVER_ERROR.getCode());
String message; String message;
@ -78,11 +83,11 @@ public class BaseExceptionHandler {
} }
result.setSuccess(false); result.setSuccess(false);
return result; return result;
}else { } else {
ModelAndView mv = new ModelAndView(); ModelAndView mv = new ModelAndView();
FastJsonJsonView view = new FastJsonJsonView(); FastJsonJsonView view = new FastJsonJsonView();
Map<String, Object> attributes = new HashMap(2); Map<String, Object> attributes = new HashMap(2);
if (ex instanceof BaseApiException){ if (ex instanceof BaseApiException) {
attributes.put("code", "401"); attributes.put("code", "401");
attributes.put("message", "用户未登录"); attributes.put("message", "用户未登录");
} else if (ex instanceof UnauthenticatedException) { } else if (ex instanceof UnauthenticatedException) {
@ -93,18 +98,21 @@ public class BaseExceptionHandler {
attributes.put("message", "用户无权限"); attributes.put("message", "用户无权限");
} else if (ex instanceof ServiceException) { } else if (ex instanceof ServiceException) {
//业务失败的异常账号或密码错误 //业务失败的异常账号或密码错误
attributes.put("code",((ServiceException) ex).getCode()); attributes.put("code", ((ServiceException) ex).getCode());
attributes.put("message",ex.getMessage()); attributes.put("message", ex.getMessage());
logger.info(ex.getMessage()); logger.info(ex.getMessage());
} else if (ex instanceof NoHandlerFoundException) { } else if (ex instanceof NoHandlerFoundException) {
attributes.put("code",ResultCode.NOT_FOUND.getCode()); attributes.put("code", ResultCode.NOT_FOUND.getCode());
attributes.put("message",ResultCode.NOT_FOUND.getMessage()); attributes.put("message", ResultCode.NOT_FOUND.getMessage());
} else if (ex instanceof ServletException) { } else if (ex instanceof ServletException) {
attributes.put("code",ResultCode.FAIL.getCode()); attributes.put("code", ResultCode.FAIL.getCode());
attributes.put("message",ex.getMessage()); attributes.put("message", ex.getMessage());
}else { } else if (ex instanceof TransactionException) {
attributes.put("code", TransactionCode.InsufficientBalance.getCode());
attributes.put("message", ex.getMessage());
} else {
//系统内部异常,不返回给客户端,内部记录错误日志 //系统内部异常,不返回给客户端,内部记录错误日志
attributes.put("code",ResultCode.INTERNAL_SERVER_ERROR.getCode()); attributes.put("code", ResultCode.INTERNAL_SERVER_ERROR.getCode());
String message; String message;
if (handler instanceof HandlerMethod) { if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler; HandlerMethod handlerMethod = (HandlerMethod) handler;
@ -117,9 +125,9 @@ public class BaseExceptionHandler {
message = ex.getMessage(); message = ex.getMessage();
} }
logger.error(message, ex); logger.error(message, ex);
attributes.put("message","操作失败"); attributes.put("message", "操作失败");
} }
attributes.put("success",false); attributes.put("success", false);
view.setAttributesMap(attributes); view.setAttributesMap(attributes);
mv.setView(view); mv.setView(view);
return mv; return mv;

View File

@ -29,7 +29,7 @@ import java.util.List;
* @author ronger * @author ronger
* @since 2018/05/28 11:00 * @since 2018/05/28 11:00
* 自定义权限匹配和账号密码匹配 * 自定义权限匹配和账号密码匹配
* */ */
public class BaseShiroRealm extends AuthorizingRealm { public class BaseShiroRealm extends AuthorizingRealm {
@Resource @Resource
private RoleService roleService; private RoleService roleService;
@ -43,13 +43,13 @@ public class BaseShiroRealm extends AuthorizingRealm {
@Override @Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
Principal principal = (Principal)principals.getPrimaryPrincipal(); Principal principal = (Principal) principals.getPrimaryPrincipal();
User user = new User(); User user = new User();
user.setIdUser(principal.getId()); user.setIdUser(principal.getId());
try { try {
List<Role> roles = roleService.selectRoleByUser(user); List<Role> roles = roleService.selectRoleByUser(user);
for (Role role : roles) { for (Role role : roles) {
if(StringUtils.isNotBlank(role.getInputCode())){ if (StringUtils.isNotBlank(role.getInputCode())) {
authorizationInfo.addRole(role.getInputCode()); authorizationInfo.addRole(role.getInputCode());
} }
} }
@ -70,7 +70,7 @@ public class BaseShiroRealm extends AuthorizingRealm {
/** /**
* 认证回调函数, 登录时调用主要是用来进行身份认证的也就是说验证用户输入的账号和密码是否正确 * 认证回调函数, 登录时调用主要是用来进行身份认证的也就是说验证用户输入的账号和密码是否正确
* */ */
@Override @Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException { protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authcToken; UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
@ -90,10 +90,11 @@ public class BaseShiroRealm extends AuthorizingRealm {
if (user == null) { if (user == null) {
return null; return null;
} }
if (!"0".equals(user.getStatus())) { //账户冻结(是否允许登陆) // 账户冻结(是否允许登陆)
if (!"0".equals(user.getStatus())) {
throw new LockedAccountException(); throw new LockedAccountException();
} }
byte[] salt = Encodes.decodeHex(user.getPassword().substring(0,16)); byte[] salt = Encodes.decodeHex(user.getPassword().substring(0, 16));
return new SimpleAuthenticationInfo(new Principal(user, token.isMobileLogin()), return new SimpleAuthenticationInfo(new Principal(user, token.isMobileLogin()),
user.getPassword().substring(16), ByteSource.Util.bytes(salt), getName()); user.getPassword().substring(16), ByteSource.Util.bytes(salt), getName());
} }
@ -139,9 +140,9 @@ public class BaseShiroRealm extends AuthorizingRealm {
* 获取SESSIONID * 获取SESSIONID
*/ */
public String getSessionid() { public String getSessionid() {
try{ try {
return (String) Utils.getSession().getId(); return (String) Utils.getSession().getId();
}catch (Exception e) { } catch (Exception e) {
return ""; return "";
} }
} }

View File

@ -45,7 +45,7 @@ public class MybatisConfigurer {
//添加XML目录 //添加XML目录
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
factory.setMapperLocations(resolver.getResources("classpath:mapper/**/*.xml")); factory.setMapperLocations(resolver.getResources("classpath:mapper/**/*.xml"));
factory.setTypeHandlersPackage("com.rymcu.forest.util.handlers"); // factory.setTypeHandlersPackage("com.rymcu.forest.util.handlers");
return factory.getObject(); return factory.getObject();
} }

View File

@ -55,6 +55,7 @@ public class ShiroConfig implements EnvironmentAware {
filterChainDefinitionMap.put("/api/**", "anon"); filterChainDefinitionMap.put("/api/**", "anon");
filterChainDefinitionMap.put("/ws/**", "anon"); filterChainDefinitionMap.put("/ws/**", "anon");
filterChainDefinitionMap.put("/wss/**", "anon");
filterChainDefinitionMap.put("/wx/**", "anon"); filterChainDefinitionMap.put("/wx/**", "anon");
filterChainDefinitionMap.put("/**", "auth"); filterChainDefinitionMap.put("/**", "auth");
//配置shiro默认登录界面地址前后端分离中登录界面跳转应由前端路由控制后台仅返回json数据 //配置shiro默认登录界面地址前后端分离中登录界面跳转应由前端路由控制后台仅返回json数据

View File

@ -20,6 +20,7 @@ public class WebSocketStompConfig implements WebSocketMessageBrokerConfigurer {
public void registerStompEndpoints(StompEndpointRegistry registry) { public void registerStompEndpoints(StompEndpointRegistry registry) {
// 允许使用socketJs方式访问 即可通过http://IP:PORT/ws来和服务端websocket连接 // 允许使用socketJs方式访问 即可通过http://IP:PORT/ws来和服务端websocket连接
registry.addEndpoint("/ws").setAllowedOrigins("*").withSockJS(); registry.addEndpoint("/ws").setAllowedOrigins("*").withSockJS();
registry.addEndpoint("/wss").setAllowedOrigins("*").withSockJS();
} }
/** /**
@ -30,7 +31,7 @@ public class WebSocketStompConfig implements WebSocketMessageBrokerConfigurer {
public void configureMessageBroker(MessageBrokerRegistry registry) { public void configureMessageBroker(MessageBrokerRegistry registry) {
// 订阅Broker名称 user点对点 topic广播即群发 // 订阅Broker名称 user点对点 topic广播即群发
registry.enableSimpleBroker("/user","/public"); registry.enableSimpleBroker("/topic", "/user");
// 全局(客户端)使用的消息前缀 // 全局(客户端)使用的消息前缀
registry.setApplicationDestinationPrefixes("/app"); registry.setApplicationDestinationPrefixes("/app");
// 点对点使用的前缀 无需配置 默认/user // 点对点使用的前缀 无需配置 默认/user

View File

@ -3,9 +3,9 @@ package com.rymcu.forest.core.constant;
/** /**
* Shiro通用常量 * Shiro通用常量
* *
* @author ronger
*/ */
public interface ShiroConstants public interface ShiroConstants {
{
/** /**
* 当前登录的用户 * 当前登录的用户
*/ */
@ -54,7 +54,7 @@ public interface ShiroConstants
/** /**
* 验证码 * 验证码
*/ */
public static final String CURRENT_VALIDATECODE = "validateCode"; public static final String CURRENT_VALIDATE_CODE = "validateCode";
/** /**
* 验证码错误 * 验证码错误

View File

@ -0,0 +1,22 @@
package com.rymcu.forest.core.exception;
import com.rymcu.forest.enumerate.TransactionCode;
/**
* @author ronger
*/
public class TransactionException extends Exception {
private int code;
private String message;
public TransactionException(TransactionCode transactionCode) {
super(transactionCode.getMessage());
this.code = transactionCode.getCode();
}
public int getCode() {
return code;
}
}

View File

@ -2,18 +2,22 @@ package com.rymcu.forest.core.result;
/** /**
* 响应码枚举参考HTTP状态码的语义 * 响应码枚举参考HTTP状态码的语义
*
* @author ronger
*/ */
public enum ResultCode { public enum ResultCode {
SUCCESS(1, "SUCCESS"),//成功 // 成功
FAIL(400, "访问失败"),//失败 SUCCESS(1, "SUCCESS"),
UNAUTHORIZED(401, "签名错误"),//未认证签名错误 // 失败
NOT_FOUND(404, "此接口不存在"),//接口不存在 FAIL(400, "访问失败"),
INTERNAL_SERVER_ERROR(500, "系统繁忙,请稍后再试"),//服务器内部错误 // 未认证签名错误
INVALID_PARAM(10000, "参数错误"), UNAUTHORIZED(401, "签名错误"),
// 接口不存在
NOT_FOUND(404, "此接口不存在"),
// 服务器内部错误
; INTERNAL_SERVER_ERROR(500, "系统繁忙,请稍后再试"),
// 参数错误
INVALID_PARAM(10000, "参数错误");
private int code; private int code;
private String message; private String message;

View File

@ -13,13 +13,17 @@ import java.util.List;
/** /**
* 基于通用MyBatis Mapper插件的Service接口的实现 * 基于通用MyBatis Mapper插件的Service接口的实现
*
* @author ronger
*/ */
public abstract class AbstractService<T> implements Service<T> { public abstract class AbstractService<T> implements Service<T> {
@Autowired @Autowired
protected Mapper<T> mapper; protected Mapper<T> mapper;
/**
private Class<T> modelClass; // 当前泛型真实类型的Class * 当前泛型真实类型的Class
*/
private Class<T> modelClass;
public AbstractService() { public AbstractService() {
ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass(); ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();

View File

@ -8,16 +8,85 @@ import java.util.List;
/** /**
* Service 基础接口其他Service 接口 请继承该接口 * Service 基础接口其他Service 接口 请继承该接口
*
* @author ronger
*/ */
public interface Service<T> { public interface Service<T> {
void save(T model);//持久化 /**
void save(List<T> models);//批量持久化 * 持久化
void deleteById(String id);//通过主鍵刪除 *
void deleteByIds(String ids);//批量刪除 egids -> 1,2,3,4 * @param model
void update(T model);//更新 */
T findById(String id);//通过ID查找 void save(T model);
T findBy(String fieldName, Object value) throws TooManyResultsException, ServiceException; //通过Model中某个成员变量名称非数据表中column的名称查找,value需符合unique约束
List<T> findByIds(String ids);//通过多个ID查找//egids -> 1,2,3,4 /**
List<T> findByCondition(Condition condition);//根据条件查找 * 批量持久化
List<T> findAll();//获取所有 *
* @param models
*/
void save(List<T> models);
/**
* 通过主鍵刪除
*
* @param id
*/
void deleteById(String id);
/**
* 批量刪除 egids -> 1,2,3,4
*
* @param ids
*/
void deleteByIds(String ids);
/**
* 更新
*
* @param model
*/
void update(T model);
/**
* 通过ID查找
*
* @param id
* @return
*/
T findById(String id);
/**
* 通过Model中某个成员变量名称非数据表中column的名称查找,value需符合unique约束
*
* @param fieldName
* @param value
* @return
* @throws TooManyResultsException
* @throws ServiceException
*/
T findBy(String fieldName, Object value) throws TooManyResultsException, ServiceException;
/**
* 通过多个ID查找//egids -> 1,2,3,4
*
* @param ids
* @return
*/
List<T> findByIds(String ids);
/**
* 根据条件查找
*
* @param condition
* @return
*/
List<T> findByCondition(Condition condition);
/**
* 获取所有
*
* @return
*/
List<T> findAll();
} }

View File

@ -0,0 +1,94 @@
package com.rymcu.forest.core.service.log;
import com.rymcu.forest.core.result.GlobalResult;
import com.rymcu.forest.core.service.log.annotation.TransactionLogger;
import com.rymcu.forest.entity.TransactionRecord;
import com.rymcu.forest.entity.User;
import com.rymcu.forest.enumerate.TransactionEnum;
import com.rymcu.forest.service.TransactionRecordService;
import com.rymcu.forest.util.UserUtils;
import com.rymcu.forest.web.api.exception.BaseApiException;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Objects;
/**
* @author ronger
*
*/
@Aspect
@Component
public class TransactionAspect {
Logger logger = LoggerFactory.getLogger(TransactionAspect.class);
@Resource
private TransactionRecordService transactionRecordService;
@Pointcut("@annotation(com.rymcu.forest.core.service.log.annotation.TransactionLogger)")
public void pointCut() {}
/**
* 保存交易操作日志
*
* @param joinPoint 连接点
* @return 方法执行结果
* @throws Throwable 调用出错
*/
@AfterReturning(value = "pointCut()", returning="obj")
public void save(JoinPoint joinPoint, Object obj) throws Exception {
logger.info("保存交易记录 start ...");
/**
* 解析Log注解
*/
String methodName = joinPoint.getSignature().getName();
Method method = currentMethod(joinPoint, methodName);
TransactionLogger log = method.getAnnotation(TransactionLogger.class);
if (Objects.nonNull(log)) {
User user = UserUtils.getCurrentUserByToken();
GlobalResult globalResult = (GlobalResult) obj;
if (globalResult.isSuccess()) {
if (TransactionEnum.Answer.equals(log.transactionType())) {
if (globalResult.getData().equals(true)) {
transactionRecordService.bankTransfer(user.getIdUser(), TransactionEnum.CorrectAnswer);
} else {
transactionRecordService.bankTransfer(user.getIdUser(), TransactionEnum.Answer);
}
}
}
}
logger.info("保存交易记录 end ...");
}
/**
* 获取当前执行的方法
*
* @param joinPoint 连接点
* @param methodName 方法名称
* @return 方法
*/
private Method currentMethod(JoinPoint joinPoint, String methodName) {
/**
* 获取目标类的所有方法找到当前要执行的方法
*/
Method[] methods = joinPoint.getTarget().getClass().getMethods();
Method resultMethod = null;
for (Method method : methods) {
if (method.getName().equals(methodName)) {
resultMethod = method;
break;
}
}
return resultMethod;
}
}

View File

@ -0,0 +1,16 @@
package com.rymcu.forest.core.service.log.annotation;
import com.rymcu.forest.enumerate.TransactionEnum;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* @author ronger
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface TransactionLogger {
TransactionEnum transactionType();
}

View File

@ -12,6 +12,8 @@ public class Author {
private String userNickname; private String userNickname;
private String userAccount;
private String userAvatarURL; private String userAvatarURL;
private String userArticleCount; private String userArticleCount;

View File

@ -0,0 +1,12 @@
package com.rymcu.forest.dto;
import lombok.Data;
/**
* @author ronger
*/
@Data
public class UserSearchDTO {
private String nickname;
}

View File

@ -1,30 +0,0 @@
package com.rymcu.forest.enumerate;
/**
* @author ronger
*/
public enum SponsorEnum {
Article("0", 20);
private String dataType;
private Integer money;
SponsorEnum(String dataType, Integer money) {
this.dataType = dataType;
this.money = money;
}
public String getDataType() {
return this.dataType;
}
public Integer getMoney() {
return this.money;
}
public boolean isArticle() {
return Article.equals(this);
}
}

View File

@ -0,0 +1,28 @@
package com.rymcu.forest.enumerate;
/**
* @author ronger
*/
public enum TransactionCode {
InsufficientBalance(901, "余额不足");
private int code;
private String message;
TransactionCode(int code, String message) {
this.code = code;
this.message = message;
}
public String getMessage() {
return this.message;
}
public int getCode() {
return this.code;
}
}

View File

@ -0,0 +1,45 @@
package com.rymcu.forest.enumerate;
import java.util.Arrays;
/**
* @author ronger
*/
public enum TransactionEnum {
ArticleSponsor("0", 20, "文章赞赏"),
Answer("1", 30, "答题奖励"),
CorrectAnswer("2", 50, "答题奖励");
private String dataType;
private Integer money;
private String description;
TransactionEnum(String dataType, Integer money, String description) {
this.dataType = dataType;
this.money = money;
this.description = description;
}
public static TransactionEnum findTransactionEnum(String dataType) {
return Arrays.stream(TransactionEnum.values()).filter(transactionEnum -> transactionEnum.getDataType().equals(dataType)).findFirst().orElse(TransactionEnum.ArticleSponsor);
}
public String getDataType() {
return this.dataType;
}
public Integer getMoney() {
return this.money;
}
public String getDescription() {
return this.description;
}
public boolean isArticleSponsor() {
return ArticleSponsor.equals(this);
}
}

View File

@ -184,4 +184,10 @@ public interface ArticleMapper extends Mapper<Article> {
* @return * @return
*/ */
int updatePerfect(@Param("idArticle") Integer idArticle, @Param("articlePerfect") String articlePerfect); int updatePerfect(@Param("idArticle") Integer idArticle, @Param("articlePerfect") String articlePerfect);
/**
* 删除文章关联文章内容表信息
* @param idArticle
*/
void deleteArticleContent(@Param("idArticle") Integer idArticle);
} }

View File

@ -1,6 +1,7 @@
package com.rymcu.forest.mapper; package com.rymcu.forest.mapper;
import com.rymcu.forest.core.mapper.Mapper; import com.rymcu.forest.core.mapper.Mapper;
import com.rymcu.forest.dto.NotificationDTO;
import com.rymcu.forest.entity.Notification; import com.rymcu.forest.entity.Notification;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
@ -23,7 +24,7 @@ public interface NotificationMapper extends Mapper<Notification> {
* @param idUser * @param idUser
* @return * @return
*/ */
List<Notification> selectNotifications(@Param("idUser") Integer idUser); List<NotificationDTO> selectNotifications(@Param("idUser") Integer idUser);
/** /**
* 获取消息数据 * 获取消息数据

View File

@ -73,4 +73,10 @@ public interface PortfolioMapper extends Mapper<Portfolio> {
* @return * @return
*/ */
Integer unbindArticle(@Param("idPortfolio") Integer idPortfolio, @Param("idArticle") Integer idArticle); Integer unbindArticle(@Param("idPortfolio") Integer idPortfolio, @Param("idArticle") Integer idArticle);
/**
* 获取作品集列表数据
* @return
*/
List<Portfolio> selectPortfolios();
} }

View File

@ -27,4 +27,12 @@ public interface TransactionRecordMapper extends Mapper<TransactionRecord> {
* @return * @return
*/ */
List<TransactionRecordDTO> selectTransactionRecords(@Param("bankAccount") String bankAccount); List<TransactionRecordDTO> selectTransactionRecords(@Param("bankAccount") String bankAccount);
/**
* 校验今日是否已发放答题奖励
* @param bankAccount
* @param funds
* @return
*/
Boolean existsWithBankAccountAndFunds(@Param("bankAccount") String bankAccount, @Param("funds") String funds);
} }

View File

@ -4,9 +4,12 @@ import com.rymcu.forest.core.mapper.Mapper;
import com.rymcu.forest.dto.Author; import com.rymcu.forest.dto.Author;
import com.rymcu.forest.dto.UserDTO; import com.rymcu.forest.dto.UserDTO;
import com.rymcu.forest.dto.UserInfoDTO; import com.rymcu.forest.dto.UserInfoDTO;
import com.rymcu.forest.dto.UserSearchDTO;
import com.rymcu.forest.entity.User; import com.rymcu.forest.entity.User;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
import java.util.List;
/** /**
* @author ronger * @author ronger
*/ */
@ -36,10 +39,10 @@ public interface UserMapper extends Mapper<User> {
/** /**
* 根据用户昵称获取用户信息 * 根据用户昵称获取用户信息
* @param nickname * @param account
* @return * @return
*/ */
UserDTO selectUserDTOByNickname(@Param("nickname") String nickname); UserDTO selectUserDTOByAccount(@Param("account") String account);
/** /**
* 修改用户密码 * 修改用户密码
@ -136,4 +139,11 @@ public interface UserMapper extends Mapper<User> {
* @return * @return
*/ */
Integer updatePasswordById(@Param("idUser") Integer idUser, @Param("password") String password); Integer updatePasswordById(@Param("idUser") Integer idUser, @Param("password") String password);
/**
* 查询用户数据
* @param searchDTO
* @return
*/
List<User> selectUsers(@Param("searchDTO") UserSearchDTO searchDTO);
} }

View File

@ -32,4 +32,10 @@ public interface BankAccountService extends Service<BankAccount> {
* @return * @return
*/ */
BankAccount findByBankAccount(String bankAccount); BankAccount findByBankAccount(String bankAccount);
/**
* 查询系统社区银行
* @return
*/
BankAccount findSystemBankAccount();
} }

View File

@ -77,4 +77,10 @@ public interface PortfolioService extends Service<Portfolio> {
* @return * @return
*/ */
Map deletePortfolio(Integer idPortfolio); Map deletePortfolio(Integer idPortfolio);
/**
* 获取作品集列表数据
* @return
*/
List<Portfolio> findPortfolios();
} }

View File

@ -3,6 +3,7 @@ package com.rymcu.forest.service;
import com.rymcu.forest.core.service.Service; import com.rymcu.forest.core.service.Service;
import com.rymcu.forest.dto.TransactionRecordDTO; import com.rymcu.forest.dto.TransactionRecordDTO;
import com.rymcu.forest.entity.TransactionRecord; import com.rymcu.forest.entity.TransactionRecord;
import com.rymcu.forest.enumerate.TransactionEnum;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.List; import java.util.List;
@ -30,9 +31,18 @@ public interface TransactionRecordService extends Service<TransactionRecord> {
* 根据用户主键进行交易 * 根据用户主键进行交易
* @param toUserId * @param toUserId
* @param formUserId * @param formUserId
* @param money * @param transactionType
* @return * @return
* @throws Exception * @throws Exception
*/ */
TransactionRecord transferByUserId(Integer toUserId, Integer formUserId, BigDecimal money) throws Exception; TransactionRecord userTransfer(Integer toUserId, Integer formUserId, TransactionEnum transactionType) throws Exception;
/**
* 社区银行转账/奖励发放
* @param idUser
* @param transactionType
* @return
* @throws Exception
*/
TransactionRecord bankTransfer(Integer idUser, TransactionEnum transactionType) throws Exception;
} }

View File

@ -6,6 +6,7 @@ import com.rymcu.forest.entity.User;
import com.rymcu.forest.entity.UserExtend; import com.rymcu.forest.entity.UserExtend;
import org.apache.ibatis.exceptions.TooManyResultsException; import org.apache.ibatis.exceptions.TooManyResultsException;
import java.util.List;
import java.util.Map; import java.util.Map;
@ -42,11 +43,11 @@ public interface UserService extends Service<User> {
Map login(String account, String password); Map login(String account, String password);
/** /**
* 通过 nickname 获取用户信息接口 * 通过 account 获取用户信息接口
* @param nickname 昵称 * @param account 昵称
* @return UserDTO * @return UserDTO
* */ * */
UserDTO findUserDTOByNickname(String nickname); UserDTO findUserDTOByAccount(String account);
/** /**
* 找回密码接口 * 找回密码接口
@ -117,10 +118,10 @@ public interface UserService extends Service<User> {
/** /**
* 获取用户扩展信息 * 获取用户扩展信息
* @param nickname * @param account
* @return * @return
*/ */
UserExtend selectUserExtendByNickname(String nickname); UserExtend selectUserExtendByAccount(String account);
/** /**
* 更换邮箱 * 更换邮箱
@ -135,4 +136,11 @@ public interface UserService extends Service<User> {
* @return * @return
*/ */
Map updatePassword(UpdatePasswordDTO updatePasswordDTO); Map updatePassword(UpdatePasswordDTO updatePasswordDTO);
/**
* 查询用户列表
* @param searchDTO
* @return
*/
List<User> findUsers(UserSearchDTO searchDTO);
} }

View File

@ -187,10 +187,15 @@ public class ArticleServiceImpl extends AbstractService<Article> implements Arti
} }
if (StringUtils.isNotBlank(articleContentHtml)) { if (StringUtils.isNotBlank(articleContentHtml)) {
String previewContent = BaiDuAipUtils.getNewsSummary(newArticle.getArticleTitle(), articleContentHtml, MAX_PREVIEW); String previewContent;
if (articleContentHtml.length() > MAX_PREVIEW) {
previewContent = BaiDuAipUtils.getNewsSummary(newArticle.getArticleTitle(), articleContentHtml, MAX_PREVIEW);
if (previewContent.length() > MAX_PREVIEW) { if (previewContent.length() > MAX_PREVIEW) {
previewContent = previewContent.substring(0, MAX_PREVIEW); previewContent = previewContent.substring(0, MAX_PREVIEW);
} }
} else {
previewContent = Html2TextUtil.getContent(articleContentHtml);
}
newArticle.setArticlePreviewContent(previewContent); newArticle.setArticlePreviewContent(previewContent);
} }
articleMapper.updateByPrimaryKeySelective(newArticle); articleMapper.updateByPrimaryKeySelective(newArticle);
@ -268,6 +273,8 @@ public class ArticleServiceImpl extends AbstractService<Article> implements Arti
articleMapper.deleteLinkedPortfolioData(id); articleMapper.deleteLinkedPortfolioData(id);
// 删除引用标签记录 // 删除引用标签记录
articleMapper.deleteTagArticle(id); articleMapper.deleteTagArticle(id);
// 删除文章内容表
articleMapper.deleteArticleContent(id);
} }
@Override @Override
@ -381,9 +388,11 @@ public class ArticleServiceImpl extends AbstractService<Article> implements Arti
private Author genAuthor(ArticleDTO article) { private Author genAuthor(ArticleDTO article) {
Author author = new Author(); Author author = new Author();
User user = userService.findById(String.valueOf(article.getArticleAuthorId()));
author.setUserNickname(article.getArticleAuthorName()); author.setUserNickname(article.getArticleAuthorName());
author.setUserAvatarURL(article.getArticleAuthorAvatarUrl()); author.setUserAvatarURL(article.getArticleAuthorAvatarUrl());
author.setIdUser(article.getArticleAuthorId()); author.setIdUser(article.getArticleAuthorId());
author.setUserAccount(user.getAccount());
return author; return author;
} }
} }

View File

@ -67,6 +67,15 @@ public class BankAccountServiceImpl extends AbstractService<BankAccount> impleme
return bankAccountMapper.selectOne(searchBankAccount); return bankAccountMapper.selectOne(searchBankAccount);
} }
@Override
public BankAccount findSystemBankAccount() {
BankAccount bankAccount = new BankAccount();
bankAccount.setIdBank(1);
bankAccount.setAccountType("1");
bankAccount.setAccountOwner(2);
return bankAccountMapper.selectOne(bankAccount);
}
private String nextBankAccount() { private String nextBankAccount() {
String bankAccount = "600000001"; String bankAccount = "600000001";
String maxBankAccount = bankAccountMapper.selectMaxBankAccount(); String maxBankAccount = bankAccountMapper.selectMaxBankAccount();

View File

@ -49,13 +49,12 @@ public class NotificationServiceImpl extends AbstractService<Notification> imple
@Override @Override
public List<NotificationDTO> findNotifications(Integer idUser) { public List<NotificationDTO> findNotifications(Integer idUser) {
List<Notification> list = notificationMapper.selectNotifications(idUser); List<NotificationDTO> list = notificationMapper.selectNotifications(idUser);
List<NotificationDTO> notifications = new ArrayList<>();
list.forEach(notification -> { list.forEach(notification -> {
NotificationDTO notificationDTO = genNotification(notification); NotificationDTO notificationDTO = genNotification(notification);
// 判断关联数据是否已删除 // 判断关联数据是否已删除
if (Objects.nonNull(notificationDTO.getAuthor())) { if (Objects.nonNull(notificationDTO.getAuthor())) {
notifications.add(notificationDTO); BeanCopierUtil.copy(notificationDTO, notification);
} else { } else {
// 关联数据已删除,且未读 // 关联数据已删除,且未读
if (unRead.equals(notification.getHasRead())) { if (unRead.equals(notification.getHasRead())) {
@ -66,10 +65,10 @@ public class NotificationServiceImpl extends AbstractService<Notification> imple
dto.setDataType("-1"); dto.setDataType("-1");
dto.setHasRead("1"); dto.setHasRead("1");
dto.setCreatedTime(notification.getCreatedTime()); dto.setCreatedTime(notification.getCreatedTime());
notifications.add(dto); BeanCopierUtil.copy(dto, notification);
} }
}); });
return notifications; return list;
} }
private NotificationDTO genNotification(Notification notification) { private NotificationDTO genNotification(Notification notification) {

View File

@ -39,10 +39,7 @@ public class PortfolioServiceImpl extends AbstractService<Portfolio> implements
@Override @Override
public List<PortfolioDTO> findUserPortfoliosByUser(UserDTO userDTO) { public List<PortfolioDTO> findUserPortfoliosByUser(UserDTO userDTO) {
List<PortfolioDTO> list = portfolioMapper.selectUserPortfoliosByIdUser(userDTO.getIdUser()); List<PortfolioDTO> list = portfolioMapper.selectUserPortfoliosByIdUser(userDTO.getIdUser());
Author author = new Author(); Author author = userService.selectAuthor(userDTO.getIdUser());
author.setIdUser(userDTO.getIdUser());
author.setUserAvatarURL(userDTO.getAvatarUrl());
author.setUserNickname(userDTO.getNickname());
list.forEach(portfolioDTO -> { list.forEach(portfolioDTO -> {
genPortfolioAuthor(portfolioDTO,author); genPortfolioAuthor(portfolioDTO,author);
}); });
@ -174,6 +171,11 @@ public class PortfolioServiceImpl extends AbstractService<Portfolio> implements
return map; return map;
} }
@Override
public List<Portfolio> findPortfolios() {
return portfolioMapper.selectPortfolios();
}
private PortfolioDTO genPortfolioAuthor(PortfolioDTO portfolioDTO, Author author) { private PortfolioDTO genPortfolioAuthor(PortfolioDTO portfolioDTO, Author author) {
portfolioDTO.setPortfolioAuthorAvatarUrl(author.getUserAvatarURL()); portfolioDTO.setPortfolioAuthorAvatarUrl(author.getUserAvatarURL());
portfolioDTO.setPortfolioAuthorName(author.getUserNickname()); portfolioDTO.setPortfolioAuthorName(author.getUserNickname());

View File

@ -1,11 +1,14 @@
package com.rymcu.forest.service.impl; package com.rymcu.forest.service.impl;
import com.rymcu.forest.core.exception.TransactionException;
import com.rymcu.forest.core.service.AbstractService; import com.rymcu.forest.core.service.AbstractService;
import com.rymcu.forest.dto.ArticleDTO; import com.rymcu.forest.dto.ArticleDTO;
import com.rymcu.forest.entity.Sponsor; import com.rymcu.forest.entity.Sponsor;
import com.rymcu.forest.entity.TransactionRecord; import com.rymcu.forest.entity.TransactionRecord;
import com.rymcu.forest.entity.User; import com.rymcu.forest.entity.User;
import com.rymcu.forest.enumerate.SponsorEnum; import com.rymcu.forest.enumerate.TransactionCode;
import com.rymcu.forest.enumerate.TransactionEnum;
import com.rymcu.forest.mapper.SponsorMapper; import com.rymcu.forest.mapper.SponsorMapper;
import com.rymcu.forest.service.ArticleService; import com.rymcu.forest.service.ArticleService;
import com.rymcu.forest.service.SponsorService; import com.rymcu.forest.service.SponsorService;
@ -39,7 +42,7 @@ public class SponsorServiceImpl extends AbstractService<Sponsor> implements Spon
map.put("success", false); map.put("success", false);
map.put("message", "数据异常"); map.put("message", "数据异常");
} else { } else {
SponsorEnum result = Arrays.stream(SponsorEnum.values()).filter(sponsorEnum -> sponsorEnum.getDataType().equals(sponsor.getDataType())).findFirst().orElse(SponsorEnum.Article); TransactionEnum result = TransactionEnum.findTransactionEnum(sponsor.getDataType());
BigDecimal money = BigDecimal.valueOf(result.getMoney()); BigDecimal money = BigDecimal.valueOf(result.getMoney());
sponsor.setSponsorshipMoney(money); sponsor.setSponsorshipMoney(money);
User user = UserUtils.getCurrentUserByToken(); User user = UserUtils.getCurrentUserByToken();
@ -47,11 +50,11 @@ public class SponsorServiceImpl extends AbstractService<Sponsor> implements Spon
sponsor.setSponsorshipTime(new Date()); sponsor.setSponsorshipTime(new Date());
sponsorMapper.insertSelective(sponsor); sponsorMapper.insertSelective(sponsor);
// 赞赏金额划转 // 赞赏金额划转
if (result.isArticle()) { if (result.isArticleSponsor()) {
ArticleDTO articleDTO = articleService.findArticleDTOById(sponsor.getDataId(), 1); ArticleDTO articleDTO = articleService.findArticleDTOById(sponsor.getDataId(), 1);
TransactionRecord transactionRecord = transactionRecordService.transferByUserId(articleDTO.getArticleAuthorId(), user.getIdUser(), money); TransactionRecord transactionRecord = transactionRecordService.userTransfer(articleDTO.getArticleAuthorId(), user.getIdUser(), result);
if (Objects.isNull(transactionRecord.getIdTransactionRecord())) { if (Objects.isNull(transactionRecord.getIdTransactionRecord())) {
throw new Exception("余额不足"); throw new TransactionException(TransactionCode.InsufficientBalance);
} }
// 更新文章赞赏数 // 更新文章赞赏数
sponsorMapper.updateArticleSponsorCount(articleDTO.getIdArticle()); sponsorMapper.updateArticleSponsorCount(articleDTO.getIdArticle());

View File

@ -1,12 +1,14 @@
package com.rymcu.forest.service.impl; package com.rymcu.forest.service.impl;
import com.rymcu.forest.core.exception.ServiceException; import com.rymcu.forest.core.exception.TransactionException;
import com.rymcu.forest.core.service.AbstractService; import com.rymcu.forest.core.service.AbstractService;
import com.rymcu.forest.core.service.redis.RedisService; import com.rymcu.forest.core.service.redis.RedisService;
import com.rymcu.forest.dto.BankAccountDTO; import com.rymcu.forest.dto.BankAccountDTO;
import com.rymcu.forest.dto.TransactionRecordDTO; import com.rymcu.forest.dto.TransactionRecordDTO;
import com.rymcu.forest.entity.BankAccount; import com.rymcu.forest.entity.BankAccount;
import com.rymcu.forest.entity.TransactionRecord; import com.rymcu.forest.entity.TransactionRecord;
import com.rymcu.forest.enumerate.TransactionCode;
import com.rymcu.forest.enumerate.TransactionEnum;
import com.rymcu.forest.mapper.TransactionRecordMapper; import com.rymcu.forest.mapper.TransactionRecordMapper;
import com.rymcu.forest.service.BankAccountService; import com.rymcu.forest.service.BankAccountService;
import com.rymcu.forest.service.TransactionRecordService; import com.rymcu.forest.service.TransactionRecordService;
@ -47,7 +49,7 @@ public class TransactionRecordServiceImpl extends AbstractService<TransactionRec
transactionRecordMapper.insertSelective(transactionRecord); transactionRecordMapper.insertSelective(transactionRecord);
} }
} else { } else {
throw new Exception("余额不足"); throw new TransactionException(TransactionCode.InsufficientBalance);
} }
return transactionRecord; return transactionRecord;
} }
@ -58,17 +60,42 @@ public class TransactionRecordServiceImpl extends AbstractService<TransactionRec
} }
@Override @Override
public TransactionRecord transferByUserId(Integer toUserId, Integer formUserId, BigDecimal money) throws Exception { public TransactionRecord userTransfer(Integer toUserId, Integer formUserId, TransactionEnum transactionType) throws Exception {
BankAccountDTO toBankAccount = bankAccountService.findBankAccountByIdUser(toUserId); BankAccountDTO toBankAccount = bankAccountService.findBankAccountByIdUser(toUserId);
BankAccountDTO formBankAccount = bankAccountService.findBankAccountByIdUser(formUserId); BankAccountDTO formBankAccount = bankAccountService.findBankAccountByIdUser(formUserId);
TransactionRecord transactionRecord = new TransactionRecord(); TransactionRecord transactionRecord = new TransactionRecord();
transactionRecord.setToBankAccount(toBankAccount.getBankAccount()); transactionRecord.setToBankAccount(toBankAccount.getBankAccount());
transactionRecord.setFormBankAccount(formBankAccount.getBankAccount()); transactionRecord.setFormBankAccount(formBankAccount.getBankAccount());
transactionRecord.setMoney(money); transactionRecord.setMoney(new BigDecimal(transactionType.getMoney()));
transactionRecord.setFunds("赞赏"); transactionRecord.setFunds(transactionType.getDescription());
return transfer(transactionRecord); return transfer(transactionRecord);
} }
@Override
public TransactionRecord bankTransfer(Integer idUser, TransactionEnum transactionType) throws Exception {
BankAccountDTO toBankAccount = bankAccountService.findBankAccountByIdUser(idUser);
Boolean isTrue;
// 校验货币规则
switch (transactionType) {
case Answer:
case CorrectAnswer:
isTrue = transactionRecordMapper.existsWithBankAccountAndFunds(toBankAccount.getBankAccount(), transactionType.getDescription());
break;
default:
isTrue = true;
}
if (isTrue) {
BankAccount formBankAccount = bankAccountService.findSystemBankAccount();
TransactionRecord transactionRecord = new TransactionRecord();
transactionRecord.setToBankAccount(toBankAccount.getBankAccount());
transactionRecord.setFormBankAccount(formBankAccount.getBankAccount());
transactionRecord.setMoney(new BigDecimal(transactionType.getMoney()));
transactionRecord.setFunds(transactionType.getDescription());
return transfer(transactionRecord);
}
return null;
}
private String nextTransactionNo() { private String nextTransactionNo() {
String orderNo = "E"; String orderNo = "E";
String key = "orderId"; String key = "orderId";

View File

@ -20,10 +20,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.Date; import java.util.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/** /**
@ -119,8 +116,8 @@ public class UserServiceImpl extends AbstractService<User> implements UserServic
} }
@Override @Override
public UserDTO findUserDTOByNickname(String nickname) { public UserDTO findUserDTOByAccount(String account) {
UserDTO user = userMapper.selectUserDTOByNickname(nickname); UserDTO user = userMapper.selectUserDTOByAccount(account);
return user; return user;
} }
@ -242,7 +239,7 @@ public class UserServiceImpl extends AbstractService<User> implements UserServic
} }
@Override @Override
public UserExtend selectUserExtendByNickname(String nickname) { public UserExtend selectUserExtendByAccount(String nickname) {
return userExtendMapper.selectUserExtendByNickname(nickname); return userExtendMapper.selectUserExtendByNickname(nickname);
} }
@ -272,4 +269,9 @@ public class UserServiceImpl extends AbstractService<User> implements UserServic
map.put("message", "更新成功!"); map.put("message", "更新成功!");
return map; return map;
} }
@Override
public List<User> findUsers(UserSearchDTO searchDTO) {
return userMapper.selectUsers(searchDTO);
}
} }

View File

@ -4,6 +4,7 @@ import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo; import com.github.pagehelper.PageInfo;
import com.rymcu.forest.core.result.GlobalResult; import com.rymcu.forest.core.result.GlobalResult;
import com.rymcu.forest.core.result.GlobalResultGenerator; import com.rymcu.forest.core.result.GlobalResultGenerator;
import com.rymcu.forest.dto.UserSearchDTO;
import com.rymcu.forest.dto.admin.TopicTagDTO; import com.rymcu.forest.dto.admin.TopicTagDTO;
import com.rymcu.forest.dto.admin.UserRoleDTO; import com.rymcu.forest.dto.admin.UserRoleDTO;
import com.rymcu.forest.entity.*; import com.rymcu.forest.entity.*;
@ -18,8 +19,6 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import static java.util.Comparator.comparing;
/** /**
* @author ronger * @author ronger
* */ * */
@ -39,11 +38,9 @@ public class AdminController {
private SpecialDayService specialDayService; private SpecialDayService specialDayService;
@GetMapping("/users") @GetMapping("/users")
public GlobalResult<Map<String, Object>> users(@RequestParam(defaultValue = "0") Integer page, @RequestParam(defaultValue = "10") Integer rows){ public GlobalResult<Map<String, Object>> users(@RequestParam(defaultValue = "0") Integer page, @RequestParam(defaultValue = "10") Integer rows, UserSearchDTO searchDTO){
PageHelper.startPage(page, rows); PageHelper.startPage(page, rows);
List<User> list = userService.findAll(); List<User> list = userService.findUsers(searchDTO);
// 按最后登录时间进行倒序排序
list.sort(comparing(User::getLastLoginTime).reversed());
PageInfo<User> pageInfo = new PageInfo<>(list); PageInfo<User> pageInfo = new PageInfo<>(list);
Map<String, Object> map = new HashMap<String, Object>(2); Map<String, Object> map = new HashMap<String, Object>(2);
map.put("users", pageInfo.getList()); map.put("users", pageInfo.getList());

View File

@ -7,6 +7,7 @@ import com.rymcu.forest.core.result.GlobalResultGenerator;
import com.rymcu.forest.core.result.GlobalResultMessage; import com.rymcu.forest.core.result.GlobalResultMessage;
import com.rymcu.forest.core.service.log.annotation.VisitLogger; import com.rymcu.forest.core.service.log.annotation.VisitLogger;
import com.rymcu.forest.dto.*; import com.rymcu.forest.dto.*;
import com.rymcu.forest.entity.Portfolio;
import com.rymcu.forest.entity.User; import com.rymcu.forest.entity.User;
import com.rymcu.forest.service.*; import com.rymcu.forest.service.*;
import com.rymcu.forest.util.UserUtils; import com.rymcu.forest.util.UserUtils;
@ -140,4 +141,16 @@ public class CommonApiController {
List<SearchModel> list = SearchService.initialSearch(); List<SearchModel> list = SearchService.initialSearch();
return GlobalResultGenerator.genSuccessResult(list); return GlobalResultGenerator.genSuccessResult(list);
} }
@GetMapping("/portfolios")
public GlobalResult portfolios(@RequestParam(defaultValue = "0") Integer page, @RequestParam(defaultValue = "12") Integer rows) {
PageHelper.startPage(page, rows);
List<Portfolio> list = portfolioService.findPortfolios();
PageInfo<Portfolio> pageInfo = new PageInfo(list);
Map map = new HashMap(2);
map.put("portfolios", pageInfo.getList());
Map pagination = Utils.getPagination(pageInfo);
map.put("pagination", pagination);
return GlobalResultGenerator.genSuccessResult(map);
}
} }

View File

@ -1,7 +1,6 @@
package com.rymcu.forest.web.api.common; package com.rymcu.forest.web.api.common;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo; import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessagingTemplate; import org.springframework.messaging.simp.SimpMessagingTemplate;
@ -9,7 +8,7 @@ import org.springframework.messaging.simp.annotation.SendToUser;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor; import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import java.util.HashMap; import javax.annotation.Resource;
/** /**
* @author ronger * @author ronger
@ -17,42 +16,18 @@ import java.util.HashMap;
@Controller @Controller
public class WebSocketController { public class WebSocketController {
@Autowired @Resource
private SimpMessagingTemplate template; private SimpMessagingTemplate template;
@MessageMapping("/sendMessage") @MessageMapping("/sendMessage")
@SendTo("/public/greetings") @SendTo("/topic/greening")
public void sendMessage(JSONObject message, StompHeaderAccessor headerAccessor){ public void sendMessage(JSONObject message, StompHeaderAccessor headerAccessor) {
this.template.convertAndSend("/public/greetings",message); this.template.convertAndSend("/topic/greening", message);
} }
@MessageMapping("/message") @MessageMapping("/message")
@SendToUser("/message") @SendToUser("/message")
public void message(JSONObject message){ public void message(JSONObject message, StompHeaderAccessor headerAccessor) {
String type = message.get("type").toString(); this.template.convertAndSendToUser(message.getString("to"), "/message", message);
HashMap res = (HashMap) message.get("data");
HashMap mine = (HashMap) res.get("mine");
HashMap to = (HashMap) res.get("to");
System.out.println(to.get("type"));
boolean flag = to.get("type").equals("friend")?true:false;
String id = to.get("id").toString();
HashMap map = new HashMap();
map.put("id",mine.get("id"));
map.put("avatar",mine.get("avatar"));
map.put("formid",mine.get("id"));
map.put("username",mine.get("username"));
map.put("type",to.get("type"));
map.put("content",mine.get("content"));
map.put("mine",false);
map.put("cid",0);
map.put("timestamp","");
JSONObject json = new JSONObject();
json.put("type",type);
json.put("data",map);
if(flag){
this.template.convertAndSendToUser(id,"/message",json);
}else{
this.template.convertAndSendToUser(id,"/message",json);
}
} }
} }

View File

@ -37,16 +37,16 @@ public class UserController {
@Resource @Resource
private FollowService followService; private FollowService followService;
@GetMapping("/{nickname}") @GetMapping("/{account}")
@VisitLogger @VisitLogger
public GlobalResult detail(@PathVariable String nickname){ public GlobalResult detail(@PathVariable String account){
UserDTO userDTO = userService.findUserDTOByNickname(nickname); UserDTO userDTO = userService.findUserDTOByAccount(account);
return GlobalResultGenerator.genSuccessResult(userDTO); return GlobalResultGenerator.genSuccessResult(userDTO);
} }
@GetMapping("/{nickname}/articles") @GetMapping("/{account}/articles")
public GlobalResult userArticles(@RequestParam(defaultValue = "0") Integer page, @RequestParam(defaultValue = "12") Integer rows, @PathVariable String nickname){ public GlobalResult userArticles(@RequestParam(defaultValue = "0") Integer page, @RequestParam(defaultValue = "12") Integer rows, @PathVariable String account){
UserDTO userDTO = userService.findUserDTOByNickname(nickname); UserDTO userDTO = userService.findUserDTOByAccount(account);
if (userDTO == null){ if (userDTO == null){
return GlobalResultGenerator.genErrorResult("用户不存在!"); return GlobalResultGenerator.genErrorResult("用户不存在!");
} }
@ -57,9 +57,9 @@ public class UserController {
return GlobalResultGenerator.genSuccessResult(map); return GlobalResultGenerator.genSuccessResult(map);
} }
@GetMapping("/{nickname}/portfolios") @GetMapping("/{account}/portfolios")
public GlobalResult userPortfolios(@RequestParam(defaultValue = "0") Integer page, @RequestParam(defaultValue = "12") Integer rows, @PathVariable String nickname){ public GlobalResult userPortfolios(@RequestParam(defaultValue = "0") Integer page, @RequestParam(defaultValue = "12") Integer rows, @PathVariable String account){
UserDTO userDTO = userService.findUserDTOByNickname(nickname); UserDTO userDTO = userService.findUserDTOByAccount(account);
if (userDTO == null){ if (userDTO == null){
return GlobalResultGenerator.genErrorResult("用户不存在!"); return GlobalResultGenerator.genErrorResult("用户不存在!");
} }
@ -73,9 +73,9 @@ public class UserController {
return GlobalResultGenerator.genSuccessResult(map); return GlobalResultGenerator.genSuccessResult(map);
} }
@GetMapping("/{nickname}/followers") @GetMapping("/{account}/followers")
public GlobalResult userFollowers(@RequestParam(defaultValue = "0") Integer page, @RequestParam(defaultValue = "12") Integer rows, @PathVariable String nickname){ public GlobalResult userFollowers(@RequestParam(defaultValue = "0") Integer page, @RequestParam(defaultValue = "12") Integer rows, @PathVariable String account){
UserDTO userDTO = userService.findUserDTOByNickname(nickname); UserDTO userDTO = userService.findUserDTOByAccount(account);
if (userDTO == null){ if (userDTO == null){
return GlobalResultGenerator.genErrorResult("用户不存在!"); return GlobalResultGenerator.genErrorResult("用户不存在!");
} }
@ -89,9 +89,9 @@ public class UserController {
return GlobalResultGenerator.genSuccessResult(map); return GlobalResultGenerator.genSuccessResult(map);
} }
@GetMapping("/{nickname}/followings") @GetMapping("/{account}/followings")
public GlobalResult userFollowings(@RequestParam(defaultValue = "0") Integer page, @RequestParam(defaultValue = "12") Integer rows, @PathVariable String nickname){ public GlobalResult userFollowings(@RequestParam(defaultValue = "0") Integer page, @RequestParam(defaultValue = "12") Integer rows, @PathVariable String account){
UserDTO userDTO = userService.findUserDTOByNickname(nickname); UserDTO userDTO = userService.findUserDTOByAccount(account);
if (userDTO == null){ if (userDTO == null){
return GlobalResultGenerator.genErrorResult("用户不存在!"); return GlobalResultGenerator.genErrorResult("用户不存在!");
} }
@ -105,9 +105,9 @@ public class UserController {
return GlobalResultGenerator.genSuccessResult(map); return GlobalResultGenerator.genSuccessResult(map);
} }
@GetMapping("/{nickname}/user-extend") @GetMapping("/{account}/user-extend")
public GlobalResult userExtend(@PathVariable String nickname) { public GlobalResult userExtend(@PathVariable String account) {
UserExtend userExtend = userService.selectUserExtendByNickname(nickname); UserExtend userExtend = userService.selectUserExtendByAccount(account);
return GlobalResultGenerator.genSuccessResult(userExtend); return GlobalResultGenerator.genSuccessResult(userExtend);
} }

View File

@ -1,5 +1,6 @@
package com.rymcu.forest.wx.mp.controller; package com.rymcu.forest.wx.mp.controller;
import com.rymcu.forest.wx.mp.service.WxMenuService;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import me.chanjar.weixin.common.bean.menu.WxMenu; import me.chanjar.weixin.common.bean.menu.WxMenu;
import me.chanjar.weixin.common.bean.menu.WxMenuButton; import me.chanjar.weixin.common.bean.menu.WxMenuButton;
@ -7,8 +8,11 @@ import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.menu.WxMpGetSelfMenuInfoResult; import me.chanjar.weixin.mp.bean.menu.WxMpGetSelfMenuInfoResult;
import me.chanjar.weixin.mp.bean.menu.WxMpMenu; import me.chanjar.weixin.mp.bean.menu.WxMpMenu;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.io.IOException;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import static me.chanjar.weixin.common.api.WxConsts.MenuButtonType; import static me.chanjar.weixin.common.api.WxConsts.MenuButtonType;
@ -21,7 +25,8 @@ import static me.chanjar.weixin.common.api.WxConsts.MenuButtonType;
@RequestMapping("/wx/menu/{appId}") @RequestMapping("/wx/menu/{appId}")
public class WxMenuController { public class WxMenuController {
private final WxMpService wxService; private final WxMpService wxService;
@Resource
private WxMenuService wxMenuService;
/** /**
* <pre> * <pre>
* 自定义菜单创建接口 * 自定义菜单创建接口
@ -38,52 +43,9 @@ public class WxMenuController {
} }
@GetMapping("/create") @GetMapping("/create")
public String menuCreateSample(@PathVariable String appId) throws WxErrorException, MalformedURLException { public String menuCreateSample(@PathVariable String appId) throws WxErrorException, IOException {
WxMenu menu = new WxMenu();
WxMenuButton button1 = new WxMenuButton();
button1.setType(MenuButtonType.VIEW);
button1.setName("官方网站");
button1.setUrl("https://rymcu.com");
// WxMenuButton button2 = new WxMenuButton();
// button2.setType(WxConsts.BUTTON_MINIPROGRAM);
// button2.setName("小程序");
// button2.setAppId("wx286b93c14bbf93aa");
// button2.setPagePath("pages/lunar/index.html");
// button2.setUrl("http://mp.weixin.qq.com");
WxMenuButton button3 = new WxMenuButton();
button3.setName("学习教程");
menu.getButtons().add(button1);
// menu.getButtons().add(button2);
menu.getButtons().add(button3);
WxMenuButton button31 = new WxMenuButton();
button31.setType(MenuButtonType.VIEW);
button31.setName("51单片机入门教程");
button31.setUrl("https://mp.weixin.qq.com/mp/homepage?__biz=MzA3NjMzMzM1Mw==&hid=1&sn=672df75323f9976d990f6be14355070b");
// WxMenuButton button34 = new WxMenuButton();
// button34.setType(MenuButtonType.VIEW);
// button34.setName("获取用户信息");
//
// ServletRequestAttributes servletRequestAttributes =
// (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
// if (servletRequestAttributes != null) {
// HttpServletRequest request = servletRequestAttributes.getRequest();
// URL requestURL = new URL(request.getRequestURL().toString());
// String url = this.wxService.switchoverTo(appId).oauth2buildAuthorizationUrl(
// String.format("%s://%s/wx/redirect/%s/greet", requestURL.getProtocol(), requestURL.getHost(), appId),
// WxConsts.OAuth2Scope.SNSAPI_USERINFO, null);
// button34.setUrl(url);
// }
button3.getSubButtons().add(button31);
// button3.getSubButtons().add(button34);
this.wxService.switchover(appId); this.wxService.switchover(appId);
return this.wxService.getMenuService().menuCreate(menu); return this.wxService.getMenuService().menuCreate(wxMenuService.getMenus());
} }
/** /**

View File

@ -1,10 +1,10 @@
package com.rymcu.forest.wx.mp.controller; package com.rymcu.forest.wx.mp.controller;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import me.chanjar.weixin.common.bean.WxOAuth2UserInfo;
import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken;
import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap; import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
@ -27,8 +27,8 @@ public class WxRedirectController {
} }
try { try {
WxMpOAuth2AccessToken accessToken = wxService.getOAuth2Service().getAccessToken(code); WxOAuth2AccessToken accessToken = wxService.getOAuth2Service().getAccessToken(code);
WxMpUser user = wxService.getOAuth2Service().getUserInfo(accessToken, null); WxOAuth2UserInfo user = wxService.getOAuth2Service().getUserInfo(accessToken, null);
map.put("user", user); map.put("user", user);
} catch (WxErrorException e) { } catch (WxErrorException e) {
e.printStackTrace(); e.printStackTrace();

View File

@ -4,10 +4,10 @@ import com.rymcu.forest.service.WxUserService;
import com.rymcu.forest.util.ContextHolderUtils; import com.rymcu.forest.util.ContextHolderUtils;
import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.WxJsapiSignature; import me.chanjar.weixin.common.bean.WxJsapiSignature;
import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken;
import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.http.URIUtil; import me.chanjar.weixin.common.util.http.URIUtil;
import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpUser; import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
@ -44,7 +44,7 @@ public class WxoAuthController {
baseUrl = new StringBuilder(domain).append(contextPath); baseUrl = new StringBuilder(domain).append(contextPath);
} }
StringBuilder accessTokenUrl = baseUrl.append("/wx/oauth/" + appId + "/getAccessToken?redirectUrl=").append(URIUtil.encodeURIComponent(redirectUrl)); StringBuilder accessTokenUrl = baseUrl.append("/wx/oauth/" + appId + "/getAccessToken?redirectUrl=").append(URIUtil.encodeURIComponent(redirectUrl));
String oauth2Url = wxMpService.getOAuth2Service().buildAuthorizationUrl(accessTokenUrl.toString(), WxConsts.OAuth2Scope.SNSAPI_BASE, null); String oauth2Url = wxMpService.getOAuth2Service().buildAuthorizationUrl(accessTokenUrl.toString(), WxConsts.OAuth2Scope.SNSAPI_USERINFO, null);
return "redirect:" + oauth2Url; return "redirect:" + oauth2Url;
} }
@ -52,14 +52,14 @@ public class WxoAuthController {
@GetMapping("getAccessToken") @GetMapping("getAccessToken")
public String getAccessToken(@PathVariable String appId, @RequestParam(name = "code") String code, @RequestParam(name = "redirectUrl") String redirectUrl) throws Exception { public String getAccessToken(@PathVariable String appId, @RequestParam(name = "code") String code, @RequestParam(name = "redirectUrl") String redirectUrl) throws Exception {
wxMpService.switchoverTo(appId); wxMpService.switchoverTo(appId);
WxMpOAuth2AccessToken oAuth2AccessToken = wxMpService.getOAuth2Service().getAccessToken(code); WxOAuth2AccessToken oAuth2AccessToken = wxMpService.getOAuth2Service().getAccessToken(code);
boolean valid = wxMpService.getOAuth2Service().validateAccessToken(oAuth2AccessToken); boolean valid = wxMpService.getOAuth2Service().validateAccessToken(oAuth2AccessToken);
if (!valid) { if (!valid) {
throw new Exception("无权限"); throw new Exception("无权限");
} }
WxMpUser wxMpUser =wxMpService.getUserService().userInfo(oAuth2AccessToken.getOpenId()); WxMpUser wxMpUser = wxMpService.getUserService().userInfo(oAuth2AccessToken.getOpenId());
wxUserService.saveUser(wxMpUser,appId); wxUserService.saveUser(wxMpUser, appId);
ContextHolderUtils.getSession2().setAttribute("wxUser", wxMpUser); ContextHolderUtils.getSession2().setAttribute("wxUser", wxMpUser);
return "redirect:" + redirectUrl; return "redirect:" + redirectUrl;
} }

View File

@ -0,0 +1,17 @@
package com.rymcu.forest.wx.mp.service;
import me.chanjar.weixin.common.bean.menu.WxMenu;
import java.io.IOException;
/**
* @author ronger
*/
public interface WxMenuService {
/**
* 获取公众号菜单配置
* @return
* @throws IOException
*/
WxMenu getMenus() throws IOException;
}

View File

@ -0,0 +1,46 @@
package com.rymcu.forest.wx.mp.service.impl;
import com.rymcu.forest.wx.mp.service.WxMenuService;
import me.chanjar.weixin.common.bean.menu.WxMenu;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
/**
* @author ronger
*/
@Service
public class WxMenuServiceImpl implements WxMenuService {
@Value("classpath:wxMpMenus.json")
private Resource menuResource;
@Override
public WxMenu getMenus() throws IOException {
File file = menuResource.getFile();
String menuJson = this.jsonRead(file);
WxMenu wxMenu = WxMenu.fromJson(menuJson);
return wxMenu;
}
private String jsonRead(File file) {
Scanner scanner = null;
StringBuilder buffer = new StringBuilder();
try {
scanner = new Scanner(file, "utf-8");
while (scanner.hasNextLine()) {
buffer.append(scanner.nextLine());
}
} catch (Exception e) {
} finally {
if (scanner != null) {
scanner.close();
}
}
return buffer.toString();
}
}

View File

@ -97,6 +97,9 @@
<delete id="deleteLinkedPortfolioData"> <delete id="deleteLinkedPortfolioData">
delete from forest_portfolio_article where id_article = #{id} delete from forest_portfolio_article where id_article = #{id}
</delete> </delete>
<delete id="deleteArticleContent">
delete from forest_article_content where id_article = #{idArticle}
</delete>
<select id="selectArticles" resultMap="DTOResultMap"> <select id="selectArticles" resultMap="DTOResultMap">
select art.*,su.nickname,su.avatar_url from forest_article art join forest_user su on art.article_author_id = su.id select art.*,su.nickname,su.avatar_url from forest_article art join forest_user su on art.article_author_id = su.id
where article_status = 0 where article_status = 0
@ -142,12 +145,14 @@
and instr(art.article_title, #{searchText}) > 0 and art.id not in (select id_article from forest_portfolio_article where id_portfolio = #{idPortfolio}) order by updated_time desc and instr(art.article_title, #{searchText}) > 0 and art.id not in (select id_article from forest_portfolio_article where id_portfolio = #{idPortfolio}) order by updated_time desc
</select> </select>
<select id="selectPortfolioArticles" resultMap="PortfolioArticleResultMap"> <select id="selectPortfolioArticles" resultMap="PortfolioArticleResultMap">
select vp.portfolio_title,vp.portfolio_head_img_url,vpa.id_portfolio,vpa.id_article,vpa.sort_no from forest_portfolio vp join forest_portfolio_article vpa on vp.id = vpa.id_portfolio where vpa.id_article = #{idArticle} select vp.portfolio_title,vp.portfolio_head_img_url,vpa.id_portfolio,vpa.id_article,vpa.sort_no from forest_portfolio vp
join forest_portfolio_article vpa on vp.id = vpa.id_portfolio where vpa.id_article = #{idArticle}
</select> </select>
<select id="existsCommentWithPrimaryKey" resultType="java.lang.Boolean"> <select id="existsCommentWithPrimaryKey" resultType="java.lang.Boolean">
select exists (select * from forest_comment where comment_article_id = #{id}) select exists (select * from forest_comment where comment_article_id = #{id})
</select> </select>
<select id="selectPortfolioArticlesByIdPortfolioAndSortNo" resultMap="DTOResultMap"> <select id="selectPortfolioArticlesByIdPortfolioAndSortNo" resultMap="DTOResultMap">
select va.article_title, va.id, va.article_permalink from forest_portfolio_article vpa join forest_article va on va.id = vpa.id_article where id_portfolio = #{idPortfolio} order by sort_no select va.article_title, va.id, va.article_permalink from forest_portfolio_article vpa
join forest_article va on va.id = vpa.id_article where va.article_status = '0' and id_portfolio = #{idPortfolio} order by sort_no
</select> </select>
</mapper> </mapper>

View File

@ -10,6 +10,15 @@
<result column="has_read" property="hasRead"></result> <result column="has_read" property="hasRead"></result>
<result column="created_time" property="createdTime"></result> <result column="created_time" property="createdTime"></result>
</resultMap> </resultMap>
<resultMap id="DTOResultMapper" type="com.rymcu.forest.dto.NotificationDTO">
<id column="id" property="idNotification"></id>
<result column="id_user" property="idUser"></result>
<result column="data_type" property="dataType"></result>
<result column="data_id" property="dataId"></result>
<result column="data_summary" property="dataSummary"></result>
<result column="has_read" property="hasRead"></result>
<result column="created_time" property="createdTime"></result>
</resultMap>
<insert id="insertNotification"> <insert id="insertNotification">
insert into forest_notification (id_user, data_type, data_id, data_summary, created_time) values (#{idUser}, #{dataType}, #{dataId}, #{dataSummary}, sysdate()) insert into forest_notification (id_user, data_type, data_id, data_summary, created_time) values (#{idUser}, #{dataType}, #{dataId}, #{dataSummary}, sysdate())
</insert> </insert>
@ -19,8 +28,8 @@
<select id="selectUnreadNotifications" resultMap="BaseResultMapper"> <select id="selectUnreadNotifications" resultMap="BaseResultMapper">
select * from forest_notification where has_read = '0' and id_user = #{idUser} order by created_time desc select * from forest_notification where has_read = '0' and id_user = #{idUser} order by created_time desc
</select> </select>
<select id="selectNotifications" resultMap="BaseResultMapper"> <select id="selectNotifications" resultMap="DTOResultMapper">
select * from forest_notification where id_user = #{idUser} order by created_time desc select * from forest_notification where id_user = #{idUser} order by has_read,created_time desc
</select> </select>
<select id="selectNotification" resultMap="BaseResultMapper"> <select id="selectNotification" resultMap="BaseResultMapper">
select * from forest_notification where id_user = #{idUser} and data_id = #{dataId} and data_type = #{dataType} select * from forest_notification where id_user = #{idUser} and data_id = #{dataId} and data_type = #{dataType}

View File

@ -51,4 +51,7 @@
<select id="selectMaxSortNo" resultType="java.lang.Integer"> <select id="selectMaxSortNo" resultType="java.lang.Integer">
select ifnull(max(sort_no),0) + 1 from forest_portfolio_article where id_portfolio = #{idPortfolio} select ifnull(max(sort_no),0) + 1 from forest_portfolio_article where id_portfolio = #{idPortfolio}
</select> </select>
<select id="selectPortfolios" resultMap="BaseResultMap">
select * from forest_portfolio order by updated_time desc
</select>
</mapper> </mapper>

View File

@ -16,6 +16,10 @@
update forest_bank_account set account_balance = account_balance + #{money} where bank_account = #{toBankAccount}; update forest_bank_account set account_balance = account_balance + #{money} where bank_account = #{toBankAccount};
</update> </update>
<select id="selectTransactionRecords" resultMap="DTOResultMap"> <select id="selectTransactionRecords" resultMap="DTOResultMap">
select * from forest_transaction_record where form_bank_account = #{bankAccount} or to_bank_account = #{bankAccount} select * from forest_transaction_record where form_bank_account = #{bankAccount} or to_bank_account = #{bankAccount} order by transaction_time desc
</select>
<select id="existsWithBankAccountAndFunds" resultType="java.lang.Boolean">
select ifnull((select false from forest_transaction_record where to_bank_account = #{bankAccount}
and funds = #{funds} and transaction_time > str_to_date(date_format(sysdate(),'%Y-%m-%d'),'%Y-%m-%d') limit 1), true)
</select> </select>
</mapper> </mapper>

View File

@ -45,6 +45,7 @@
<result column="id" property="idUser"/> <result column="id" property="idUser"/>
<result column="nickname" property="userNickname"/> <result column="nickname" property="userNickname"/>
<result column="avatar_url" property="userAvatarURL"/> <result column="avatar_url" property="userAvatarURL"/>
<result column="account" property="userAccount"/>
</resultMap> </resultMap>
<insert id="insertUserRole"> <insert id="insertUserRole">
insert into forest_user_role (id_user,id_role,created_time) values (#{idUser},#{idRole},sysdate()) insert into forest_user_role (id_user,id_role,created_time) values (#{idUser},#{idRole},sysdate())
@ -81,8 +82,8 @@
<select id="findUserInfoByAccount" resultMap="UserInfoResultMapper"> <select id="findUserInfoByAccount" resultMap="UserInfoResultMapper">
select id, nickname, sex, avatar_type, avatar_url, email, phone, account, status, signature, last_login_time from forest_user where account = #{account} select id, nickname, sex, avatar_type, avatar_url, email, phone, account, status, signature, last_login_time from forest_user where account = #{account}
</select> </select>
<select id="selectUserDTOByNickname" resultMap="DTOResultMapper"> <select id="selectUserDTOByAccount" resultMap="DTOResultMapper">
select id, nickname, avatar_type, avatar_url, account, signature from forest_user where nickname = #{nickname} and status = 0 select id, nickname, avatar_type, avatar_url, account, signature from forest_user where account = #{account} and status = 0
</select> </select>
<select id="selectRoleWeightsByUser" resultType="java.lang.Integer"> <select id="selectRoleWeightsByUser" resultType="java.lang.Integer">
select vr.weights from forest_role vr left join forest_user_role vur on vr.id = vur.id_role where vur.id_user = #{idUser} select vr.weights from forest_role vr left join forest_user_role vur on vr.id = vur.id_role where vur.id_user = #{idUser}
@ -99,5 +100,14 @@
<select id="selectAuthor" resultMap="AuthorResultMap"> <select id="selectAuthor" resultMap="AuthorResultMap">
select * from forest_user where id = #{id} select * from forest_user where id = #{id}
</select> </select>
<select id="selectUsers" resultMap="BaseResultMap">
select id, nickname, sex, avatar_type, avatar_url, email, account, status, last_login_time, created_time from forest_user
<where>
<if test="searchDTO.nickname != null and searchDTO.nickname != ''">
and instr(nickname, #{searchDTO.nickname}) > 0
</if>
</where>
order by last_login_time desc
</select>
</mapper> </mapper>

View File

@ -84,7 +84,7 @@ create table forest_comment
comment_original_comment_id bigint null comment '父评论 id', comment_original_comment_id bigint null comment '父评论 id',
comment_status char default '0' null comment '状态', comment_status char default '0' null comment '状态',
comment_ip varchar(128) null comment '评论 IP', comment_ip varchar(128) null comment '评论 IP',
comment_ua varchar(128) null comment 'User-Agent', comment_ua varchar(512) null comment 'User-Agent',
comment_anonymous char null comment '0公开回帖1匿名回帖', comment_anonymous char null comment '0公开回帖1匿名回帖',
comment_reply_count int null comment '回帖计数', comment_reply_count int null comment '回帖计数',
comment_visible char null comment '0所有人可见1仅楼主和自己可见', comment_visible char null comment '0所有人可见1仅楼主和自己可见',

View File

@ -0,0 +1,26 @@
{
"menu": {
"button": [
{
"type": "view",
"name": "官方网站",
"url": "https://rymcu.com"
},
{
"type": "view",
"name": "交流群",
"url": "https://mp.weixin.qq.com/s/0XDVL3mgrSpeGEALOQz-4Q"
},
{
"name": "学习教程",
"sub_button": [
{
"type": "view",
"name": "51单片机入门教程",
"url": "https://mp.weixin.qq.com/mp/homepage?__biz=MzA3NjMzMzM1Mw==&hid=1&sn=672df75323f9976d990f6be14355070b"
}
]
}
]
}
}