更新系统

This commit is contained in:
清晨
2025-04-03 10:50:11 +08:00
commit 242237c7e6
1414 changed files with 120299 additions and 0 deletions

26
ruoyi-mall-api/Dockerfile Normal file
View File

@@ -0,0 +1,26 @@
# 贝尔实验室 Spring 官方推荐镜像 JDK下载地址 https://bell-sw.com/pages/downloads/
FROM bellsoft/liberica-openjdk-debian:17.0.11-cds
#FROM bellsoft/liberica-openjdk-debian:21.0.3-cds
#FROM findepi/graalvm:java17-native
LABEL maintainer="Lion Li"
RUN mkdir -p /ruoyi/server/logs \
/ruoyi/server/temp \
/ruoyi/skywalking/agent
WORKDIR /ruoyi/server
ENV SERVER_PORT=8080 LANG=C.UTF-8 LC_ALL=C.UTF-8 JAVA_OPTS=""
EXPOSE ${SERVER_PORT}
ADD ./target/ruoyi-admin.jar ./app.jar
ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom -Dserver.port=${SERVER_PORT} \
# 应用名称 如果想区分集群节点监控 改成不同的名称即可
#-Dskywalking.agent.service_name=ruoyi-server \
#-javaagent:/ruoyi/skywalking/agent/skywalking-agent.jar \
-XX:+HeapDumpOnOutOfMemoryError -XX:+UseZGC ${JAVA_OPTS} \
-jar app.jar

120
ruoyi-mall-api/pom.xml Normal file
View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ruoyi-vue-plus</artifactId>
<groupId>org.dromara</groupId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<artifactId>ruoyi-mall-api</artifactId>
<description>
商城api接口服务
</description>
<dependencies>
<!-- Mysql驱动包 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-doc</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-social</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-ratelimiter</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-redis</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-system</artifactId>
</dependency>
<!-- 商城模块 -->
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-mall</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-pay</artifactId>
<version>5.3.0</version>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-crypto</artifactId>
<version>${spring-security-crypto.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.17.0</version>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>${maven-jar-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>${maven-war-plugin.version}</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
<warName>${project.artifactId}</warName>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,23 @@
package org.dromara;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup;
/**
* 启动程序
*
* @author Lion Li
*/
@SpringBootApplication
public class MallApiApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(MallApiApplication.class);
application.setApplicationStartup(new BufferingApplicationStartup(2048));
application.run(args);
System.out.println("(♥◠‿◠)ノ゙ 商城接口服务启动成功 ლ(´ڡ`ლ)゙");
}
}

View File

@@ -0,0 +1,18 @@
package org.dromara;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
/**
* web容器中进行部署
*
* @author Lion Li
*/
public class MallApiServletInitializer extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(MallApiApplication.class);
}
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
*
* https://www.mall4j.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package org.dromara.web.common;
import com.alibaba.ttl.TransmittableThreadLocal;
/**
* @author FrozenWatermelon
* @date 2020/7/16
*/
public class AuthUserContext {
private static final ThreadLocal<UserInfoInTokenBO> USER_INFO_IN_TOKEN_HOLDER = new TransmittableThreadLocal<>();
public static UserInfoInTokenBO get() {
return USER_INFO_IN_TOKEN_HOLDER.get();
}
public static void set(UserInfoInTokenBO userInfoInTokenBo) {
USER_INFO_IN_TOKEN_HOLDER.set(userInfoInTokenBo);
}
public static void clean() {
if (USER_INFO_IN_TOKEN_HOLDER.get() != null) {
USER_INFO_IN_TOKEN_HOLDER.remove();
}
}
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
*
* https://www.mall4j.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package org.dromara.web.common;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
/**
* @author lanhai
*/
public class HttpContextUtils {
public static HttpServletRequest getHttpServletRequest() {
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
}
public static String getDomain(){
HttpServletRequest request = getHttpServletRequest();
StringBuffer url = request.getRequestURL();
return url.delete(url.length() - request.getRequestURI().length(), url.length()).toString();
}
public static String getOrigin(){
HttpServletRequest request = getHttpServletRequest();
return request.getHeader("Origin");
}
}

View File

@@ -0,0 +1,38 @@
package org.dromara.web.common;
/**
* @author 菠萝凤梨
* @date 2022/3/28 14:32
*/
public interface OauthCacheNames {
/**
* oauth 授权相关key
*/
String OAUTH_PREFIX = "mall4j_oauth:";
/**
* token 授权相关key
*/
String OAUTH_TOKEN_PREFIX = OAUTH_PREFIX + "token:";
/**
* 保存token 缓存使用key
*/
String ACCESS = OAUTH_TOKEN_PREFIX + "access:";
/**
* 刷新token 缓存使用key
*/
String REFRESH_TO_ACCESS = OAUTH_TOKEN_PREFIX + "refresh_to_access:";
/**
* 根据uid获取保存的token key缓存使用的key
*/
String UID_TO_ACCESS = OAUTH_TOKEN_PREFIX + "uid_to_access:";
/**
* 保存token的用户信息使用的key
*/
String USER_INFO = OAUTH_TOKEN_PREFIX + "user_info:";
}

View File

@@ -0,0 +1,128 @@
/*
* Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
*
* https://www.mall4j.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package org.dromara.web.common;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.media.Schema;
import org.springdoc.core.annotations.ParameterObject;
import java.util.List;
/**
* @author lanhai
*/
@Schema
@ParameterObject
public class PageParam<T> extends Page<T> {
/**
* 每页显示条数,默认 10
*/
@Schema(description = "每页大小默认10")
private long size = 10;
/**
* 当前页
*/
@Schema(description = "当前页默认1")
private long current = 1;
/**
* 查询数据列表
*/
@Hidden
private List<T> records;
/**
* 总数
*/
@Hidden
private long total = 0;
/**
* 是否进行 count 查询
*/
@JsonIgnore
private boolean isSearchCount = true;
@JsonIgnore
private String countId;
@JsonIgnore
private Long maxLimit;
@JsonIgnore
private boolean optimizeCountSql;
@Override
public List<T> getRecords() {
return this.records;
}
@Override
public Page<T> setRecords(List<T> records) {
this.records = records;
return this;
}
@Override
public long getTotal() {
return this.total;
}
@Override
public Page<T> setTotal(long total) {
this.total = total;
return this;
}
@JsonIgnore
public boolean getSearchCount() {
if (total < 0) {
return false;
}
return isSearchCount;
}
@Override
public Page<T> setSearchCount(boolean isSearchCount) {
this.isSearchCount = isSearchCount;
return this;
}
@Override
public long getSize() {
return this.size;
}
@Override
public Page<T> setSize(long size) {
int maxSize = 100;
if (size > maxSize) {
this.size = maxSize;
} else {
this.size = size;
}
return this;
}
@Override
public long getCurrent() {
return this.current;
}
@Override
public Page<T> setCurrent(long current) {
this.current = current;
return this;
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
*
* https://www.mall4j.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package org.dromara.web.common;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;
import org.dromara.common.core.exception.user.UserException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.nio.charset.StandardCharsets;
/**
* @author 菠萝凤梨
* @date 2022/1/19 16:02
*/
@Component
public class PasswordManager {
private static final Logger logger = LoggerFactory.getLogger(PasswordManager.class);
/**
* 用于aes签名的key16位
*/
@Value("${auth.password.signKey:-mall4j-password}")
public String passwordSignKey;
public String decryptPassword(String data) {
// 在使用oracle的JDK时JAR包必须签署特殊的证书才能使用。
// 解决方案 1.使用openJDK或者非oracle的JDK建议 2.添加证书
// hutool的aes报错可以打开下面那段代码
SecureUtil.disableBouncyCastle();
AES aes = new AES(passwordSignKey.getBytes(StandardCharsets.UTF_8));
String decryptStr;
String decryptPassword;
try {
decryptStr = aes.decryptStr(data);
decryptPassword = decryptStr.substring(13);
} catch (Exception e) {
logger.error("Exception:", e);
throw new UserException("AES解密错误", e);
}
return decryptPassword;
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
*
* https://www.mall4j.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package org.dromara.web.common;
/**
* @author FrozenWatermelon
* @date 2020/7/9
*/
public enum ResponseEnum {
/**
* ok
*/
OK("00000", "ok"),
SHOW_FAIL("A00001", ""),
/**
* 用于直接显示提示用户的错误,内容由输入内容决定
*/
/**
* 用于直接显示提示系统的成功,内容由输入内容决定
*/
SHOW_SUCCESS("A00002", ""),
/**
* 未授权
*/
UNAUTHORIZED("A00004", "Unauthorized"),
/**
* 服务器出了点小差
*/
EXCEPTION("A00005", "服务器出了点小差"),
/**
* 方法参数没有校验,内容由输入内容决定
*/
METHOD_ARGUMENT_NOT_VALID("A00014", "方法参数没有校验");
private final String code;
private final String msg;
public String value() {
return code;
}
public String getMsg() {
return msg;
}
ResponseEnum(String code, String msg) {
this.code = code;
this.msg = msg;
}
@Override
public String toString() {
return "ResponseEnum{" + "code='" + code + '\'' + ", msg='" + msg + '\'' + "} " + super.toString();
}
}

View File

@@ -0,0 +1,49 @@
package org.dromara.web.common;
import lombok.experimental.UtilityClass;
/**
* @author LGH
*/
@UtilityClass
public class SecurityUtils {
private static final String USER_REQUEST = "/api/mall/";
/**
* 获取用户
*/
public YamiUser getUser() {
if (!HttpContextUtils.getHttpServletRequest().getRequestURI().startsWith(USER_REQUEST)) {
// 用户相关的请求,应该以/p开头
throw new RuntimeException("yami.user.request.error");
}
String accessToken = HttpContextUtils.getHttpServletRequest().getHeader("accessToken");
TokenStore tokenStore = new TokenStore();
UserInfoInTokenBO userInfoInTokenBO = tokenStore.getUserInfoByAccessToken(accessToken,false);
YamiUser yamiUser = new YamiUser();
yamiUser.setUserId(userInfoInTokenBO.getUserId());
yamiUser.setBizUserId(userInfoInTokenBO.getBizUserId());
yamiUser.setEnabled(userInfoInTokenBO.getEnabled());
yamiUser.setShopId(userInfoInTokenBO.getShopId());
yamiUser.setStationId(userInfoInTokenBO.getOtherId());
return yamiUser;
}
/**
* 获取用户ID
*/
public Long getUserInfo() {
Long userId = null;
try {
userId = getUser().getUserId();
} catch (RuntimeException e) {
// 处理异常
System.out.println(e.getMessage());
}
return userId;
}
}

View File

@@ -0,0 +1,199 @@
package org.dromara.web.common;
import lombok.extern.slf4j.Slf4j;
import java.io.Serializable;
import java.util.Objects;
/**
* @author lanhai
*/
@Slf4j
public class ServerResponseEntity<T> implements Serializable {
/**
* 状态码
*/
private String code;
/**
* 信息
*/
private String msg;
/**
* 数据
*/
private T data;
/**
* 版本
*/
private String version;
/**
* 时间
*/
private Long timestamp;
/* private String sign;
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}*/
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public ServerResponseEntity setData(T data) {
this.data = data;
return this;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public Long getTimestamp() {
return timestamp;
}
public void setTimestamp(Long timestamp) {
this.timestamp = timestamp;
}
public boolean isSuccess() {
return Objects.equals(ResponseEnum.OK.value(), this.code);
}
public boolean isFail() {
return !Objects.equals(ResponseEnum.OK.value(), this.code);
}
public ServerResponseEntity() {
// 版本号
this.version = "1.0";
}
public static <T> ServerResponseEntity<T> success(T data) {
ServerResponseEntity<T> serverResponseEntity = new ServerResponseEntity<>();
serverResponseEntity.setData(data);
serverResponseEntity.setCode(ResponseEnum.OK.value());
serverResponseEntity.setTimestamp(System.currentTimeMillis());
serverResponseEntity.setMsg("success");
return serverResponseEntity;
}
public static <T> ServerResponseEntity<T> success() {
ServerResponseEntity<T> serverResponseEntity = new ServerResponseEntity<>();
serverResponseEntity.setCode(ResponseEnum.OK.value());
serverResponseEntity.setMsg(ResponseEnum.OK.getMsg());
serverResponseEntity.setMsg("success");
serverResponseEntity.setTimestamp(System.currentTimeMillis());
return serverResponseEntity;
}
public static <T> ServerResponseEntity<T> success(Integer code, T data) {
return success(String.valueOf(code), data);
}
public static <T> ServerResponseEntity<T> success(String code, T data) {
ServerResponseEntity<T> serverResponseEntity = new ServerResponseEntity<>();
serverResponseEntity.setCode(code);
serverResponseEntity.setData(data);
serverResponseEntity.setMsg("success");
serverResponseEntity.setTimestamp(System.currentTimeMillis());
return serverResponseEntity;
}
/**
* 前端显示失败消息
* @param msg 失败消息
* @return
*/
public static <T> ServerResponseEntity<T> showFailMsg(String msg) {
log.error(msg);
ServerResponseEntity<T> serverResponseEntity = new ServerResponseEntity<>();
serverResponseEntity.setMsg(msg);
serverResponseEntity.setCode(ResponseEnum.SHOW_FAIL.value());
serverResponseEntity.setTimestamp(System.currentTimeMillis());
return serverResponseEntity;
}
public static <T> ServerResponseEntity<T> fail(ResponseEnum responseEnum) {
log.error(responseEnum.toString());
ServerResponseEntity<T> serverResponseEntity = new ServerResponseEntity<>();
serverResponseEntity.setMsg(responseEnum.getMsg());
serverResponseEntity.setCode(responseEnum.value());
serverResponseEntity.setTimestamp(System.currentTimeMillis());
return serverResponseEntity;
}
public static <T> ServerResponseEntity<T> fail(ResponseEnum responseEnum, T data) {
log.error(responseEnum.toString());
ServerResponseEntity<T> serverResponseEntity = new ServerResponseEntity<>();
serverResponseEntity.setMsg(responseEnum.getMsg());
serverResponseEntity.setCode(responseEnum.value());
serverResponseEntity.setData(data);
serverResponseEntity.setTimestamp(System.currentTimeMillis());
return serverResponseEntity;
}
public static <T> ServerResponseEntity<T> fail(String code, String msg, T data) {
log.error(msg);
ServerResponseEntity<T> serverResponseEntity = new ServerResponseEntity<>();
serverResponseEntity.setMsg(msg);
serverResponseEntity.setCode(code);
serverResponseEntity.setData(data);
serverResponseEntity.setTimestamp(System.currentTimeMillis());
return serverResponseEntity;
}
public static <T> ServerResponseEntity<T> fail(String code, String msg) {
return fail(code, msg, null);
}
public static <T> ServerResponseEntity<T> fail(Integer code, T data) {
ServerResponseEntity<T> serverResponseEntity = new ServerResponseEntity<>();
serverResponseEntity.setCode(String.valueOf(code));
serverResponseEntity.setData(data);
serverResponseEntity.setTimestamp(System.currentTimeMillis());
return serverResponseEntity;
}
@Override
public String toString() {
return "ServerResponseEntity{" +
"code='" + code + '\'' +
", msg='" + msg + '\'' +
", data=" + data +
", version='" + version + '\'' +
", timestamp=" + timestamp +
// ", sign='" + sign + '\'' +
'}';
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
*
* https://www.mall4j.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package org.dromara.web.common;
import lombok.Data;
/**
* token信息该信息存在redis中
*
* @author 菠萝凤梨
* @date 2022/3/25 17:33
*/
@Data
public class TokenInfoBO {
/**
* 保存在token信息里面的用户信息
*/
private UserInfoInTokenBO userInfoInToken;
private String accessToken;
private String refreshToken;
/**
* 在多少秒后过期
*/
private Integer expiresIn;
}

View File

@@ -0,0 +1,23 @@
package org.dromara.web.common;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* token信息该信息用户返回给前端前端请求携带accessToken进行用户校验
*
* @author FrozenWatermelon
* @date 2020/7/2
*/
@Data
public class TokenInfoVO {
@Schema(description = "accessToken" )
private String accessToken;
@Schema(description = "refreshToken" )
private String refreshToken;
@Schema(description = "在多少秒后过期" )
private Integer expiresIn;
}

View File

@@ -0,0 +1,171 @@
package org.dromara.web.common;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.StrUtil;
import org.dromara.common.core.exception.user.UserException;
import org.dromara.common.redis.utils.RedisUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* token管理 1. 登陆返回token 2. 刷新token 3. 清除用户过去token 4. 校验token
*
* @author FrozenWatermelon
* @date 2020/7/2
*/
@Component
public class TokenStore {
private static final Logger logger = LoggerFactory.getLogger(TokenStore.class);
// private final RedisTemplate<String, Object> redisTemplate;
/*public TokenStore(RedisTemplate<String, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}*/
/**
* 以Sa-Token技术生成token并返回token信息
* @param userInfoInToken
* @return
*/
public TokenInfoBO storeAccessSaToken(UserInfoInTokenBO userInfoInToken) {
//生成过期时间
int timeoutSecond = getExpiresIn(userInfoInToken.getSysType());
Duration accessTokenExpires = Duration.ofSeconds(timeoutSecond);
String uid = this.getUid(userInfoInToken.getSysType().toString(), userInfoInToken.getUserId());
StpUtil.login(uid, timeoutSecond);
String token = StpUtil.getTokenValue();
// 用户信息存入缓存 token生成
String keyName = OauthCacheNames.USER_INFO + token;
RedisUtils.deleteObject(keyName);
RedisUtils.setCacheObject(keyName, userInfoInToken, accessTokenExpires);
// 数据封装返回(token不用加密)
TokenInfoBO tokenInfoBO = new TokenInfoBO();
tokenInfoBO.setUserInfoInToken(userInfoInToken);
tokenInfoBO.setExpiresIn(timeoutSecond);
tokenInfoBO.setAccessToken(token);
tokenInfoBO.setRefreshToken(token);
return tokenInfoBO;
}
/**
* 计算过期时间(单位:秒)
* @param sysType
* @return
*/
private int getExpiresIn(int sysType) {
// 3600秒
int expiresIn = 3600;
// 普通用户token过期时间
if (Objects.equals(sysType, 0)) {
expiresIn = expiresIn * 24 * 30;
}
// 系统管理员的token过期时间
if (Objects.equals(sysType, 1)) {
expiresIn = expiresIn * 24 * 30;
}
return expiresIn;
}
/**
* 根据accessToken 获取用户信息
* @param accessToken accessToken
* @param needDecrypt 是否需要解密
* @return 用户信息
*/
public UserInfoInTokenBO getUserInfoByAccessToken(String accessToken, boolean needDecrypt) {
if (StrUtil.isBlank(accessToken)) {
throw new UserException("accessToken is blank");
}
String keyName = OauthCacheNames.USER_INFO + accessToken;
Object redisCache = RedisUtils.getCacheObject(keyName);
if (redisCache == null) {
throw new UserException("-2","登录过期,请重新登录");
}
return (UserInfoInTokenBO) redisCache;
}
/**
* 刷新token并返回新的token
* @param refreshToken
* @return
*/
public TokenInfoBO refreshToken(String refreshToken) {
if (StrUtil.isBlank(refreshToken)) {
throw new UserException("refreshToken is blank");
}
// 删除旧token
UserInfoInTokenBO userInfoInTokenBO = getUserInfoByAccessToken(refreshToken, false);
this.deleteCurrentToken(refreshToken);
// 保存一份新的token
return storeAccessSaToken(userInfoInTokenBO);
}
/**
* 删除指定用户的全部的token
*/
public void deleteAllToken(String sysType, Long userId) {
// 删除用户缓存
String uid = this.getUid(sysType, userId);
List<String> tokens = StpUtil.getTokenValueListByLoginId(uid);
if (!CollectionUtils.isEmpty(tokens)) {
List<String> keyNames = new ArrayList<>();
for (String token : tokens) {
keyNames.add(OauthCacheNames.USER_INFO + token);
}
RedisUtils.deleteObject(keyNames);
}
// 移除token
StpUtil.logout(userId);
}
/**
* 生成token并返回token展示信息
* @param userInfoInToken
* @return
*/
public TokenInfoVO storeAndGetVo(UserInfoInTokenBO userInfoInToken) {
if (!userInfoInToken.getEnabled()){
// 用户已禁用,请联系客服
throw new UserException("用户已禁用,请联系客服");
}
TokenInfoBO tokenInfoBO = storeAccessSaToken(userInfoInToken);
// 数据封装返回
TokenInfoVO tokenInfoVO = new TokenInfoVO();
tokenInfoVO.setAccessToken(tokenInfoBO.getAccessToken());
tokenInfoVO.setRefreshToken(tokenInfoBO.getRefreshToken());
tokenInfoVO.setExpiresIn(tokenInfoBO.getExpiresIn());
return tokenInfoVO;
}
/**
* 删除当前登录的token
* @param accessToken 令牌
*/
public void deleteCurrentToken(String accessToken) {
// 删除用户缓存
String keyName = OauthCacheNames.USER_INFO + accessToken;
RedisUtils.deleteObject(keyName);
// 移除token
StpUtil.logoutByTokenValue(accessToken);
}
/**
* 生成各系统唯一uid
* @param sysType 系统类型
* @param userId 用户id
* @return
*/
private String getUid(String sysType, Long userId) {
return sysType + ":" + userId;
}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
*
* https://www.mall4j.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package org.dromara.web.common;
import lombok.Data;
import java.util.Set;
/**
* 保存在token信息里面的用户信息
*
* @author 菠萝凤梨
* @date 2022/3/25 17:33
*/
@Data
public class UserInfoInTokenBO {
/**
* 用户在自己系统的用户id
*/
private Long userId;
/**
* 租户id (商家id)
*/
private Long shopId;
/**
* 昵称
*/
private String nickName;
/**
* 系统类型 0:普通用户 1系统管理员
*
*/
private Integer sysType;
/**
* 是否是管理员
*/
private Integer isAdmin;
/**
* 业务系统用户id
*/
private String bizUserId;
/**
* 权限列表
*/
private Set<String> perms;
/**
* 状态 1 正常 0 无效
*/
private Boolean enabled;
/**
* 其他Id
*/
private Long otherId;
}

View File

@@ -0,0 +1,46 @@
package org.dromara.web.common;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
/**
* @author lh
*/
@Data
@Schema(description = "用户登录信息")
public class UserRegisterParam {
@Schema(description = "密码")
private String passWord;
@Schema(description = "邮箱")
private String userMail;
@Schema(description = "昵称")
private String nickName;
@Schema(description = "用户名")
private String userName;
@Schema(description = "手机号")
@NotBlank(message = "手机号码不能为空", groups = { AddGroup.class})
private String mobile;
@Schema(description = "头像")
private String img;
@Schema(description = "校验登陆注册验证码成功的标识")
private String checkRegisterSmsFlag;
@Schema(description = "当账户未绑定时临时的uid")
private String tempUid;
@Schema(description = "用户id")
private Long userId;
@Schema(description = "微信openId")
private String openId;
}

View File

@@ -0,0 +1,35 @@
package org.dromara.web.common;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
public class WxXcxUtils {
static String appid = "wxab288bfb906883b9";
static String secret = "072931a4a75ad265c7994c67d6020e61";
public static String getAccessToken(){
String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+appid+"&secret="+secret;
String result = HttpUtil.get(url);
JSONObject jsonObject = JSONObject.parseObject(result);
return jsonObject.get("access_token").toString();
}
public static JSONObject getUserPhoneNumber(String code){
String accessToken = getAccessToken();
String url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token="+accessToken;
JSONObject json = new JSONObject();
json.put("code", code);
String result = HttpRequest.post(url).body(json.toString()).execute().body();
JSONObject jsonObject = JSONObject.parseObject(result);
/*JSONObject phoneInfo = jsonObject.getJSONObject("phone_info");
System.out.println(phoneInfo+"==================================");
String phoneNumber = phoneInfo.get("phoneNumber").toString();*/
return jsonObject;
}
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
*
* https://www.mall4j.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package org.dromara.web.common;
import lombok.Data;
/**
* 用户详细信息
* @author LGH
*/
@Data
public class YamiUser {
/**
* 用户ID
*/
private Long userId;
private String bizUserId;
private Boolean enabled;
/**
* 自提点Id
*/
private Long stationId;
/**
* 店铺Id
*/
private Long shopId;
}

View File

@@ -0,0 +1,45 @@
package org.dromara.web.controller;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.core.utils.TxApiSdkUtils;
import org.dromara.web.common.ServerResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* 文本/图片安全验证
* @author Maosw
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/api/mall/appletAuth")
@Tag(name = "腾讯云接口")
public class ApiAppletAuthController {
@PostMapping("/checkContext")
@Operation(summary = "腾讯云文本内容安全识别" , description = "腾讯云文本内容安全识别")
public ServerResponseEntity<String> checkContext(@RequestParam String content) {
if (StringUtils.isEmpty(content)) {
return ServerResponseEntity.fail("-1", "内容不能为空");
}
return ServerResponseEntity.success(TxApiSdkUtils.checkContext(content));
}
@PostMapping("/checkImages")
@Operation(summary = "腾讯云图片内容安全识别" , description = "腾讯云图片内容安全识别")
public ServerResponseEntity<String> checkImages(@RequestParam String content) {
if (StringUtils.isEmpty(content)) {
return ServerResponseEntity.fail("-1", "内容不能为空");
}
return ServerResponseEntity.success(TxApiSdkUtils.checkImages(content));
}
}

View File

@@ -0,0 +1,240 @@
package org.dromara.web.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lakala.zf.laop.java.sdk.demo.BaseCommonDemo;
import com.lakala.zf.laop.java.sdk.demo.utils.KlkConstant;
import com.lakala.zf.laop.java.sdk.demo.utils.V3LakalaUserUtils;
import com.lkl.laop.sdk.LKLSDK;
import com.lkl.laop.sdk.request.V2LaepIndustryEwalletSettleProfileRequest;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.mall.domain.HyCodeOrder;
import org.dromara.mall.domain.HyOrder;
import org.dromara.mall.domain.TzBankCard;
import org.dromara.mall.domain.TzWithdrawRequest;
import org.dromara.mall.service.IHyCodeOrderService;
import org.dromara.mall.service.IHyOrderService;
import org.dromara.mall.service.ITzBankCardService;
import org.dromara.mall.service.ITzWithdrawRequestService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* @author Maosw
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/api/mall/callback")
@Tag(name = "回调接口")
public class ApiCallbackController extends BaseCommonDemo {
private final IHyOrderService hyOrderService;
private final ITzBankCardService bankCardService;
private final ITzWithdrawRequestService withdrawRequestService;
private final IHyCodeOrderService codeOrderService;
/*@PostMapping("/payOrder")
@Operation(summary = "订单支付回调" , description = "订单支付回调")
public ServerResponseEntity<Boolean> payOrder(Long orderId) {
hyOrderService.callbackOrder(orderId);
return ServerResponseEntity.success();
}*/
@RequestMapping("/applyBind")
@Operation(summary = "分账关系绑定申请回调" , description = "分账关系绑定申请回调")
public Map<String, String> applyBind(@RequestBody String requestBody) throws Exception {
System.out.println("分账关系绑定结果开始回调...");
// 1. 配置初始化
doInit();
//业务处理
JSONObject jsonObject = JSON.parseObject(requestBody);
String receiverNo = jsonObject.getString("receiverNo");
TzBankCard bankCard = bankCardService.queryByReceiverNo(receiverNo);
if ("1".equals(jsonObject.getString("auditStatus"))) {
// 绑定成功
bankCard.setStatus(1);
//提款模式设置
V2LaepIndustryEwalletSettleProfileRequest ewalletSettleProfileRequest = new V2LaepIndustryEwalletSettleProfileRequest();
ewalletSettleProfileRequest.setBmcpNo(KlkConstant.ORG_CODE);
ewalletSettleProfileRequest.setMercId(receiverNo);
ewalletSettleProfileRequest.setSettleType("02");
ewalletSettleProfileRequest.setPayType("04");
V3LakalaUserUtils.setWithdrawMode(ewalletSettleProfileRequest);
} else {
bankCard.setStatus(2);
bankCard.setRemark(jsonObject.getString("remark"));
}
if (!bankCardService.updateById(bankCard)) {
throw new RuntimeException("绑定银行卡回调更新数据失败");
}
return getKlkCommonResp();
}
/**
* 提现结果回调处理
*/
@RequestMapping("/withdrawal")
public Map<String, String> withdrawal(@RequestBody String requestBody) throws Exception {
System.out.println("提现结果开始回调...");
// 1. 配置初始化
doInit();
//业务处理
JSONObject respData = JSON.parseObject(requestBody);
String separateNo = respData.getString("separate_no");
String outSeparateNo = respData.getString("out_separate_no");
String finalStatus = respData.getString("final_status");
String cmdType = respData.getString("cmd_type");
if("SEPARATE".equals(cmdType)){
TzWithdrawRequest withdrawRequest = withdrawRequestService.queryWithdrawRequest(separateNo, outSeparateNo);
if (withdrawRequest != null) {
if("SUCCESS".equals(finalStatus)){
withdrawRequest.setWithdrawStatus(3);
withdrawRequestService.updateById(withdrawRequest);
return getKlkCommonResp();
}
}
}
return null;
}
/**
* 会员兑换码订单回调地址
*/
@RequestMapping("/codeOrder")
public Map<String, String> codeOrder(@RequestBody String requestBody) throws Exception {
System.out.println("会员兑换码订单开始回调...");
// 1. 配置初始化
doInit();
//业务处理
JSONObject respData = JSON.parseObject(requestBody);
String orderNo = respData.getString("out_order_no");
String payOrderNo = respData.getString("pay_order_no");
String orderStatus = respData.getString("order_status");
if ("2".equals(orderStatus)) {
HyCodeOrder codeOrder = codeOrderService.queryByOrderNo(orderNo, payOrderNo);
boolean result = codeOrderService.generateMemberCodes(codeOrder.getId());
if (result) {
return getKlkCommonResp();
}
}
return null;
}
/**
* 材料订单回调地址
*/
@RequestMapping("/order")
@RepeatSubmit(interval = 1, timeUnit = TimeUnit.SECONDS, message = "重复请求")
public Map<String, String> order(HttpServletRequest request) throws Exception {
System.out.println("材料订单回调开始回调...");
// 1. 配置初始化
doInit();
LKLSDK.notificationHandle(getBody(request), getAuthorization(request));
String body = getBody(request);
// 业务处理
JSONObject respData = JSON.parseObject(body);
String orderNo = respData.getString("out_order_no");
String payOrderNo = respData.getString("pay_order_no");
String orderStatus = respData.getString("order_status");
JSONObject jsonObject = respData.getJSONObject("order_trade_info");
String tradeNo = jsonObject.getString("trade_no");
String logNo = jsonObject.getString("log_no");
if ("2".equals(orderStatus)) {
HyOrder order = hyOrderService.queryByOrderNo(orderNo, payOrderNo);
if (order == null) {
throw new RuntimeException("订单不存在");
}
if (order.getPayState() == 3) {
throw new RuntimeException("订单已支付");
}
boolean result = hyOrderService.callbackOrder(order.getId(),tradeNo,logNo);
if (result) {
return getKlkCommonResp();
}
}
return null;
}
/**
* 读取请求头
*/
private String getAuthorization(HttpServletRequest request) {
return request.getHeader("Authorization");
}
/**
* 读取请求体
*/
private String getBody(HttpServletRequest request) {
try (InputStreamReader in = new InputStreamReader(request.getInputStream(), StandardCharsets.UTF_8)) {
StringBuilder bf = new StringBuilder();
int len;
char[] chs = new char[1024];
while ((len = in.read(chs)) != -1) {
bf.append(new String(chs, 0, len));
}
return bf.toString();
} catch (Exception e) {
throw new RuntimeException("读取body失败");
}
}
private Integer getWithdrawalStatus(String drawState) {
//提现状态1-处理中 2-已受理 3-成功 4-失败 5-冻结 -1-未关联卡拉卡平台
if ("DRAW.PROCESSING".equals(drawState)) {
return 1;
} else if ("DRAW.ACCEPTED".equals(drawState)) {
return 2;
} else if ("DRAW.SUCCESS".equals(drawState)) {
return 3;
} else if ("DRAW.FAILED".equals(drawState)) {
return 4;
} else if ("DRAW.FREEZE".equals(drawState)) {
return 5;
} else {
return -1;
}
}
/**
* 卡拉卡回调统一响应
* {
* "code":"SUCCESS",
* "message":"执行成功"
* }
*/
public Map<String, String> getKlkCommonResp() {
Map<String, String> map = new HashMap<>();
map.put("code", "SUCCESS");
map.put("message", "执行成功");
return map;
}
}

View File

@@ -0,0 +1,105 @@
package org.dromara.web.controller;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.validate.QueryGroup;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.mall.domain.TzUserSearch;
import org.dromara.mall.domain.bo.TzHotSearchBo;
import org.dromara.mall.domain.bo.TzIndexImgBo;
import org.dromara.mall.domain.bo.TzNoticeBo;
import org.dromara.mall.domain.bo.TzPictureAlbumBo;
import org.dromara.mall.domain.vo.*;
import org.dromara.mall.service.*;
import org.dromara.web.common.SecurityUtils;
import org.dromara.web.common.ServerResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* @author lanhai
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/api/mall/index")
@Tag(name = "首页接口")
public class ApiIndexController {
private final ITzIndexImgService tzIndexImgService;
private final ITzHotSearchService tzHotSearchService;
private final ITzUserSearchService tzUserSearchService;
private final ITzPictureAlbumService tzPictureAlbumService;
private final ITzNoticeService tzNoticeService;
@GetMapping("/indexImgs")
@Operation(summary = "首页轮播图" , description = "获取首页轮播图列表信息")
public ServerResponseEntity<List<TzIndexImgVo>> indexImgs() {
TzIndexImgBo tzIndexImgBo = new TzIndexImgBo();
tzIndexImgBo.setStatus(2);
List<TzIndexImgVo> indexImgList = tzIndexImgService.queryList(tzIndexImgBo);
return ServerResponseEntity.success(indexImgList);
}
@PostMapping("/searchByName")
@Operation(summary = "模糊查询搜索关键词" , description = "根据输入字段关联查询搜索关键词")
public ServerResponseEntity<IPage<TzHotSearchVo>> searchByName(@Validated(QueryGroup.class) @RequestBody TzHotSearchBo bo, @Valid @RequestBody PageQuery pageQuery) {
IPage<TzHotSearchVo> productPage = tzHotSearchService.pageSearchByName(bo,pageQuery);
return ServerResponseEntity.success(productPage);
}
@PostMapping("/searchList")
@Operation(summary = "猜你想搜" , description = "猜你想搜分页列表")
public ServerResponseEntity<JSON> searchList(@Valid @RequestBody PageQuery pageQuery) {
Long userId = SecurityUtils.getUserInfo();
if(ObjectUtil.isNotEmpty(userId)){
long count = tzUserSearchService.count(new LambdaQueryWrapper<TzUserSearch>().eq(TzUserSearch::getUserId,userId));
if(count >= 6){
IPage<TzUserSearchVo> searchVoIPage = tzUserSearchService.querySearchList(pageQuery,userId);
return ServerResponseEntity.success(JSON.parseObject(JSON.toJSONString(searchVoIPage)));
}
}
IPage<TzHotSearchVo> productPage = tzHotSearchService.searchList(pageQuery);
return ServerResponseEntity.success(JSON.parseObject(JSON.toJSONString(productPage)));
}
@PostMapping("/pictureAlbumList")
@Operation(summary = "分页查询画册列表" , description = "分页查询画册列表")
public ServerResponseEntity<IPage<TzPictureAlbumVo>> pictureAlbumList(@Validated(QueryGroup.class) @RequestBody TzPictureAlbumBo bo, @Valid @RequestBody PageQuery pageQuery) {
IPage<TzPictureAlbumVo> pictureAlbumList = tzPictureAlbumService.pictureAlbumList(bo,pageQuery);
return ServerResponseEntity.success(pictureAlbumList);
}
/**
* 分页查询公告列表
*/
@PostMapping("/noticeList")
@Operation(summary = "分页查询公告列表" , description = "分页查询公告列表")
public ServerResponseEntity<IPage<TzNoticeVo>> noticeList(@RequestBody TzNoticeBo bo, @Valid @RequestBody PageQuery pageQuery) {
bo.setStatus(1);
bo.setDelFlag(1);
IPage<TzNoticeVo> noticeList = tzNoticeService.queryPageListAPP(bo,pageQuery);
return ServerResponseEntity.success(noticeList);
}
@PostMapping("/noticeDetail/{id}")
@Operation(summary = "公告详情" , description = "公告详情")
public ServerResponseEntity<TzNoticeVo> noticeDetail(@PathVariable Long id) {
TzNoticeVo noticeDetail = tzNoticeService.queryById(id);
return ServerResponseEntity.success(noticeDetail);
}
}

View File

@@ -0,0 +1,136 @@
package org.dromara.web.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.mall.domain.bo.TzInvoiceApplyBo;
import org.dromara.mall.domain.bo.TzInvoiceTitleBo;
import org.dromara.mall.domain.vo.TzInvoiceApplyVo;
import org.dromara.mall.domain.vo.TzInvoiceTitleVo;
import org.dromara.mall.service.ITzInvoiceApplyService;
import org.dromara.mall.service.ITzInvoiceTitleService;
import org.dromara.web.common.SecurityUtils;
import org.dromara.web.common.ServerResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.Collections;
/**
* 发票接口
* @author Maosw
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/api/mall/invoice")
@Tag(name = "发票接口")
public class ApiInvoiceController {
private final ITzInvoiceApplyService invoiceApplyService;
private final ITzInvoiceTitleService invoiceTitleService;
@Operation(summary = "分页查询发票抬头列表")
@PostMapping("/title/list")
public ServerResponseEntity<IPage<TzInvoiceTitleVo>> list(@Valid @RequestBody PageQuery pageQuery) {
Long userId = SecurityUtils.getUser().getUserId();
TzInvoiceTitleBo bo = new TzInvoiceTitleBo();
bo.setUserId(userId);
bo.setDelFlag(1);
return ServerResponseEntity.success(invoiceTitleService.queryPageListAPP(bo, pageQuery));
}
@Operation(summary = "新增发票抬头")
@PostMapping("/title/add")
public ServerResponseEntity<Boolean> add(@Valid @RequestBody TzInvoiceTitleBo bo) {
Long userId = SecurityUtils.getUser().getUserId();
bo.setUserId(userId);
return ServerResponseEntity.success(invoiceTitleService.insertByBo(bo));
}
@Operation(summary = "修改发票抬头")
@PostMapping("/title/update")
public ServerResponseEntity<Boolean> update(@Valid @RequestBody TzInvoiceTitleBo bo) {
Long userId = SecurityUtils.getUser().getUserId();
bo.setUserId(userId);
// 校验是否是自己的发票抬头
TzInvoiceTitleVo titleVo = invoiceTitleService.queryById(bo.getId());
if (titleVo == null || !userId.equals(titleVo.getUserId())) {
return ServerResponseEntity.fail("-1","发票抬头不存在");
}
return ServerResponseEntity.success(invoiceTitleService.updateByBo(bo));
}
@Operation(summary = "删除发票抬头")
@DeleteMapping("/title/delete/{id}")
public ServerResponseEntity<Boolean> delete(@PathVariable Long id) {
Long userId = SecurityUtils.getUser().getUserId();
// 校验是否是自己的发票抬头
TzInvoiceTitleVo titleVo = invoiceTitleService.queryById(id);
if (titleVo == null || !userId.equals(titleVo.getUserId())) {
return ServerResponseEntity.fail("-1","发票抬头不存在");
}
return ServerResponseEntity.success(invoiceTitleService.deleteWithValidByIds(Collections.singleton(id), true));
}
@Operation(summary = "分页查询发票记录列表")
@PostMapping("/apply/list")
public ServerResponseEntity<IPage<TzInvoiceApplyVo>> applyList(@Valid @RequestBody PageQuery pageQuery) {
Long userId = SecurityUtils.getUser().getUserId();
TzInvoiceApplyBo bo = new TzInvoiceApplyBo();
bo.setUserId(userId);
bo.setDelFlag(1);
return ServerResponseEntity.success(invoiceApplyService.queryPageListAPP(bo, pageQuery));
}
@Operation(summary = "查询发票申请详情")
@PostMapping("/apply/detail/{id}")
public ServerResponseEntity<TzInvoiceApplyVo> applyDetail(@PathVariable Long id) {
SecurityUtils.getUser();
TzInvoiceApplyVo applyDetail = invoiceApplyService.queryById(id);
return ServerResponseEntity.success(applyDetail);
}
@Operation(summary = "新增发票申请")
@PostMapping("/apply/add")
public ServerResponseEntity<Boolean> applyAdd(@Valid @RequestBody TzInvoiceApplyBo bo) {
Long userId = SecurityUtils.getUser().getUserId();
bo.setUserId(userId);
return ServerResponseEntity.success(invoiceApplyService.insertByBo(bo));
}
@Operation(summary = "取消发票申请")
@PostMapping("/apply/cancel/{id}")
public ServerResponseEntity<Boolean> applyCancel(@PathVariable Long id) {
Long userId = SecurityUtils.getUser().getUserId();
// 校验是否是自己的发票申请
TzInvoiceApplyVo applyVo = invoiceApplyService.queryById(id);
if (applyVo == null || !userId.equals(applyVo.getUserId())) {
return ServerResponseEntity.fail("-1", "发票申请不存在");
}
// 只有待开票状态可以取消
if (applyVo.getStatus() != 1) {
return ServerResponseEntity.fail("-1", "当前状态不可取消");
}
return ServerResponseEntity.success(invoiceApplyService.cancelApply(id));
}
/**
* 根据订单ID查询发票申请详情
*/
@Operation(summary = "根据订单ID查询发票申请详情")
@PostMapping("/apply/detailByOrderId/{orderId}")
public ServerResponseEntity<TzInvoiceApplyVo> applyDetailByOrderId(@PathVariable Long orderId) {
Long userId = SecurityUtils.getUser().getUserId();
TzInvoiceApplyVo applyDetail = invoiceApplyService.queryByOrderId(orderId, userId);
return ServerResponseEntity.success(applyDetail);
}
}

View File

@@ -0,0 +1,137 @@
package org.dromara.web.controller;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.lakala.zf.laop.java.sdk.demo.bo.AddOrUpdateBankCardReq;
import com.lakala.zf.laop.java.sdk.demo.bo.AgreementReq;
import com.lakala.zf.laop.java.sdk.demo.utils.V3LakalaUserUtils;
import com.lkl.laop.sdk.request.V2MmsApplyLedgerReceiverRequest;
import com.lkl.laop.sdk.request.V2MmsOpenApiUploadFile;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.mall.domain.TzAgreement;
import org.dromara.mall.service.ITzAgreementService;
import org.dromara.mall.service.ITzBankCardService;
import org.dromara.web.common.SecurityUtils;
import org.dromara.web.common.ServerResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.time.ZoneId;
/**
* 拉卡拉接口
* @author Maosw
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/api/mall/Lakala")
@Tag(name = "拉卡拉接口")
public class ApiLakalaController {
private final ITzAgreementService agreementService;
private final ITzBankCardService bankCardService;
/**
* 查询开户行名称
*/
@PostMapping("/getBankName")
@Operation(summary = "查询开户行名称" , description = "查询开户行名称")
public ServerResponseEntity<JSONObject> getBankName(@RequestParam String cardNo) {
JSONObject jsonObject;
try {
jsonObject = V3LakalaUserUtils.cardBin(cardNo);
} catch (Exception e) {
throw new ServiceException("拉卡拉查询开户行名称接口异常");
}
return ServerResponseEntity.success(jsonObject);
}
/**
* 添加或修改银行卡信息
*/
@PostMapping("/addOrUpdateBankCard")
@Operation(summary = "添加或修改银行卡信息" , description = "添加或修改银行卡信息")
public ServerResponseEntity<Boolean> addOrUpdateBankCard(@RequestBody AddOrUpdateBankCardReq req) {
Long userId = SecurityUtils.getUser().getUserId();
return ServerResponseEntity.success(bankCardService.addOrUpdateBankCard(req, userId));
}
/**
* 文件上传
*/
@PostMapping("/uploadFile")
@Operation(summary = "文件上传" , description = "文件上传")
public ServerResponseEntity<JSONObject> uploadFile(@RequestBody V2MmsOpenApiUploadFile uploadFile) {
JSONObject jsonObject;
try {
jsonObject = V3LakalaUserUtils.uploadFile(uploadFile);
} catch (Exception e) {
throw new ServiceException("拉卡拉文件上传接口异常");
}
return ServerResponseEntity.success(jsonObject);
}
/**
* 分账接收方创建申请
*/
@PostMapping("/applyLedgerReceiver")
@Operation(summary = "分账接收方创建申请" , description = "分账接收方创建申请")
public ServerResponseEntity<JSONObject> applyLedgerReceiver(@RequestBody V2MmsApplyLedgerReceiverRequest ledgerReceiver) {
JSONObject jsonObject;
try {
jsonObject = V3LakalaUserUtils.applyLedgerReceiver(ledgerReceiver);
} catch (Exception e) {
throw new ServiceException("拉卡拉分账接收方创建申请接口异常");
}
return ServerResponseEntity.success(jsonObject);
}
/**
* 获取分账协议
*/
@PostMapping("/agreement")
@Operation(summary = "获取分账协议", description = "获取分账协议")
public ServerResponseEntity<String> agreement(@RequestBody AgreementReq req) {
TzAgreement agreement = agreementService.selectOne(new QueryWrapper<TzAgreement>().lambda().eq(TzAgreement::getCode, req.getCode()));
if (agreement == null || agreement.getContent() == null) {
return ServerResponseEntity.fail("-1", "协议不存在");
}
String code = req.getCode();
if ("fzxy".equals(code) || "sale_fzxy".equals(code)) {
try {
String agreementStr = processAgreementContent(agreement.getContent(), req);
return ServerResponseEntity.success(agreementStr);
} catch (Exception e) {
throw new ServiceException("协议处理失败: " + e.getMessage());
}
} else {
return ServerResponseEntity.fail("-1", "code不存在");
}
}
private String processAgreementContent(String content, AgreementReq req) {
int year = 5;
content = content.replace("${store.name}", StringUtils.defaultString(req.getAcctName()));
content = content.replace("${store.idno}", StringUtils.defaultString(req.getAcctCertificateNo()));
content = content.replace("${year}", Integer.toString(year));
LocalDateTime now = LocalDateTime.now(ZoneId.systemDefault());
content = content.replace("${beginYear}", now.getYear() + "");
content = content.replace("${beginMonth}", (now.getMonthValue()) + "");
content = content.replace("${beginDay}", now.getDayOfMonth() + "");
LocalDateTime endDate = now.plusYears(year);
content = content.replace("${endYear}", endDate.getYear() + "");
content = content.replace("${endMonth}", endDate.getMonthValue() + "");
content = content.replace("${endDay}", endDate.getDayOfMonth() + "");
return content;
}
}

View File

@@ -0,0 +1,112 @@
package org.dromara.web.controller;
import cn.dev33.satoken.secure.BCrypt;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.mall.domain.TzUser;
import org.dromara.mall.domain.vo.TzUserVo;
import org.dromara.mall.service.ITzUserService;
import org.dromara.web.common.*;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
/**
* @author Maosw
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/api/mall/user/login")
@Tag(name = "登录接口")
public class ApiLoginController {
private final ITzUserService tzUserService;
private final TokenStore tokenStore;
@PostMapping("/getUserPhoneNumber")
@Operation(summary = "微信接口获取手机号码" , description = "微信接口获取手机号码")
@Parameter(name = "code", description = "code", required = true)
public ServerResponseEntity<JSONObject> getUserPhoneNumber(@RequestParam(value = "code") String code) {
// String phone = WxXcxUtils.getUserPhoneNumber(code);
return ServerResponseEntity.success(WxXcxUtils.getUserPhoneNumber(code));
}
@PostMapping("/register")
@Operation(summary = "注册登录" , description = "用户绑定手机号注册登录")
public ServerResponseEntity<TokenInfoVO> register(@Valid @RequestBody UserRegisterParam userRegisterParam) {
if (StrUtil.isBlank(userRegisterParam.getNickName())) {
userRegisterParam.setNickName(userRegisterParam.getUserName());
}
TzUser tzUser = tzUserService.getOne(new LambdaQueryWrapper<TzUser>().eq(TzUser::getUserMobile, userRegisterParam.getMobile()));
if (ObjectUtil.isNotEmpty(tzUser)) {
//登录
UserInfoInTokenBO userInfoInTokenBO = new UserInfoInTokenBO();
userInfoInTokenBO.setUserId(tzUser.getUserId());
userInfoInTokenBO.setSysType(0);
userInfoInTokenBO.setEnabled(true);
return ServerResponseEntity.success(tokenStore.storeAndGetVo(userInfoInTokenBO));
}else {
//注册并登录
Date now = new Date();
TzUser user = new TzUser();
user.setModifyTime(now);
user.setUserRegtime(now);
user.setStatus(1);
user.setUserMobile(userRegisterParam.getMobile());
user.setNickName(userRegisterParam.getNickName());
user.setUserMail(userRegisterParam.getUserMail());
user.setPic(userRegisterParam.getImg());
user.setLoginPassword(BCrypt.hashpw(userRegisterParam.getPassWord()));
user.setOpenId(userRegisterParam.getOpenId());
tzUserService.save(user);
// 2. 登录
UserInfoInTokenBO userInfoInTokenBO = new UserInfoInTokenBO();
userInfoInTokenBO.setUserId(user.getUserId());
userInfoInTokenBO.setSysType(0);
userInfoInTokenBO.setEnabled(true);
return ServerResponseEntity.success(tokenStore.storeAndGetVo(userInfoInTokenBO));
}
}
@PutMapping("/updatePwd")
@Operation(summary = "修改密码" , description = "修改密码")
public ServerResponseEntity<Boolean> updatePwd(@Valid @RequestBody UserRegisterParam userPwdUpdateParam) {
Long userId = SecurityUtils.getUser().getUserId();
TzUserVo user = tzUserService.queryById(userId);
if (user == null) {
// 无法获取用户信息
throw new ServiceException("无法获取用户信息");
}
if (StrUtil.isBlank(userPwdUpdateParam.getPassWord())) {
// 新密码不能为空
throw new ServiceException("新密码不能为空");
}
String password = BCrypt.hashpw(userPwdUpdateParam.getPassWord());
if (StrUtil.equals(password, user.getLoginPassword())) {
// 新密码不能与原密码相同
throw new ServiceException("新密码不能与原密码相同");
}
user.setModifyTime(new Date());
user.setLoginPassword(password);
TzUser tzUser = MapstructUtils.convert(user, TzUser.class);
return ServerResponseEntity.success(tzUserService.updateById(tzUser));
}
}

View File

@@ -0,0 +1,147 @@
package org.dromara.web.controller;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.mall.domain.bo.HyCodeOrderBo;
import org.dromara.mall.domain.bo.HyCouponRecordBo;
import org.dromara.mall.domain.bo.HyMemberCodeBo;
import org.dromara.mall.domain.bo.HyUserRecordBo;
import org.dromara.mall.domain.vo.HyCodeOrderVo;
import org.dromara.mall.domain.vo.HyCouponRecordVo;
import org.dromara.mall.domain.vo.HyMemberCodeVo;
import org.dromara.mall.domain.vo.HyUserRecordVo;
import org.dromara.mall.service.IHyCodeOrderService;
import org.dromara.mall.service.IHyCouponRecordService;
import org.dromara.mall.service.IHyMemberCodeService;
import org.dromara.mall.service.IHyUserRecordService;
import org.dromara.web.common.SecurityUtils;
import org.dromara.web.common.ServerResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import java.util.List;
/**
* @author Maosw
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/api/mall/member")
@Tag(name = "会员接口")
public class ApiMemberController {
private final IHyMemberCodeService memberCodeService;
private final IHyCodeOrderService codeOrderService;
private final IHyUserRecordService userRecordService;
private final IHyCouponRecordService couponRecordService;
@Operation(summary = "获取会员价格", description = "获取会员价格")
@GetMapping("/price/{id}")
public ServerResponseEntity<BigDecimal> getMemberPrice(@PathVariable Integer id) {
if (id == null) {
return ServerResponseEntity.fail("-1", "类型不能为空");
}
SecurityUtils.getUser();
return ServerResponseEntity.success(memberCodeService.getMemberPrice(id));
}
@Operation(summary = "购买兑换码", description = "用户购买会员码生成订单")
@RepeatSubmit()
@PostMapping("/buyCode")
public ServerResponseEntity<JSONObject> buyMemberCode(@Validated @RequestBody HyCodeOrderBo bo) throws Exception {
Long userId = SecurityUtils.getUser().getUserId();
bo.setUserId(userId);
return ServerResponseEntity.success(codeOrderService.createOrder(bo));
}
@Operation(summary = "获取会员兑换码订单列表", description = "分页获取当前用户的会员兑换码订单列表")
@GetMapping("/orderList")
public ServerResponseEntity<IPage<HyCodeOrderVo>> getOrderList(@Valid PageQuery pageQuery) {
Long userId = SecurityUtils.getUser().getUserId();
HyCodeOrderBo bo = new HyCodeOrderBo();
bo.setUserId(userId);
bo.setDelFlag(1);
return ServerResponseEntity.success(codeOrderService.queryPageListAPP(bo, pageQuery));
}
@Operation(summary = "删除会员兑换码订单", description = "根据订单ID批量逻辑删除未付款的会员兑换码订单")
@RepeatSubmit()
@PostMapping("/deleteOrder")
public ServerResponseEntity<String> deleteOrder(@RequestBody List<Long> orderIds) {
if (orderIds == null || orderIds.isEmpty()) {
return ServerResponseEntity.fail("-1", "请选择要删除的订单");
}
Long userId = SecurityUtils.getUser().getUserId();
boolean result = codeOrderService.logicDeleteByIds(orderIds, userId, 4);
return result ? ServerResponseEntity.success("删除成功") : ServerResponseEntity.fail("-1", "删除失败");
}
@Operation(summary = "根据订单ID生成会员兑换码测试专用", description = "根据订单ID生成会员兑换码测试专用")
@GetMapping("/order/{orderId}")
public ServerResponseEntity<String> generateMemberCodes(@PathVariable Long orderId) {
if (orderId == null) {
return ServerResponseEntity.fail("-1", "订单ID不能为空");
}
boolean result = codeOrderService.generateMemberCodes(orderId);
return result ? ServerResponseEntity.success("生成会员兑换码成功") : ServerResponseEntity.fail("-1", "生成会员兑换码失败");
}
@Operation(summary = "获取会员兑换码列表", description = "分页获取当前用户的会员兑换码列表")
@GetMapping("/codeList")
public ServerResponseEntity<IPage<HyMemberCodeVo>> getMemberCodeList(@Valid PageQuery pageQuery) {
Long userId = SecurityUtils.getUser().getUserId();
HyMemberCodeBo bo = new HyMemberCodeBo();
bo.setUserId(userId);
bo.setDelFlag(1);
return ServerResponseEntity.success(memberCodeService.queryPageListAPP(bo, pageQuery));
}
@Operation(summary = "查询会员兑换码详情", description = "根据会员兑换码ID查询会员兑换码详情")
@GetMapping("/codeDetail/{codeId}")
public ServerResponseEntity<HyMemberCodeVo> getMemberCodeDetail(@PathVariable Long codeId) {
return ServerResponseEntity.success(memberCodeService.queryById(codeId));
}
@Operation(summary = "兑换会员码", description = "使用会员兑换码兑换会员资格")
@RepeatSubmit()
@PostMapping("/redeemCode")
public ServerResponseEntity<String> redeemMemberCode(@RequestParam String code) {
if (StringUtils.isEmpty(code)) {
return ServerResponseEntity.fail("-1", "兑换码不能为空");
}
Long userId = SecurityUtils.getUser().getUserId();
boolean result = memberCodeService.redeemCode(code, userId);
return result ? ServerResponseEntity.success("兑换成功") : ServerResponseEntity.fail("-1", "兑换失败");
}
@Operation(summary = "分页获取用户资金记录列表", description = "分页获取当前用户的资金记录列表")
@PostMapping("/recordList")
public ServerResponseEntity<IPage<HyUserRecordVo>> getRecordList(@Valid @RequestBody HyUserRecordBo bo ,@Valid PageQuery pageQuery) {
Long userId = SecurityUtils.getUser().getUserId();
bo.setUserId(userId);
bo.setDelFlag(1);
return ServerResponseEntity.success(userRecordService.queryPageListAPP(bo, pageQuery));
}
@Operation(summary = "分页获取抵用金记录", description = "分页获取当前用户的抵用金记录")
@PostMapping("/couponRecordList")
public ServerResponseEntity<IPage<HyCouponRecordVo>> getCouponRecordList(@Valid @RequestBody HyCouponRecordBo bo,@Valid PageQuery pageQuery) {
Long userId = SecurityUtils.getUser().getUserId();
bo.setUserId(userId);
bo.setDelFlag(1);
return ServerResponseEntity.success(couponRecordService.queryPageListAPP(bo, pageQuery));
}
}

View File

@@ -0,0 +1,295 @@
package org.dromara.web.controller;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.lakala.zf.laop.java.sdk.demo.utils.KlkConstant;
import com.lakala.zf.laop.java.sdk.demo.utils.LakalaUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.mall.domain.HyOrder;
import org.dromara.mall.domain.bo.BasketBo;
import org.dromara.mall.domain.bo.HyBasketBo;
import org.dromara.mall.domain.bo.HyOrderBo;
import org.dromara.mall.domain.bo.HyOrderItemBo;
import org.dromara.mall.domain.vo.HyBasketVo;
import org.dromara.mall.domain.vo.HyOrderItemVo;
import org.dromara.mall.domain.vo.HyOrderVo;
import org.dromara.mall.service.IHyBasketService;
import org.dromara.mall.service.IHyOrderItemService;
import org.dromara.mall.service.IHyOrderService;
import org.dromara.web.common.SecurityUtils;
import org.dromara.web.common.ServerResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;
/**
* @author Maosw
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/api/mall/hyOrder")
@Tag(name = "订单接口")
public class ApiOrderController {
private final IHyOrderService hyOrderService;
private final IHyBasketService hyBasketService;
private final IHyOrderItemService hyOrderItemService;
@Operation(summary = "添加商品到购物车", description = "添加商品到购物车")
@RepeatSubmit()
@PostMapping("/addToBasket")
public ServerResponseEntity<Boolean> addToBasket(@Validated @RequestBody HyBasketBo bo) {
Long userId = SecurityUtils.getUser().getUserId();
bo.setUserId(userId);
return ServerResponseEntity.success(hyBasketService.insertByBo(bo));
}
@Operation(summary = "根据购物车ID修改购物车信息", description = "根据购物车ID修改购物车信息")
@RepeatSubmit(interval = 1, timeUnit = TimeUnit.SECONDS, message = "操作过于频繁")
@PostMapping("/editBasket")
public ServerResponseEntity<Boolean> editBasket(@Validated @RequestBody HyBasketBo bo) {
Long userId = SecurityUtils.getUser().getUserId();
bo.setUserId(userId);
return ServerResponseEntity.success(hyBasketService.updateByBo(bo));
}
@Operation(summary = "删除购物车商品", description = "根据购物车ID批量逻辑删除购物车商品")
@RepeatSubmit()
@PostMapping("/deleteBasket")
public ServerResponseEntity<String> deleteBasket(@RequestBody List<Long> basketIds) {
if (basketIds == null || basketIds.isEmpty()) {
return ServerResponseEntity.fail("-1", "请选择要删除的商品");
}
Long userId = SecurityUtils.getUser().getUserId();
boolean result = hyBasketService.logicDeleteByIds(basketIds, userId);
return result ? ServerResponseEntity.success("删除成功") : ServerResponseEntity.fail("-1", "删除失败");
}
@Operation(summary = "查询购物车列表", description = "获取当前用户的购物车商品列表")
@PostMapping("/basketList")
public ServerResponseEntity<IPage<HyBasketVo>> basketList(@Valid @RequestBody PageQuery pageQuery) {
Long userId = SecurityUtils.getUser().getUserId();
HyBasketBo bo = new HyBasketBo();
bo.setUserId(userId);
bo.setDelFlag(1);
return ServerResponseEntity.success(hyBasketService.queryPageListApp(bo, pageQuery));
}
@Operation(summary = "查询购物车商品数量", description = "获取当前用户的购物车商品数量")
@GetMapping("/basketCount")
public ServerResponseEntity<Long> basketCount() {
Long userId = SecurityUtils.getUser().getUserId();
return ServerResponseEntity.success(hyBasketService.countByUserId(userId));
}
@Operation(summary = "用户查询订单列表", description = "根据订单状态查询用户订单列表")
@PostMapping("/orderList")
public ServerResponseEntity<IPage<HyOrderVo>> orderList(@Valid PageQuery pageQuery, @RequestBody HyOrderBo bo) {
Long userId = SecurityUtils.getUser().getUserId();
bo.setUserId(userId);
bo.setDelFlag(1);
return ServerResponseEntity.success(hyOrderService.queryPageListApp(bo, pageQuery));
}
@Operation(summary = "用户子查询订单列表", description = "根据子订单状态查询用户订单列表")
@PostMapping("/orderItemList")
public ServerResponseEntity<IPage<HyOrderItemVo>> orderItemList(@Valid PageQuery pageQuery, @RequestBody HyOrderItemBo bo) {
Long userId = SecurityUtils.getUser().getUserId();
bo.setUserId(userId);
bo.setDelFlag(1);
return ServerResponseEntity.success(hyOrderItemService.queryPageListApp(bo, pageQuery));
}
@Operation(summary = "删除订单", description = "根据订单ID逻辑删除订单")
@RepeatSubmit()
@PostMapping("/deleteOrder")
public ServerResponseEntity<String> deleteOrder(@RequestBody List<Long> orderIds) {
if (orderIds == null || orderIds.isEmpty()) {
return ServerResponseEntity.fail("-1", "请选择要删除的订单");
}
Long userId = SecurityUtils.getUser().getUserId();
boolean result = hyOrderItemService.logicDeleteByIds(orderIds, userId);
return result ? ServerResponseEntity.success("删除成功") : ServerResponseEntity.fail("-1", "删除失败");
}
@Operation(summary = "查询订单详情", description = "根据订单ID查询订单详情")
@GetMapping("/orderDetail/{orderId}")
public ServerResponseEntity<HyOrderItemVo> orderDetail(@PathVariable Long orderId) {
Long userId = SecurityUtils.getUser().getUserId();
HyOrderItemVo orderDetail = hyOrderItemService.queryOrderDetail(orderId, userId);
return ServerResponseEntity.success(orderDetail);
}
@Operation(summary = "订单调价", description = "订单调价")
@RepeatSubmit()
@PostMapping("/editOrder")
public ServerResponseEntity<Boolean> editOrder(@Validated @RequestBody HyOrderItemBo bo) {
Long userId = SecurityUtils.getUser().getUserId();
bo.setUserId(userId);
return ServerResponseEntity.success(hyOrderItemService.editOrder(bo));
}
@Operation(summary = "提交订单(立即购买)", description = "提交订单(立即购买)")
@RepeatSubmit()
@PostMapping("/submitOrder")
public ServerResponseEntity<Long> submitOrder(@Validated @RequestBody HyOrderItemBo bo) throws Exception {
Long userId = SecurityUtils.getUser().getUserId();
bo.setUserId(userId);
Long orderId = hyOrderItemService.insertByBo(bo);
return ServerResponseEntity.success(orderId);
}
@Operation(summary = "提交订单(购物车)", description = "从购物车提交订单")
@RepeatSubmit()
@PostMapping("/submitBasketOrder")
public ServerResponseEntity<Long> submitBasketOrder(@Validated @RequestBody BasketBo basketBo) throws Exception {
if (basketBo.getBasketBoList() == null || basketBo.getBasketBoList().isEmpty()) {
return ServerResponseEntity.fail("-1", "请选择要购买的商品");
}
Long userId = SecurityUtils.getUser().getUserId();
Long orderId = hyOrderItemService.insertByBasketIds(basketBo, userId);
return ServerResponseEntity.success(orderId);
}
@Operation(summary = "根据订单ID发起支付", description = "根据订单ID发起支付")
@GetMapping("/orderPay/{orderId}")
public ServerResponseEntity<JSONObject> orderPay(@PathVariable Long orderId) throws Exception {
SecurityUtils.getUser();
HyOrderVo orderVo = hyOrderService.queryById(orderId);
String orderNo = "Z"+genItemId();
List<HyOrderItemVo> orderItemVoList = hyOrderItemService.queryOrderItemsByOrderId(orderVo.getId(),orderVo.getUserId());
/*List<V3CcssOrderOutSplitInfo> splitInfoList = new ArrayList<>();
for (HyOrderItemVo hyOrderItemVo : orderItemVoList) {
V3CcssOrderOutSplitInfo splitInfo = new V3CcssOrderOutSplitInfo();
splitInfo.setOutSubOrderNo(hyOrderItemVo.getOrderNum());
splitInfo.setMerchantNo(KlkConstant.merchantNo);
splitInfo.setTermNo(KlkConstant.TERM_NO);
splitInfo.setAmount(String.valueOf(hyOrderItemVo.getPayPrice().multiply(new BigDecimal(100)).longValue()));
splitInfoList.add(splitInfo);
}*/
JSONObject jsonObject = LakalaUtils.createOrderPay(orderNo, orderVo.getPayPrice(), KlkConstant.MEMBER_ORDER);
if ("000000".equals(jsonObject.get("code"))) {
System.out.println(jsonObject.get("resp_data").toString());
JSONObject respData = jsonObject.getJSONObject("resp_data");
String payOrderNo = respData.getString("pay_order_no");
HyOrder hyOrder = new HyOrder();
hyOrder.setId(orderVo.getId());
hyOrder.setOrderNum(orderNo);
hyOrder.setPayOrderNo(payOrderNo);
if (!hyOrderService.updateById(hyOrder)){
throw new ServiceException("更新订单失败");
}
} else {
System.out.println(jsonObject.get("msg").toString());
}
return ServerResponseEntity.success(jsonObject);
}
@Operation(summary = "修改订单地址", description = "根据订单ID修改用户收货地址")
@PostMapping("/editOrderAddr")
public ServerResponseEntity<String> editOrderAddr(@RequestBody HyOrderBo bo) {
Long userId = SecurityUtils.getUser().getUserId();
boolean result = hyOrderService.editOrderAddr(bo);
return result ? ServerResponseEntity.success("修改成功") : ServerResponseEntity.fail("-1","修改失败");
}
@Operation(summary = "查询订单清单列表", description = "根据总订单ID查询子订单清单列表")
@GetMapping("/orderItems/{orderId}")
public ServerResponseEntity<List<HyOrderItemVo>> getOrderItemsByOrderId(@PathVariable Long orderId) {
Long userId = SecurityUtils.getUser().getUserId();
List<HyOrderItemVo> orderItems = hyOrderItemService.queryOrderItemsByOrderId(orderId, userId);
return ServerResponseEntity.success(orderItems);
}
@Operation(summary = "确认收货", description = "根据总订单ID确认收货")
@GetMapping("/confirmOrder/{orderId}")
public ServerResponseEntity<String> confirmOrder(@PathVariable Long orderId) {
SecurityUtils.getUser();
boolean result = hyOrderItemService.confirmOrderById(orderId);
return result ? ServerResponseEntity.success("确认收货成功") : ServerResponseEntity.fail("-1","确认收货失败");
}
@Operation(summary = "查询订单清单列表(分享)", description = "根据总订单ID查询子订单清单列表")
@GetMapping("/getOrderByOrderId/{orderId}")
public ServerResponseEntity<List<HyOrderItemVo>> getOrderByOrderId(@PathVariable Long orderId) {
List<HyOrderItemVo> orderItems = hyOrderItemService.queryOrderItemsByOrderId(orderId,null);
return ServerResponseEntity.success(orderItems);
}
@Operation(summary = "取消总订单", description = "根据订单ID批量取消总订单")
@RepeatSubmit()
@PostMapping("/cancelHyOrder")
public ServerResponseEntity<String> cancelHyOrder(@RequestBody Long orderId) {
if (orderId == null) {
return ServerResponseEntity.fail("-1", "请选择要取消的订单");
}
Long userId = SecurityUtils.getUser().getUserId();
boolean result = hyOrderService.cancelById(orderId, userId);
return result ? ServerResponseEntity.success("取消成功") : ServerResponseEntity.fail("-1", "取消失败");
}
@Operation(summary = "删除总订单", description = "根据订单ID逻辑删除总订单")
@RepeatSubmit()
@PostMapping("/deleteHyOrder")
public ServerResponseEntity<Boolean> deleteHyOrder(@RequestBody Long orderId) {
if (orderId == null) {
return ServerResponseEntity.fail("-1", "请选择要删除的订单");
}
Long userId = SecurityUtils.getUser().getUserId();
return ServerResponseEntity.success(hyOrderService.logicDeleteByIds(orderId, userId));
}
@Operation(summary = "取消订单", description = "根据订单ID批量取消订单")
@RepeatSubmit()
@PostMapping("/cancelOrder")
public ServerResponseEntity<String> cancelOrder(@RequestBody List<Long> orderIds) {
if (orderIds == null || orderIds.isEmpty()) {
return ServerResponseEntity.fail("-1", "请选择要取消的订单");
}
Long userId = SecurityUtils.getUser().getUserId();
boolean result = hyOrderItemService.cancelByIds(orderIds, userId);
return result ? ServerResponseEntity.success("取消成功") : ServerResponseEntity.fail("-1", "取消失败");
}
@Operation(summary = "获取订单状态统计", description = "统计各个状态的订单数量")
@GetMapping("/statusCount")
public ServerResponseEntity<Map<String, Long>> getOrderStatusCount() {
Long userId = SecurityUtils.getUser().getUserId();
return ServerResponseEntity.success(hyOrderItemService.countByStatus(userId));
}
@Operation(summary = "获取总订单待付款的数量", description = "获取总订单待付款的数量")
@GetMapping("/hyOrder/statusCount")
public ServerResponseEntity<Long> statusCount() {
Long userId = SecurityUtils.getUser().getUserId();
return ServerResponseEntity.success(hyOrderService.countByStatus(userId));
}
public static String genItemId() {
//取当前时间的长整形值包含毫秒
long millis = System.currentTimeMillis();
//加上两位随机数
Random random = new Random();
int end2 = random.nextInt(99);
//如果不足两位前面补0
return "DD" + millis + String.format("%02d", end2);
}
}

View File

@@ -0,0 +1,346 @@
package org.dromara.web.controller;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.mall.domain.TzProd;
import org.dromara.mall.domain.TzProdBrowse;
import org.dromara.mall.domain.bo.TzProdBrowseBo;
import org.dromara.mall.domain.bo.TzProdCommBo;
import org.dromara.mall.domain.bo.TzProdFavoriteBo;
import org.dromara.mall.domain.vo.*;
import org.dromara.mall.service.*;
import org.dromara.system.domain.vo.SysTenantVo;
import org.dromara.system.service.ISysTenantService;
import org.dromara.web.common.SecurityUtils;
import org.dromara.web.common.ServerResponseEntity;
import org.dromara.web.domain.vo.UserProdStatsVo;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author Maosw
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/api/mall/prod")
@Tag(name = "商品接口")
public class ApiProdController {
private final ITzProdService prodService;
private final ITzSkuService skuService;
private final ITzProdFavoriteService prodFavoriteService;
private final ITzProdBrowseService prodBrowseService;
private final ITzCategoryService categoryService;
private final ITzHotSearchService hotSearchService;
private final ITzUserSearchService userSearchService;
private final ITzProdCommService prodCommService;
private final ITzProdRelationService prodRelationService;
private final ISysTenantService sysTenantService;
@PostMapping("/pageProd")
@Operation(summary = "通过分类id商品列表信息", description = "根据分类ID获取该分类下所有的商品列表信息")
@Parameter(name = "categoryId", description = "分类ID")
public ServerResponseEntity<IPage<TzProdVo>> prodList(@Valid PageQuery pageQuery, @RequestParam String categoryId) {
List<Long> categoryIds = Arrays.stream(categoryId.split(","))
.map(Long::parseLong)
.collect(Collectors.toList());
IPage<TzProdVo> productPage = prodService.pageByCategoryId(pageQuery, categoryIds);
return ServerResponseEntity.success(productPage);
}
@PostMapping("/prodInfo")
@Operation(summary = "商品详情信息", description = "根据商品IDprodId获取商品信息")
@Parameters({@Parameter(name = "prodId", description = "商品ID", required = true)})
public ServerResponseEntity<TzProdVo> prodInfo(@RequestParam(value = "prodId") Long prodId) {
Long userId = SecurityUtils.getUserInfo();
TzProdVo tzProdVo = prodService.queryById(prodId);
if (ObjectUtil.isEmpty(tzProdVo)) {
throw new ServiceException("prodId=" + prodId + "该商品不存在");
}
if (ObjectUtil.isNotEmpty(userId)) {
TzProdBrowse tzProdBrowse = prodBrowseService.queryListOne(userId, prodId);
TzProdBrowseBo prodBrowse;
if (ObjectUtil.isEmpty(tzProdBrowse)) {
prodBrowse = new TzProdBrowseBo();
prodBrowse.setUserId(userId);
prodBrowse.setProdId(prodId);
prodBrowse.setCreateTime(new Date());
prodBrowseService.insertByBo(prodBrowse);
} else {
tzProdBrowse.setCreateTime(new Date());
prodBrowseService.update(tzProdBrowse);
}
boolean exist = prodFavoriteService.exists(userId, prodId);
if (exist) {
tzProdVo.setIsCollect(1L);
} else {
tzProdVo.setIsCollect(0L);
}
}
List<TzSkuVo> skuList = skuService.listByProdId(prodId);
// 启用的sku列表
List<TzSkuVo> useSkuList = skuList.stream().filter(sku -> sku.getStatus() == 1).collect(Collectors.toList());
tzProdVo.setSkuList(useSkuList);
//浏览量+1
LambdaUpdateWrapper<TzProd> lwq = new LambdaUpdateWrapper<>();
lwq.eq(TzProd::getProdId, prodId);
lwq.setIncrBy(TzProd::getBrowseNum, 1);
prodService.update(lwq);
return ServerResponseEntity.success(tzProdVo);
}
@PostMapping("/saleProdPage")
@Operation(summary = "特价专区", description = "获取特价专区商品列表")
public ServerResponseEntity<IPage<TzProdVo>> saleProdPage(@Valid @RequestBody PageQuery pageQuery) {
IPage<TzProdVo> productPage = prodService.saleProdPage(pageQuery);
return ServerResponseEntity.success(productPage);
}
@PostMapping("/lastedProdPage")
@Operation(summary = "新品推荐", description = "获取新品推荐商品列表")
public ServerResponseEntity<IPage<TzProdVo>> lastedProdPage(@Valid @RequestBody PageQuery pageQuery) {
IPage<TzProdVo> productPage = prodService.pageByPutAwayTime(pageQuery);
Long userId = SecurityUtils.getUserInfo();
if (ObjectUtil.isNotNull(userId)) {
return ServerResponseEntity.success(productPage(productPage, userId));
}
return ServerResponseEntity.success(productPage);
}
@PostMapping("/randomProdPage")
@Operation(summary = "随机推荐", description = "获取随机推荐商品列表")
public ServerResponseEntity<IPage<TzProdVo>> randomProdPage(@Valid @RequestBody PageQuery pageQuery) {
IPage<TzProdVo> productPage = prodService.randomProdPage(pageQuery);
Long userId = SecurityUtils.getUserInfo();
if (ObjectUtil.isNotNull(userId)) {
return ServerResponseEntity.success(productPage(productPage, userId));
}
return ServerResponseEntity.success(productPage);
}
@PostMapping("/hotProdPage")
@Operation(summary = "热门推荐", description = "获取热门推荐商品列表")
public ServerResponseEntity<IPage<TzProdVo>> hotProdPage(@Valid @RequestBody PageQuery pageQuery) {
IPage<TzProdVo> productPage = prodService.hotProdPage(pageQuery);
Long userId = SecurityUtils.getUserInfo();
if (ObjectUtil.isNotNull(userId)) {
return ServerResponseEntity.success(productPage(productPage, userId));
}
return ServerResponseEntity.success(productPage);
}
@PostMapping("/getSkuList")
@Operation(summary = "通过prodId获取商品全部规格列表", description = "通过prodId获取商品全部规格列表")
@Parameter(name = "prodId", description = "商品ID", required = true)
public ServerResponseEntity<List<TzSkuVo>> getSkuListByProdId(@RequestParam(value = "prodId") Long prodId) {
List<TzSkuVo> skuList = skuService.listByProdId(prodId);
return ServerResponseEntity.success(skuList);
}
@PostMapping("/saveProdFavor")
@Operation(summary = "商品收藏", description = "根据商品IDprodId收藏商品")
@Parameter(name = "prodId", description = "商品ID", required = true)
public ServerResponseEntity<Boolean> saveProdFavor(@RequestParam(value = "prodId") Long prodId) {
Long userId = SecurityUtils.getUser().getUserId();
return ServerResponseEntity.success(prodService.updateCollectNum(userId, prodId));
}
@PostMapping("/isProdFavor")
@Operation(summary = "是否已经商品收藏", description = "根据商品IDprodId查询是否已经商品收藏")
@Parameter(name = "prodId", description = "商品ID", required = true)
public ServerResponseEntity<Boolean> isProdFavor(@RequestParam(value = "prodId") Long prodId) {
Long userId = SecurityUtils.getUser().getUserId();
boolean exist = prodFavoriteService.exists(userId, prodId);
return ServerResponseEntity.success(exist);
}
@PostMapping("/clearProdFavor")
@Operation(summary = "取消商品收藏", description = "根据商品IDprodId取消收藏商品")
@Parameter(name = "prodId", description = "商品ID", required = true)
public ServerResponseEntity<Boolean> clearProdFavor(@RequestParam(value = "prodId") Long prodId) {
Long userId = SecurityUtils.getUser().getUserId();
return ServerResponseEntity.success(prodFavoriteService.clearProdFavor(userId, prodId));
}
@PostMapping("/getProdFavor")
@Operation(summary = "分页查询收藏商品列表", description = "获取收藏商品列表")
public ServerResponseEntity<IPage<TzProdVo>> getProdFavor(@Valid @RequestBody PageQuery pageQuery) {
Long userId = SecurityUtils.getUser().getUserId();
IPage<TzProdVo> productPage = prodFavoriteService.queryPageListByUserId(userId, pageQuery);
return ServerResponseEntity.success(productPage);
}
@PostMapping("/getProdBrowse")
@Operation(summary = "分页查询浏览商品列表", description = "获取浏览商品列表")
public ServerResponseEntity<IPage<TzProdVo>> getProdBrowse(@Valid @RequestBody PageQuery pageQuery) {
Long userId = SecurityUtils.getUser().getUserId();
IPage<TzProdVo> productPage = prodBrowseService.queryPageListByUserId(userId, pageQuery);
if (ObjectUtil.isNotNull(userId)) {
return ServerResponseEntity.success(productPage(productPage, userId));
}
return ServerResponseEntity.success(productPage);
}
@GetMapping("/categoryAll")
@Operation(summary = "全部分类信息列表", description = "获取全部分类信息列表")
public ServerResponseEntity<List<TzCategoryVo>> categoryAll() {
List<TzCategoryVo> categories = categoryService.categoryAll();
return ServerResponseEntity.success(categories);
}
@GetMapping("/categoryInfo")
@Operation(summary = "分类信息列表", description = "获取所有的产品分类信息顶级分类的parentId为0,默认为顶级分类")
@Parameter(name = "parentId", description = "分类ID")
public ServerResponseEntity<List<TzCategoryVo>> categoryInfo(@RequestParam(value = "parentId", defaultValue = "0") Long parentId) {
List<TzCategoryVo> categories = categoryService.listByParentId(parentId);
return ServerResponseEntity.success(categories);
}
@PostMapping("/searchProdPage")
@Operation(summary = "分页排序搜索商品", description = "根据商品名搜索")
@Parameters({@Parameter(name = "categoryId", description = "分类ID"),@Parameter(name = "prodName", description = "商品名"), @Parameter(name = "floor", description = "是否特价 1是 2", required = true),@Parameter(name = "sort", description = "排序(0综合 1价格排序 2热门 3新品)", required = true), @Parameter(name = "orderBy", description = "排序(0升序 1降序)--sort选择1时必传")})
public ServerResponseEntity<IPage<TzProdVo>> searchProdPage(@RequestBody PageQuery pageQuery, @RequestParam(value = "categoryId") Long categoryId, @RequestParam(value = "prodName") String prodName, @RequestParam(value = "floor") Integer floor, @RequestParam(value = "sort") Integer sort, @RequestParam(value = "orderBy") Integer orderBy) {
Long userId = SecurityUtils.getUserInfo();
//用户个人搜索关键词叠加
if (ObjectUtil.isNotEmpty(userId)) {
userSearchService.setSearchNumByUserID(prodName, userId);
}
//热搜关键词次数叠加
hotSearchService.setSearchNum(prodName);
return ServerResponseEntity.success(prodService.getSearchProdPageByProdName(pageQuery, categoryId, prodName, floor, sort, orderBy));
}
@PostMapping("/prodCommByProdId")
@Operation(summary = "商品评论列表", description = "根据商品IDprodId查询商品评论列表")
@Parameter(name = "prodId", description = "商品ID", required = true)
public ServerResponseEntity<IPage<TzProdCommVo>> prodCommByProdId(@RequestParam(value = "prodId") Long prodId, @RequestBody PageQuery pageQuery) {
IPage<TzProdCommVo> prodCommPage = prodCommService.queryPageListByProdId(prodId, pageQuery);
return ServerResponseEntity.success(prodCommPage);
}
@Operation(summary = "获取用户商品评论列表", description = "分页获取当前用户的商品评论列表")
@PostMapping("/userProdComm")
public ServerResponseEntity<IPage<TzProdCommVo>> getUserProdComm(@Valid @RequestBody PageQuery pageQuery) {
Long userId = SecurityUtils.getUser().getUserId();
TzProdCommBo bo = new TzProdCommBo();
bo.setUserId(userId);
// bo.setStatus(1);
bo.setDelFlag(1);
return ServerResponseEntity.success(prodCommService.queryPageListByUser(bo, pageQuery));
}
@PostMapping("/prodCommById")
@Operation(summary = "商品评论详情", description = "根据评论IDprodCommId查询商品评论详情")
@Parameter(name = "prodCommId", description = "评论ID", required = true)
public ServerResponseEntity<TzProdCommVo> prodCommById(@RequestParam(value = "prodCommId") Long prodCommId) {
TzProdCommVo prodCommVo = prodCommService.queryById(prodCommId);
return ServerResponseEntity.success(prodCommVo);
}
@PostMapping("/prodCommInsert")
@Operation(summary = "发表评论", description = "发表评论")
public ServerResponseEntity<Boolean> prodCommInsert(@Valid @RequestBody TzProdCommBo bo) {
Long userId = SecurityUtils.getUser().getUserId();
bo.setUserId(userId);
return ServerResponseEntity.success(prodCommService.insertByBo(bo));
}
@Operation(summary = "查询商品评论数量", description = "根据商品ID查询评论数量")
@GetMapping("/commentCount/{prodId}")
public ServerResponseEntity<Long> commentCount(@PathVariable Long prodId) {
return ServerResponseEntity.success(prodCommService.countByProdId(prodId));
}
@PostMapping("/prodRelationList")
@Operation(summary = "商品关联列表", description = "根据商品IDprodId查询商品关联列表分页查询商品列表")
@Parameter(name = "prodId", description = "商品ID", required = true)
public ServerResponseEntity<IPage<TzProdVo>> prodRelationList(@RequestParam(value = "prodId") Long prodId, @RequestBody PageQuery pageQuery) {
try {
// 根据prodId查询商品关联列表
List<Long> relatedProdIds = prodRelationService.getRelatedProdIds(prodId);
if (relatedProdIds.isEmpty()) {
// 如果关联商品集合为空,则返回空列表
return ServerResponseEntity.success(null);
}
// 根据关联商品集合查询商品列表
IPage<TzProdVo> page = prodService.getProdListByProdIds(relatedProdIds, pageQuery);
// 返回成功响应
return ServerResponseEntity.success(page);
} catch (Exception e) {
// 处理其他异常
throw new ServiceException("系统错误: " + e.getMessage());
}
}
@GetMapping("/userProdStats")
@Operation(summary = "获取用户收藏和浏览商品数量", description = "根据用户ID获取收藏商品数量和浏览商品数量")
public ServerResponseEntity<UserProdStatsVo> getUserProdStats() {
Long userId = SecurityUtils.getUser().getUserId();
Long favoriteCount = prodFavoriteService.countByUserId(userId);
Long browseCount = prodBrowseService.countByUserId(userId);
UserProdStatsVo statsVo = new UserProdStatsVo();
statsVo.setFavoriteCount(favoriteCount);
statsVo.setBrowseCount(browseCount);
return ServerResponseEntity.success(statsVo);
}
@Operation(summary = "获取商品客服信息", description = "根据商品ID获取对应租户的客服企业微信链接")
@GetMapping("/customerService/{prodId}")
public ServerResponseEntity<String> getCustomerService(@PathVariable Long prodId) {
// 1. 查询商品信息获取租户ID
TzProdVo prodVo = prodService.queryById(prodId);
if (prodVo == null) {
return ServerResponseEntity.fail("-1","商品不存在");
}
// 2. 根据租户ID查询租户信息
SysTenantVo tenant = sysTenantService.getTenantById(prodVo.getTenantId());
if (tenant == null) {
return ServerResponseEntity.fail("-1","租户信息不存在");
}
// 3. 返回租户的客服企业微信链接
return ServerResponseEntity.success(tenant.getKfWx());
}
public IPage<TzProdVo> productPage(IPage<TzProdVo> productPage, Long userId) {
TzProdFavoriteBo favoriteBo = new TzProdFavoriteBo();
favoriteBo.setUserId(userId);
List<TzProdFavoriteVo> favoriteList = prodFavoriteService.queryList(favoriteBo);
for (TzProdVo prodVo : productPage.getRecords()) {
for (TzProdFavoriteVo prodFavorite : favoriteList) {
if (prodVo.getProdId().equals(prodFavorite.getProdId())) {
prodVo.setIsCollect(1L);
break;
}
}
}
return productPage;
}
}

View File

@@ -0,0 +1,224 @@
package org.dromara.web.controller;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.mall.domain.HyPromoter;
import org.dromara.mall.domain.bo.*;
import org.dromara.mall.domain.vo.*;
import org.dromara.mall.service.*;
import org.dromara.web.common.*;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 推广员接口
* @author Maosw
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/api/mall/promoter")
@Tag(name = "推广员接口")
public class ApiPromoterController {
private final IHyPromoterService promoterService;
private final ITzBankCardService bankCardService;
private final ITzWithdrawRequestService withdrawRequestService;
private final IHyPromoterRecordService promoterRecordService;
private final IHyCodeOrderService codeOrderService;
private final IHyMemberCodeService memberCodeService;
private final TokenStore tokenStore;
@Operation(summary = "推广员注册")
@PostMapping("/register")
public ServerResponseEntity<Boolean> register(@Validated @RequestBody HyPromoterBo bo) {
// 验证手机号是否已注册
if (promoterService.checkPhoneUnique(bo.getPhone())) {
return ServerResponseEntity.fail("-1","该手机号已注册");
}
return ServerResponseEntity.success(promoterService.register(bo));
}
@Operation(summary = "推广员登录")
@PostMapping("/login")
public ServerResponseEntity<TokenInfoVO> login(@RequestParam String phone, @RequestParam String password) {
if (!promoterService.checkPhoneUnique(phone)) {
return ServerResponseEntity.fail("-1","该手机号未注册");
}
HyPromoter promoter = promoterService.login(phone, password);
if (ObjectUtil.isNotEmpty(promoter)) {
//登录
UserInfoInTokenBO userInfoInTokenBO = new UserInfoInTokenBO();
userInfoInTokenBO.setUserId(promoter.getId());
userInfoInTokenBO.setSysType(0);
userInfoInTokenBO.setEnabled(true);
return ServerResponseEntity.success(tokenStore.storeAndGetVo(userInfoInTokenBO));
}
return ServerResponseEntity.fail("-1","登录失败");
}
/**
* 重置密码
*/
@Operation(summary = "重置密码")
@PostMapping("/resetPassword")
public ServerResponseEntity<Boolean> resetPassword(@RequestParam String phone, @RequestParam String oldPassword, @RequestParam String newPassword) {
if (!promoterService.checkPhoneUnique(phone)) {
return ServerResponseEntity.fail("-1","该手机号未注册");
}
return ServerResponseEntity.success(promoterService.resetPassword(phone, oldPassword, newPassword));
}
@Operation(summary = "提交推广员实名认证", description = "提交推广员实名认证")
@RepeatSubmit()
@PostMapping("/submitAuth")
public ServerResponseEntity<Boolean> submitAuth(@Validated @RequestBody HyPromoterBo bo) {
Long userId = SecurityUtils.getUser().getUserId();
bo.setId(userId);
return ServerResponseEntity.success(promoterService.submitAuth(bo));
}
@Operation(summary = "绑定银行卡", description = "推广员绑定银行卡信息")
@RepeatSubmit()
@PostMapping("/bindBankCard")
public ServerResponseEntity<Boolean> bindBankCard(@Validated @RequestBody TzBankCardBo bo) {
Long userId = SecurityUtils.getUser().getUserId();
bo.setUserId(userId);
bo.setRoleType(3);
return ServerResponseEntity.success(bankCardService.insertByBo(bo));
}
@Operation(summary = "获取银行卡列表", description = "获取推广员绑定的银行卡列表")
@GetMapping("/bankCardList")
public ServerResponseEntity<List<TzBankCardVo>> getBankCardList() {
Long userId = SecurityUtils.getUser().getUserId();
TzBankCardBo bo = new TzBankCardBo();
bo.setUserId(userId);
bo.setRoleType(3);
bo.setDelFlag(1);
return ServerResponseEntity.success(bankCardService.queryListAPP(bo));
}
@Operation(summary = "删除银行卡", description = "解绑推广员银行卡")
@RepeatSubmit()
@PostMapping("/deleteBankCard/{cardId}")
public ServerResponseEntity<Boolean> deleteBankCard(@PathVariable Long cardId) {
Long userId = SecurityUtils.getUser().getUserId();
return ServerResponseEntity.success(bankCardService.logicDeleteByCardId(cardId, userId));
}
@Operation(summary = "设置默认银行卡", description = "设置推广员默认银行卡")
@RepeatSubmit()
@PostMapping("/setDefaultBankCard/{cardId}")
public ServerResponseEntity<Boolean> setDefaultBankCard(@PathVariable Long cardId) {
Long userId = SecurityUtils.getUser().getUserId();
return ServerResponseEntity.success(bankCardService.setDefaultCard(cardId, userId,3));
}
@Operation(summary = "查询是否已绑定银行卡", description = "查询当前推广员是否已绑定银行卡")
@GetMapping("/hasBankCard")
public ServerResponseEntity<Boolean> hasBankCard() {
Long userId = SecurityUtils.getUser().getUserId();
return ServerResponseEntity.success(bankCardService.hasBankCard(userId,3));
}
@Operation(summary = "推广员提现申请", description = "推广员申请提现")
@RepeatSubmit()
@PostMapping("/withdraw")
public ServerResponseEntity<Boolean> withdraw(@Validated @RequestBody TzWithdrawRequestBo bo) {
Long userId = SecurityUtils.getUser().getUserId();
bo.setUserId(userId);
bo.setRoleType(3);
return ServerResponseEntity.success(withdrawRequestService.applyWithdrawPromoter(bo));
}
@Operation(summary = "获取推广员提现记录", description = "获取推广员提现记录")
@GetMapping("/withdrawList")
public ServerResponseEntity<IPage<TzWithdrawRequestVo>> getWithdrawList(PageQuery pageQuery) {
Long userId = SecurityUtils.getUser().getUserId();
TzWithdrawRequestBo bo = new TzWithdrawRequestBo();
bo.setUserId(userId);
bo.setRoleType(3);
return ServerResponseEntity.success(withdrawRequestService.getWithdrawList(bo, pageQuery));
}
@Operation(summary = "分页获取推广员资金记录列表", description = "分页获取当前推广员的资金记录列表")
@GetMapping("/recordList")
public ServerResponseEntity<IPage<HyPromoterRecordVo>> getRecordList(@Valid PageQuery pageQuery) {
Long userId = SecurityUtils.getUser().getUserId();
HyPromoterRecordBo bo = new HyPromoterRecordBo();
bo.setPromoterId(userId);
bo.setDelFlag(1);
return ServerResponseEntity.success(promoterRecordService.queryPageListAPP(bo, pageQuery));
}
@Operation(summary = "推广员购买兑换码", description = "推广员购买会员码生成订单")
@RepeatSubmit()
@PostMapping("/buyCode")
public ServerResponseEntity<JSONObject> buyMemberCode(@Validated @RequestBody HyCodeOrderBo bo) throws Exception {
Long userId = SecurityUtils.getUser().getUserId();
bo.setPromoterId(userId);
return ServerResponseEntity.success(codeOrderService.createOrder(bo));
}
@Operation(summary = "推广员获取会员兑换码订单列表", description = "分页获取当前推广员的会员兑换码订单列表")
@GetMapping("/orderList")
public ServerResponseEntity<IPage<HyCodeOrderVo>> getOrderList(@Valid PageQuery pageQuery) {
Long userId = SecurityUtils.getUser().getUserId();
HyCodeOrderBo bo = new HyCodeOrderBo();
bo.setPromoterId(userId);
bo.setDelFlag(1);
return ServerResponseEntity.success(codeOrderService.queryPageListAPP(bo, pageQuery));
}
@Operation(summary = "删除会员兑换码订单", description = "根据订单ID批量逻辑删除未付款的会员兑换码订单")
@RepeatSubmit()
@PostMapping("/deleteOrder")
public ServerResponseEntity<String> deleteOrder(@RequestBody List<Long> orderIds) {
if (orderIds == null || orderIds.isEmpty()) {
return ServerResponseEntity.fail("-1", "请选择要删除的订单");
}
Long userId = SecurityUtils.getUser().getUserId();
boolean result = codeOrderService.logicDeleteByIds(orderIds, userId, 3);
return result ? ServerResponseEntity.success("删除成功") : ServerResponseEntity.fail("-1", "删除失败");
}
@Operation(summary = "获取会员兑换码列表", description = "分页获取当前推广员的会员兑换码列表")
@PostMapping("/codeList")
public ServerResponseEntity<IPage<HyMemberCodeVo>> getMemberCodeList(@Valid PageQuery pageQuery, @RequestBody HyMemberCodeBo bo) {
Long userId = SecurityUtils.getUser().getUserId();
// HyMemberCodeBo bo = new HyMemberCodeBo();
bo.setPromoterId(userId);
bo.setDelFlag(1);
return ServerResponseEntity.success(memberCodeService.queryPageListAPP(bo, pageQuery));
}
/**
* 复制兑换码
*/
@Operation(summary = "复制兑换码", description = "复制兑换码")
@RepeatSubmit()
@PostMapping("/copyCode")
public ServerResponseEntity<String> copyCode(@RequestBody HyMemberCodeBo bo) {
Long userId = SecurityUtils.getUser().getUserId();
bo.setPromoterId(userId);
return ServerResponseEntity.success(memberCodeService.copyCode(bo));
}
}

View File

@@ -0,0 +1,230 @@
/*
* Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
*
* https://www.mall4j.com/
*
* 未经允许,不可做商业用途!
*
* 版权所有,侵权必究!
*/
package org.dromara.web.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.mall.domain.bo.TzBankCardBo;
import org.dromara.mall.domain.bo.TzUserAddressBo;
import org.dromara.mall.domain.bo.TzUserBo;
import org.dromara.mall.domain.bo.TzWithdrawRequestBo;
import org.dromara.mall.domain.vo.TzBankCardVo;
import org.dromara.mall.domain.vo.TzUserAddressVo;
import org.dromara.mall.domain.vo.TzUserVo;
import org.dromara.mall.domain.vo.TzWithdrawRequestVo;
import org.dromara.mall.service.ITzBankCardService;
import org.dromara.mall.service.ITzUserAddressService;
import org.dromara.mall.service.ITzUserService;
import org.dromara.mall.service.ITzWithdrawRequestService;
import org.dromara.web.common.SecurityUtils;
import org.dromara.web.common.ServerResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* @author Maosw
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/api/mall/user")
@Tag(name = "用户接口")
public class ApiUserController {
private final ITzUserService userService;
private final ITzUserAddressService userAddressService;
private final ITzBankCardService bankCardService;
private final ITzWithdrawRequestService withdrawRequestService;
@GetMapping("/userInfo")
@Operation(summary = "查看用户信息" , description = "根据用户IDuserId获取用户信息")
public ServerResponseEntity<TzUserVo> userInfo() {
Long userId = SecurityUtils.getUser().getUserId();
TzUserVo tzUserVo = userService.queryById(userId);
return ServerResponseEntity.success(tzUserVo);
}
@GetMapping("/userAddress")
@Operation(summary = "查询用户默认地址信息" , description = "根据用户IDuserId查询用户默认地址信息")
public ServerResponseEntity<TzUserAddressVo> userAddress() {
Long userId = SecurityUtils.getUser().getUserId();
TzUserAddressVo userAddress = userAddressService.userAddress(userId);
return ServerResponseEntity.success(userAddress);
}
@GetMapping("/userAddressList")
@Operation(summary = "查询用户全部地址信息" , description = "根据用户IDuserId查询用户全部地址信息")
public ServerResponseEntity<List<TzUserAddressVo>> userAddressList() {
Long userId = SecurityUtils.getUser().getUserId();
List<TzUserAddressVo> userAddressList = userAddressService.userAddressList(userId);
return ServerResponseEntity.success(userAddressList);
}
@Operation(summary = "新增用户地址" , description = "新增用户地址")
@RepeatSubmit()
@PostMapping("/addUserAddress")
public ServerResponseEntity<Boolean> addUserAddress(@Validated(AddGroup.class) @RequestBody TzUserAddressBo bo) {
Long userId = SecurityUtils.getUser().getUserId();
bo.setUserId(userId);
return ServerResponseEntity.success(userAddressService.insertByBo(bo));
}
@Operation(summary = "修改用户地址" , description = "修改用户地址")
@RepeatSubmit()
@PostMapping("/editUserAddress")
public ServerResponseEntity<Boolean> editUserAddress(@Validated(EditGroup.class) @RequestBody TzUserAddressBo bo) {
Long userId = SecurityUtils.getUser().getUserId();
bo.setUserId(userId);
return ServerResponseEntity.success(userAddressService.updateByBo(bo));
}
@Operation(summary = "删除用户地址" , description = "删除用户地址")
@RepeatSubmit()
@PostMapping("/delUserAddress")
public ServerResponseEntity<Boolean> delUserAddress(@RequestParam List<Long> ids) {
SecurityUtils.getUser();
return ServerResponseEntity.success(userAddressService.deleteWithValidByIds(ids, true));
}
@Operation(summary = "设置默认用户地址" , description = "设置默认用户地址")
@RepeatSubmit()
@PostMapping("/editDefaultUserAddress")
public ServerResponseEntity<Boolean> editDefaultUserAddress(@Validated(EditGroup.class) @RequestBody TzUserAddressBo bo) {
Long userId = SecurityUtils.getUser().getUserId();
userAddressService.clearAddressList(userId);
return ServerResponseEntity.success(userAddressService.updateByBo(bo));
}
@PostMapping("/setUserInfo")
@Operation(summary = "设置用户信息" , description = "设置用户信息")
public ServerResponseEntity<Boolean> setUserInfo(@Valid @RequestBody TzUserBo tzUserBo) {
Long userId = SecurityUtils.getUser().getUserId();
tzUserBo.setUserId(userId);
return ServerResponseEntity.success(userService.updateByBo(tzUserBo));
}
@Operation(summary = "修改用户头像", description = "更新用户的头像URL")
@RepeatSubmit()
@PostMapping("/updateAvatar")
public ServerResponseEntity<Boolean> updateAvatar(@RequestParam String avatarUrl) {
Long userId = SecurityUtils.getUser().getUserId();
TzUserBo userBo = new TzUserBo();
userBo.setUserId(userId);
userBo.setPic(avatarUrl);
return ServerResponseEntity.success(userService.updateByBo(userBo));
}
@Operation(summary = "提交设计师认证", description = "提交设计师认证信息")
@RepeatSubmit()
@PostMapping("/submitSjsAuth")
public ServerResponseEntity<Boolean> submitSjsAuth(@Validated @RequestBody TzUserBo bo) {
Long userId = SecurityUtils.getUser().getUserId();
bo.setUserId(userId);
return ServerResponseEntity.success(userService.submitSjsAuth(bo));
}
@Operation(summary = "提交实名认证", description = "提交实名认证信息")
@RepeatSubmit()
@PostMapping("/submitAuth")
public ServerResponseEntity<Boolean> submitAuth(@Validated @RequestBody TzUserBo bo) {
Long userId = SecurityUtils.getUser().getUserId();
bo.setUserId(userId);
return ServerResponseEntity.success(userService.submitAuth(bo));
}
@Operation(summary = "绑定银行卡", description = "会员用户绑定银行卡信息")
@RepeatSubmit()
@PostMapping("/bindBankCard")
public ServerResponseEntity<Boolean> bindBankCard(@Validated @RequestBody TzBankCardBo bo) {
Long userId = SecurityUtils.getUser().getUserId();
bo.setUserId(userId);
bo.setRoleType(4);
return ServerResponseEntity.success(bankCardService.insertByBo(bo));
}
@Operation(summary = "修改银行卡", description = "修改银行卡信息")
@RepeatSubmit()
@PostMapping("/editBankCard")
public ServerResponseEntity<Boolean> editBankCard(@Validated @RequestBody TzBankCardBo bo) {
Long userId = SecurityUtils.getUser().getUserId();
bo.setUserId(userId);
bo.setRoleType(4);
return ServerResponseEntity.success(bankCardService.updateByBo(bo));
}
@Operation(summary = "获取银行卡列表", description = "获取用户绑定的银行卡列表")
@GetMapping("/bankCardList")
public ServerResponseEntity<List<TzBankCardVo>> getBankCardList() {
Long userId = SecurityUtils.getUser().getUserId();
TzBankCardBo bo = new TzBankCardBo();
bo.setUserId(userId);
bo.setRoleType(4);
bo.setDelFlag(1);
return ServerResponseEntity.success(bankCardService.queryListAPP(bo));
}
@Operation(summary = "删除银行卡", description = "解绑用户银行卡")
@RepeatSubmit()
@PostMapping("/deleteBankCard/{cardId}")
public ServerResponseEntity<Boolean> deleteBankCard(@PathVariable Long cardId) {
Long userId = SecurityUtils.getUser().getUserId();
return ServerResponseEntity.success(bankCardService.logicDeleteByCardId(cardId, userId));
}
@Operation(summary = "设置默认银行卡", description = "设置用户默认银行卡")
@RepeatSubmit()
@PostMapping("/setDefaultBankCard/{cardId}")
public ServerResponseEntity<Boolean> setDefaultBankCard(@PathVariable Long cardId) {
Long userId = SecurityUtils.getUser().getUserId();
return ServerResponseEntity.success(bankCardService.setDefaultCard(cardId, userId,4));
}
@Operation(summary = "查询是否已绑定银行卡", description = "查询当前用户是否已绑定银行卡")
@GetMapping("/hasBankCard")
public ServerResponseEntity<Boolean> hasBankCard() {
Long userId = SecurityUtils.getUser().getUserId();
return ServerResponseEntity.success(bankCardService.hasBankCard(userId,4));
}
@Operation(summary = "用户提现申请", description = "用户申请提现")
@RepeatSubmit()
@PostMapping("/withdraw")
public ServerResponseEntity<Boolean> withdraw(@Validated @RequestBody TzWithdrawRequestBo bo) {
Long userId = SecurityUtils.getUser().getUserId();
bo.setUserId(userId);
bo.setRoleType(4);
return ServerResponseEntity.success(withdrawRequestService.applyWithdraw(bo));
}
@Operation(summary = "用户提现记录列表", description = "用户提现记录列表")
@GetMapping("/withdrawList")
public ServerResponseEntity<IPage<TzWithdrawRequestVo>> withdrawList(PageQuery pageQuery) {
Long userId = SecurityUtils.getUser().getUserId();
TzWithdrawRequestBo bo = new TzWithdrawRequestBo();
bo.setUserId(userId);
bo.setRoleType(4);
return ServerResponseEntity.success(withdrawRequestService.getWithdrawList(bo, pageQuery));
}
}

View File

@@ -0,0 +1,72 @@
package org.dromara.web.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.mall.domain.bo.TzProdWishlistBo;
import org.dromara.mall.domain.vo.TzProdWishlistVo;
import org.dromara.mall.service.ITzProdWishlistService;
import org.dromara.web.common.SecurityUtils;
import org.dromara.web.common.ServerResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 心愿单接口
* @author Maosw
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/api/mall/wishlist")
@Tag(name = "心愿单接口")
public class ApiWishlistController {
private final ITzProdWishlistService wishlistService;
@Operation(summary = "提交心愿单", description = "用户提交心愿单")
@PostMapping("/submit")
public ServerResponseEntity<Boolean> submitWishlist(@Valid @RequestBody TzProdWishlistBo bo) {
Long userId = SecurityUtils.getUser().getUserId();
bo.setUserId(userId);
return ServerResponseEntity.success(wishlistService.insertByBo(bo));
}
@Operation(summary = "获取心愿单列表", description = "分页获取用户心愿单列表")
@PostMapping("/list")
public ServerResponseEntity<IPage<TzProdWishlistVo>> getWishlist(@Valid @RequestBody PageQuery pageQuery) {
Long userId = SecurityUtils.getUser().getUserId();
TzProdWishlistBo bo = new TzProdWishlistBo();
bo.setUserId(userId);
return ServerResponseEntity.success(wishlistService.queryPageListAPP(bo, pageQuery));
}
@Operation(summary = "获取心愿单详情", description = "根据ID获取心愿单详情")
@GetMapping("/{id}")
public ServerResponseEntity<TzProdWishlistVo> getWishlistDetail(@PathVariable("id") Long id) {
Long userId = SecurityUtils.getUser().getUserId();
TzProdWishlistVo vo = wishlistService.queryById(id);
if (vo == null || !userId.equals(vo.getUserId())) {
return ServerResponseEntity.fail("-1","心愿单不存在");
}
return ServerResponseEntity.success(vo);
}
@Operation(summary = "删除心愿单", description = "删除用户心愿单")
@DeleteMapping("/{id}")
public ServerResponseEntity<Boolean> deleteWishlist(@PathVariable("id") Long id) {
Long userId = SecurityUtils.getUser().getUserId();
// 先查询是否是自己的心愿单
TzProdWishlistVo vo = wishlistService.queryById(id);
if (vo == null || !userId.equals(vo.getUserId())) {
return ServerResponseEntity.fail("-1", "心愿单不存在");
}
return ServerResponseEntity.success(wishlistService.deleteWithValidByIds(List.of(id), true));
}
}

View File

@@ -0,0 +1,25 @@
package org.dromara.web.domain.vo;
import lombok.Data;
/**
* 验证码信息
*
* @author Michelle.Chung
*/
@Data
public class CaptchaVo {
/**
* 是否开启验证码
*/
private Boolean captchaEnabled = true;
private String uuid;
/**
* 验证码图片
*/
private String img;
}

View File

@@ -0,0 +1,25 @@
package org.dromara.web.domain.vo;
import lombok.Data;
import java.util.List;
/**
* 登录租户对象
*
* @author Michelle.Chung
*/
@Data
public class LoginTenantVo {
/**
* 租户开关
*/
private Boolean tenantEnabled;
/**
* 租户对象列表
*/
private List<TenantListVo> voList;
}

View File

@@ -0,0 +1,54 @@
package org.dromara.web.domain.vo;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
/**
* 登录验证信息
*
* @author Michelle.Chung
*/
@Data
public class LoginVo {
/**
* 授权令牌
*/
@JsonProperty("access_token")
private String accessToken;
/**
* 刷新令牌
*/
@JsonProperty("refresh_token")
private String refreshToken;
/**
* 授权令牌 access_token 的有效期
*/
@JsonProperty("expire_in")
private Long expireIn;
/**
* 刷新令牌 refresh_token 的有效期
*/
@JsonProperty("refresh_expire_in")
private Long refreshExpireIn;
/**
* 应用id
*/
@JsonProperty("client_id")
private String clientId;
/**
* 令牌权限
*/
private String scope;
/**
* 用户 openid
*/
private String openid;
}

View File

@@ -0,0 +1,31 @@
package org.dromara.web.domain.vo;
import org.dromara.system.domain.vo.SysTenantVo;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
/**
* 租户列表
*
* @author Lion Li
*/
@Data
@AutoMapper(target = SysTenantVo.class)
public class TenantListVo {
/**
* 租户编号
*/
private String tenantId;
/**
* 企业名称
*/
private String companyName;
/**
* 域名
*/
private String domain;
}

View File

@@ -0,0 +1,17 @@
package org.dromara.web.domain.vo;
import lombok.Data;
@Data
public class UserProdStatsVo {
/**
* 收藏商品数量
*/
private Long favoriteCount;
/**
* 浏览商品数量
*/
private Long browseCount;
}

View File

@@ -0,0 +1,271 @@
--- # 监控中心配置
spring.boot.admin.client:
# 增加客户端开关
enabled: true
url: http://localhost:9090/admin
instance:
service-host-type: IP
metadata:
username: ${spring.boot.admin.client.username}
userpassword: ${spring.boot.admin.client.password}
username: @monitor.username@
password: @monitor.password@
--- # snail-job 配置
snail-job:
enabled: false
# 需要在 SnailJob 后台组管理创建对应名称的组,然后创建任务的时候选择对应的组,才能正确分派任务
group: "ruoyi_group"
# SnailJob 接入验证令牌 详见 script/sql/ry_job.sql `sj_group_config` 表
token: "SJ_cKqBTPzCsWA3VyuCfFoccmuIEGXjr5KT"
server:
host: 127.0.0.1
port: 17888
# 命名空间UUID 详见 script/sql/ry_job.sql `sj_namespace`表`unique_id`字段
namespace: ${spring.profiles.active}
# 随主应用端口漂移
port: 2${server.port}
# 客户端ip指定
host:
# RPC类型: netty, grpc
rpc-type: grpc
--- # 数据源配置
spring:
datasource:
type: com.zaxxer.hikari.HikariDataSource
# 动态数据源文档 https://www.kancloud.cn/tracy5546/dynamic-datasource/content
dynamic:
# 性能分析插件(有性能损耗 不建议生产环境使用)
p6spy: true
# 设置默认的数据源或者数据源组,默认值即为 master
primary: master
# 严格模式 匹配不到数据源则报错
strict: true
datasource:
# 主库数据源
master:
type: ${spring.datasource.type}
driverClassName: com.mysql.cj.jdbc.Driver
# jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
# rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
# url: jdbc:mysql://localhost:3306/jcs?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
# username: root
# password: root
url: jdbc:mysql://erp9.52o.site:13308/jcs20250106?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
username: jcs20250106
password: esXkafdSMsxRAkNe
# 从库数据源
slave:
lazy: false
type: ${spring.datasource.type}
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://124.223.56.113:13306/cailiao1?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
username: cailiao1
password: j5RcfMwRG2WMHyAC
# url: jdbc:mysql://localhost:3306/cailiao?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
# username:
# password:
# oracle:
# type: ${spring.datasource.type}
# driverClassName: oracle.jdbc.OracleDriver
# url: jdbc:oracle:thin:@//localhost:1521/XE
# username: ROOT
# password: root
# postgres:
# type: ${spring.datasource.type}
# driverClassName: org.postgresql.Driver
# url: jdbc:postgresql://localhost:5432/postgres?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true
# username: root
# password: root
# sqlserver:
# type: ${spring.datasource.type}
# driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
# url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true
# username: SA
# password: root
hikari:
# 最大连接池数量
maxPoolSize: 20
# 最小空闲线程数量
minIdle: 10
# 配置获取连接等待超时的时间
connectionTimeout: 30000
# 校验超时时间
validationTimeout: 5000
# 空闲连接存活最大时间默认10分钟
idleTimeout: 600000
# 此属性控制池中连接的最长生命周期值0表示无限生命周期默认30分钟
maxLifetime: 1800000
# 多久检查一次连接的活性
keepaliveTime: 30000
--- # redis 单机配置(单机与集群只能开启一个另一个需要注释掉)
spring.data:
redis:
# 地址
host: localhost
# 端口默认为6379
port: 6379
# 数据库索引
database: 0
# redis 密码必须配置
password: Huitu123
# 连接超时时间
timeout: 10s
# 是否开启ssl
ssl.enabled: false
# redisson 配置
redisson:
# redis key前缀
keyPrefix:
# 线程池数量
threads: 4
# Netty线程池数量
nettyThreads: 8
# 单节点配置
singleServerConfig:
# 客户端名称
clientName: ${ruoyi.name}
# 最小空闲连接数
connectionMinimumIdleSize: 8
# 连接池大小
connectionPoolSize: 32
# 连接空闲超时,单位:毫秒
idleConnectionTimeout: 10000
# 命令等待超时,单位:毫秒
timeout: 3000
# 发布和订阅连接池大小
subscriptionConnectionPoolSize: 50
--- # mail 邮件发送
mail:
enabled: false
host: smtp.163.com
port: 465
# 是否需要用户名密码验证
auth: true
# 发送方遵循RFC-822标准
from: xxx@163.com
# 用户名注意如果使用foxmail邮箱此处user为qq号
user: xxx@163.com
# 密码注意某些邮箱需要为SMTP服务单独设置密码详情查看相关帮助
pass: xxxxxxxxxx
# 使用 STARTTLS安全连接STARTTLS是对纯文本通信协议的扩展。
starttlsEnable: true
# 使用SSL安全连接
sslEnable: true
# SMTP超时时长单位毫秒缺省值不超时
timeout: 0
# Socket连接超时值单位毫秒缺省值不超时
connectionTimeout: 0
--- # sms 短信 支持 阿里云 腾讯云 云片 等等各式各样的短信服务商
# https://sms4j.com/doc3/ 差异配置文档地址 支持单厂商多配置,可以配置多个同时使用
sms:
# 配置源类型用于标定配置来源(interface,yaml)
config-type: yaml
# 用于标定yml中的配置是否开启短信拦截接口配置不受此限制
restricted: true
# 短信拦截限制单手机号每分钟最大发送,只对开启了拦截的配置有效
minute-max: 1
# 短信拦截限制单手机号每日最大发送量,只对开启了拦截的配置有效
account-max: 30
# 以下配置来自于 org.dromara.sms4j.provider.config.BaseConfig类中
blends:
# 唯一ID 用于发送短信寻找具体配置 随便定义别用中文即可
# 可以同时存在两个相同厂商 例如: ali1 ali2 两个不同的阿里短信账号 也可用于区分租户
config1:
# 框架定义的厂商名称标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分
supplier: alibaba
# 有些称为accessKey有些称之为apiKey也有称为sdkKey或者appId。
access-key-id: 您的accessKey
# 称为accessSecret有些称之为apiSecret
access-key-secret: 您的accessKeySecret
signature: 您的短信签名
sdk-app-id: 您的sdkAppId
config2:
# 厂商标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分
supplier: tencent
access-key-id: 您的accessKey
access-key-secret: 您的accessKeySecret
signature: 您的短信签名
sdk-app-id: 您的sdkAppId
--- # 三方授权
justauth:
# 前端外网访问地址
address: http://localhost:80
type:
maxkey:
# maxkey 服务器地址
# 注意 如下均配置均不需要修改 maxkey 已经内置好了数据
server-url: http://sso.maxkey.top
client-id: 876892492581044224
client-secret: x1Y5MTMwNzIwMjMxNTM4NDc3Mzche8
redirect-uri: ${justauth.address}/social-callback?source=maxkey
topiam:
# topiam 服务器地址
server-url: http://127.0.0.1:1989/api/v1/authorize/y0q************spq***********8ol
client-id: 449c4*********937************759
client-secret: ac7***********1e0************28d
redirect-uri: ${justauth.address}/social-callback?source=topiam
scopes: [openid, email, phone, profile]
qq:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=qq
union-id: false
weibo:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=weibo
gitee:
client-id: 91436b7940090d09c72c7daf85b959cfd5f215d67eea73acbf61b6b590751a98
client-secret: 02c6fcfd70342980cd8dd2f2c06c1a350645d76c754d7a264c4e125f9ba915ac
redirect-uri: ${justauth.address}/social-callback?source=gitee
dingtalk:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=dingtalk
baidu:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=baidu
csdn:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=csdn
coding:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=coding
coding-group-name: xx
oschina:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=oschina
alipay_wallet:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=alipay_wallet
alipay-public-key: MIIB**************DAQAB
wechat_open:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=wechat_open
wechat_mp:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=wechat_mp
wechat_enterprise:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=wechat_enterprise
agent-id: 1000002
gitlab:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=gitlab

View File

@@ -0,0 +1,273 @@
--- # 临时文件存储位置 避免临时文件被系统清理报错
spring.servlet.multipart.location: /ruoyi/server/temp
--- # 监控中心配置
spring.boot.admin.client:
# 增加客户端开关
enabled: true
url: http://localhost:9090/admin
instance:
service-host-type: IP
metadata:
username: ${spring.boot.admin.client.username}
userpassword: ${spring.boot.admin.client.password}
username: @monitor.username@
password: @monitor.password@
--- # snail-job 配置
snail-job:
enabled: false
# 需要在 SnailJob 后台组管理创建对应名称的组,然后创建任务的时候选择对应的组,才能正确分派任务
group: "ruoyi_group"
# SnailJob 接入验证令牌 详见 script/sql/ry_job.sql `sj_group_config`表
token: "SJ_cKqBTPzCsWA3VyuCfFoccmuIEGXjr5KT"
server:
host: 127.0.0.1
port: 17888
# 命名空间UUID 详见 script/sql/ry_job.sql `sj_namespace`表`unique_id`字段
namespace: ${spring.profiles.active}
# 随主应用端口漂移
port: 2${server.port}
# 客户端ip指定
host:
# RPC类型: netty, grpc
rpc-type: grpc
--- # 数据源配置
spring:
datasource:
type: com.zaxxer.hikari.HikariDataSource
# 动态数据源文档 https://www.kancloud.cn/tracy5546/dynamic-datasource/content
dynamic:
# 性能分析插件(有性能损耗 不建议生产环境使用)
p6spy: false
# 设置默认的数据源或者数据源组,默认值即为 master
primary: master
# 严格模式 匹配不到数据源则报错
strict: true
datasource:
# 主库数据源
master:
type: ${spring.datasource.type}
driverClassName: com.mysql.cj.jdbc.Driver
# jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
# rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
# url: jdbc:mysql://localhost:3306/cailiao?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
# username: root
# password: root
url: jdbc:mysql://localhost:3306/jcs?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
username: root
password: root
# 从库数据源
slave:
lazy: false
type: ${spring.datasource.type}
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://124.223.56.113:13306/cailiao1?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
username: cailiao1
password: j5RcfMwRG2WMHyAC
# url: jdbc:mysql://localhost:3306/cailiao?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
# username:
# password:
# oracle:
# type: ${spring.datasource.type}
# driverClassName: oracle.jdbc.OracleDriver
# url: jdbc:oracle:thin:@//localhost:1521/XE
# username: ROOT
# password: root
# postgres:
# type: ${spring.datasource.type}
# driverClassName: org.postgresql.Driver
# url: jdbc:postgresql://localhost:5432/postgres?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true
# username: root
# password: root
# sqlserver:
# type: ${spring.datasource.type}
# driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
# url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true
# username: SA
# password: root
hikari:
# 最大连接池数量
maxPoolSize: 20
# 最小空闲线程数量
minIdle: 10
# 配置获取连接等待超时的时间
connectionTimeout: 30000
# 校验超时时间
validationTimeout: 5000
# 空闲连接存活最大时间默认10分钟
idleTimeout: 600000
# 此属性控制池中连接的最长生命周期值0表示无限生命周期默认30分钟
maxLifetime: 1800000
# 多久检查一次连接的活性
keepaliveTime: 30000
--- # redis 单机配置(单机与集群只能开启一个另一个需要注释掉)
spring.data:
redis:
# 地址
host: localhost
# 端口默认为6379
port: 6379
# 数据库索引
database: 0
# redis 密码必须配置
password: Huitu123
# 连接超时时间
timeout: 10s
# 是否开启ssl
ssl.enabled: false
# redisson 配置
redisson:
# redis key前缀
keyPrefix:
# 线程池数量
threads: 16
# Netty线程池数量
nettyThreads: 32
# 单节点配置
singleServerConfig:
# 客户端名称
clientName: ${ruoyi.name}
# 最小空闲连接数
connectionMinimumIdleSize: 32
# 连接池大小
connectionPoolSize: 64
# 连接空闲超时,单位:毫秒
idleConnectionTimeout: 10000
# 命令等待超时,单位:毫秒
timeout: 3000
# 发布和订阅连接池大小
subscriptionConnectionPoolSize: 50
--- # mail 邮件发送
mail:
enabled: false
host: smtp.163.com
port: 465
# 是否需要用户名密码验证
auth: true
# 发送方遵循RFC-822标准
from: xxx@163.com
# 用户名注意如果使用foxmail邮箱此处user为qq号
user: xxx@163.com
# 密码注意某些邮箱需要为SMTP服务单独设置密码详情查看相关帮助
pass: xxxxxxxxxx
# 使用 STARTTLS安全连接STARTTLS是对纯文本通信协议的扩展。
starttlsEnable: true
# 使用SSL安全连接
sslEnable: true
# SMTP超时时长单位毫秒缺省值不超时
timeout: 0
# Socket连接超时值单位毫秒缺省值不超时
connectionTimeout: 0
--- # sms 短信 支持 阿里云 腾讯云 云片 等等各式各样的短信服务商
# https://sms4j.com/doc3/ 差异配置文档地址 支持单厂商多配置,可以配置多个同时使用
sms:
# 配置源类型用于标定配置来源(interface,yaml)
config-type: yaml
# 用于标定yml中的配置是否开启短信拦截接口配置不受此限制
restricted: true
# 短信拦截限制单手机号每分钟最大发送,只对开启了拦截的配置有效
minute-max: 1
# 短信拦截限制单手机号每日最大发送量,只对开启了拦截的配置有效
account-max: 30
# 以下配置来自于 org.dromara.sms4j.provider.config.BaseConfig类中
blends:
# 唯一ID 用于发送短信寻找具体配置 随便定义别用中文即可
# 可以同时存在两个相同厂商 例如: ali1 ali2 两个不同的阿里短信账号 也可用于区分租户
config1:
# 框架定义的厂商名称标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分
supplier: alibaba
# 有些称为accessKey有些称之为apiKey也有称为sdkKey或者appId。
access-key-id: 您的accessKey
# 称为accessSecret有些称之为apiSecret
access-key-secret: 您的accessKeySecret
signature: 您的短信签名
sdk-app-id: 您的sdkAppId
config2:
# 厂商标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分
supplier: tencent
access-key-id: 您的accessKey
access-key-secret: 您的accessKeySecret
signature: 您的短信签名
sdk-app-id: 您的sdkAppId
--- # 三方授权
justauth:
# 前端外网访问地址
address: http://localhost:80
type:
maxkey:
# maxkey 服务器地址
# 注意 如下均配置均不需要修改 maxkey 已经内置好了数据
server-url: http://sso.maxkey.top
client-id: 876892492581044224
client-secret: x1Y5MTMwNzIwMjMxNTM4NDc3Mzche8
redirect-uri: ${justauth.address}/social-callback?source=maxkey
topiam:
# topiam 服务器地址
server-url: http://127.0.0.1:1989/api/v1/authorize/y0q************spq***********8ol
client-id: 449c4*********937************759
client-secret: ac7***********1e0************28d
redirect-uri: ${justauth.address}/social-callback?source=topiam
scopes: [ openid, email, phone, profile ]
qq:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=qq
union-id: false
weibo:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=weibo
gitee:
client-id: 91436b7940090d09c72c7daf85b959cfd5f215d67eea73acbf61b6b590751a98
client-secret: 02c6fcfd70342980cd8dd2f2c06c1a350645d76c754d7a264c4e125f9ba915ac
redirect-uri: ${justauth.address}/social-callback?source=gitee
dingtalk:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=dingtalk
baidu:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=baidu
csdn:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=csdn
coding:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=coding
coding-group-name: xx
oschina:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=oschina
alipay_wallet:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=alipay_wallet
alipay-public-key: MIIB**************DAQAB
wechat_open:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=wechat_open
wechat_mp:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=wechat_mp
wechat_enterprise:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=wechat_enterprise
agent-id: 1000002
gitlab:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=gitlab

View File

@@ -0,0 +1,286 @@
# 项目相关配置
ruoyi:
# 名称
name: CaiLiao-APP
# 版本
version: ${revision}
# 版权年份
copyrightYear: 2024
captcha:
enable: true
# 页面 <参数设置> 可开启关闭 验证码校验
# 验证码类型 math 数组计算 char 字符验证
type: MATH
# line 线段干扰 circle 圆圈干扰 shear 扭曲干扰
category: CIRCLE
# 数字验证码位数
numberLength: 1
# 字符验证码长度
charLength: 4
# 开发环境配置
server:
# 服务器的HTTP端口默认为8090
port: 8090
servlet:
# 应用的访问路径
context-path: /
# undertow 配置
undertow:
# HTTP post内容的最大大小。当值为-1时默认值为大小是无限的
max-http-post-size: -1
# 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
# 每块buffer的空间大小,越小的空间被利用越充分
buffer-size: 512
# 是否分配的直接内存
direct-buffers: true
threads:
# 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程
io: 8
# 阻塞任务线程池, 当执行类似servlet请求阻塞操作, undertow会从这个线程池中取得线程,它的值设置取决于系统的负载
worker: 256
# 日志配置
logging:
level:
org.dromara: @logging.level@
org.springframework: warn
org.mybatis.spring.mapper: error
config: classpath:logback-plus.xml
# 用户配置
user:
password:
# 密码最大错误次数
maxRetryCount: 5
# 密码锁定时间默认10分钟
lockTime: 10
# Spring配置
spring:
application:
name: ${ruoyi.name}
threads:
# 开启虚拟线程 仅jdk21可用
virtual:
enabled: false
# 资源信息
messages:
# 国际化资源文件路径
basename: i18n/messages
profiles:
active: @profiles.active@
# 文件上传
servlet:
multipart:
# 单个文件大小
max-file-size: 10MB
# 设置总上传的文件大小
max-request-size: 20MB
mvc:
# 设置静态资源路径 防止所有请求都去查静态资源
static-path-pattern: /static/**
format:
date-time: yyyy-MM-dd HH:mm:ss
jackson:
# 日期格式化
date-format: yyyy-MM-dd HH:mm:ss
serialization:
# 格式化输出
indent_output: false
# 忽略无法转换的对象
fail_on_empty_beans: false
deserialization:
# 允许对象忽略json中不存在的属性
fail_on_unknown_properties: false
# Sa-Token配置
sa-token:
# token名称 (同时也是cookie名称)
token-name: Authorization
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
is-share: false
# jwt秘钥
jwt-secret-key: abcdefghijklmnopqrstuvwxyz
# security配置
security:
# 排除路径
excludes:
# 静态资源
- /*.html
- /**/*.html
- /**/*.css
- /**/*.js
# 公共路径
- /favicon.ico
- /error
# swagger 文档配置
- /*/api-docs
- /*/api-docs/**
# actuator 监控配置
- /actuator
- /actuator/**
- /api/mall/**
# 多租户配置
tenant:
# 是否开启
enable: false
# 排除表
excludes:
- sys_menu
- sys_tenant
- sys_tenant_package
- sys_role_dept
- sys_role_menu
- sys_user_post
- sys_user_role
- sys_client
- sys_oss_config
# MyBatisPlus配置
# https://baomidou.com/config/
mybatis-plus:
# 多包名使用 例如 org.dromara.**.mapper,org.xxx.**.mapper
mapperPackage: org.dromara.**.mapper
# 对应的 XML 文件位置
mapperLocations: classpath*:mapper/**/*Mapper.xml
# 实体扫描多个package用逗号或者分号分隔
typeAliasesPackage: org.dromara.**.domain
global-config:
dbConfig:
# 主键类型
# AUTO 自增 NONE 空 INPUT 用户输入 ASSIGN_ID 雪花 ASSIGN_UUID 唯一 UUID
# 如需改为自增 需要将数据库表全部设置为自增
idType: AUTO
# 数据加密
mybatis-encryptor:
# 是否开启加密
enable: false
# 默认加密算法
algorithm: BASE64
# 编码方式 BASE64/HEX。默认BASE64
encode: BASE64
# 安全秘钥 对称算法的秘钥 如AESSM4
password:
# 公私钥 非对称算法的公私钥 如SM2RSA
publicKey:
privateKey:
# api接口加密
api-decrypt:
# 是否开启全局接口加密
enabled: true
# AES 加密头标识
headerFlag: encrypt-key
# 响应加密公钥 非对称算法的公私钥 如SM2RSA 使用者请自行更换
# 对应前端解密私钥 MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAmc3CuPiGL/LcIIm7zryCEIbl1SPzBkr75E2VMtxegyZ1lYRD+7TZGAPkvIsBcaMs6Nsy0L78n2qh+lIZMpLH8wIDAQABAkEAk82Mhz0tlv6IVCyIcw/s3f0E+WLmtPFyR9/WtV3Y5aaejUkU60JpX4m5xNR2VaqOLTZAYjW8Wy0aXr3zYIhhQQIhAMfqR9oFdYw1J9SsNc+CrhugAvKTi0+BF6VoL6psWhvbAiEAxPPNTmrkmrXwdm/pQQu3UOQmc2vCZ5tiKpW10CgJi8kCIFGkL6utxw93Ncj4exE/gPLvKcT+1Emnoox+O9kRXss5AiAMtYLJDaLEzPrAWcZeeSgSIzbL+ecokmFKSDDcRske6QIgSMkHedwND1olF8vlKsJUGK3BcdtM8w4Xq7BpSBwsloE=
publicKey: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJnNwrj4hi/y3CCJu868ghCG5dUj8wZK++RNlTLcXoMmdZWEQ/u02RgD5LyLAXGjLOjbMtC+/J9qofpSGTKSx/MCAwEAAQ==
# 请求解密私钥 非对称算法的公私钥 如SM2RSA 使用者请自行更换
# 对应前端加密公钥 MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ==
privateKey: MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKNPuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gAkM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWowcSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99EcvDQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthhYhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3UP8iWi1Qw0Y=
springdoc:
api-docs:
# 是否开启接口文档
enabled: true
# swagger-ui:
# # 持久化认证数据
# persistAuthorization: true
info:
# 标题
title: '标题:${ruoyi.name}商城前端系统_接口文档'
# 描述
description: '描述:商城小程序前端接口文档'
# 版本
version: '版本号: ${ruoyi.version}'
# 作者信息
contact:
name: Maosw
email: 136767481@qq.com
components:
# 鉴权方式配置
security-schemes:
apiKey:
type: APIKEY
in: HEADER
name: ${sa-token.token-name}
#这里定义了两个分组,可定义多个,也可以不定义
group-configs:
- group: 1.App接口
packages-to-scan: org.dromara.web
# 防止XSS攻击
xss:
# 过滤开关
enabled: false
# 排除链接(多个用逗号分隔)
excludes: /system/notice
# 匹配链接
urlPatterns: /system/*,/monitor/*,/tool/*,/mall/*
# 全局线程池相关配置
# 如使用JDK21请直接使用虚拟线程 不要开启此配置
thread-pool:
# 是否开启线程池
enabled: false
# 队列最大长度
queueCapacity: 128
# 线程池维护线程所允许的空闲时间
keepAliveSeconds: 300
--- # 分布式锁 lock4j 全局配置
lock4j:
# 获取分布式锁超时时间,默认为 3000 毫秒
acquire-timeout: 3000
# 分布式锁的超时时间,默认为 30 秒
expire: 30000
--- # Actuator 监控端点的配置项
management:
endpoints:
web:
exposure:
include: '*'
endpoint:
health:
show-details: ALWAYS
logfile:
external-file: ./logs/sys-console.log
--- # websocket
websocket:
# 如果关闭 需要和前端开关一起关闭
enabled: true
# 路径
path: /resource/websocket
# 设置访问源地址
allowedOrigins: '*'
--- #flowable配置
flowable:
async-executor-activate: false #关闭定时任务JOB
# 将databaseSchemaUpdate设置为true。当Flowable发现库与数据库表结构不一致时会自动将数据库表结构升级至新版本。
database-schema-update: true
activity-font-name: 宋体
label-font-name: 宋体
annotation-font-name: 宋体
# 关闭各个模块生成表,目前只使用工作流基础表
idm:
enabled: false
cmmn:
enabled: false
dmn:
enabled: false
app:
enabled: false
# 企业微信配置
wx:
corpid: ${WX_CORPID:your_corpid}
corpsecret: ${WX_CORPSECRET:your_secret}

View File

@@ -0,0 +1,8 @@
Application Version: ${revision}
Spring Boot Version: ${spring-boot.version}
__________ _____.___.__ ____ ____ __________.__
\______ \__ __ ____\__ | |__| \ \ / /_ __ ____ \______ \ | __ __ ______
| _/ | \/ _ \/ | | | ______ \ Y / | \_/ __ \ ______ | ___/ | | | \/ ___/
| | \ | ( <_> )____ | | /_____/ \ /| | /\ ___/ /_____/ | | | |_| | /\___ \
|____|_ /____/ \____// ______|__| \___/ |____/ \___ > |____| |____/____//____ >
\/ \/ \/ \/

View File

@@ -0,0 +1,61 @@
#错误消息
not.null=* 必须填写
user.jcaptcha.error=验证码错误
user.jcaptcha.expire=验证码已失效
user.not.exists=对不起, 您的账号:{0} 不存在.
user.password.not.match=用户不存在/密码错误
user.password.retry.limit.count=密码输入错误{0}次
user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定{1}分钟
user.password.delete=对不起,您的账号:{0} 已被删除
user.blocked=对不起,您的账号:{0} 已禁用,请联系管理员
role.blocked=角色已封禁,请联系管理员
user.logout.success=退出成功
length.not.valid=长度必须在{min}到{max}个字符之间
user.username.not.blank=用户名不能为空
user.username.not.valid=* 2到20个汉字、字母、数字或下划线组成且必须以非数字开头
user.username.length.valid=账户长度必须在{min}到{max}个字符之间
user.password.not.blank=用户密码不能为空
user.password.length.valid=用户密码长度必须在{min}到{max}个字符之间
user.password.not.valid=* 5-50个字符
user.email.not.valid=邮箱格式错误
user.email.not.blank=邮箱不能为空
user.phonenumber.not.blank=用户手机号不能为空
user.mobile.phone.number.not.valid=手机号格式错误
user.login.success=登录成功
user.register.success=注册成功
user.register.save.error=保存用户 {0} 失败,注册账号已存在
user.register.error=注册失败,请联系系统管理人员
user.notfound=请重新登录
user.forcelogout=管理员强制退出,请重新登录
user.unknown.error=未知错误,请重新登录
auth.grant.type.error=认证权限类型错误
auth.grant.type.blocked=认证权限类型已禁用
auth.grant.type.not.blank=认证权限类型不能为空
auth.clientid.not.blank=认证客户端id不能为空
##文件上传消息
upload.exceed.maxSize=上传的文件大小超出限制的文件大小!<br/>允许的文件最大大小是:{0}MB
upload.filename.exceed.length=上传的文件名最长{0}个字符
##权限
no.permission=您没有数据的权限,请联系管理员添加权限 [{0}]
no.create.permission=您没有创建数据的权限,请联系管理员添加权限 [{0}]
no.update.permission=您没有修改数据的权限,请联系管理员添加权限 [{0}]
no.delete.permission=您没有删除数据的权限,请联系管理员添加权限 [{0}]
no.export.permission=您没有导出数据的权限,请联系管理员添加权限 [{0}]
no.view.permission=您没有查看数据的权限,请联系管理员添加权限 [{0}]
repeat.submit.message=不允许重复提交,请稍候再试
rate.limiter.message=访问过于频繁,请稍候再试
sms.code.not.blank=短信验证码不能为空
sms.code.retry.limit.count=短信验证码输入错误{0}次
sms.code.retry.limit.exceed=短信验证码输入错误{0}次,帐户锁定{1}分钟
email.code.not.blank=邮箱验证码不能为空
email.code.retry.limit.count=邮箱验证码输入错误{0}次
email.code.retry.limit.exceed=邮箱验证码输入错误{0}次,帐户锁定{1}分钟
xcx.code.not.blank=小程序[code]不能为空
social.source.not.blank=第三方登录平台[source]不能为空
social.code.not.blank=第三方登录平台[code]不能为空
social.state.not.blank=第三方登录平台[state]不能为空
##租户
tenant.number.not.blank=租户编号不能为空
tenant.not.exists=对不起, 您的租户不存在,请联系管理员
tenant.blocked=对不起,您的租户已禁用,请联系管理员
tenant.expired=对不起,您的租户已过期,请联系管理员

View File

@@ -0,0 +1,61 @@
#????
not.null=* Required fill in
user.jcaptcha.error=Captcha error
user.jcaptcha.expire=Captcha invalid
user.not.exists=Sorry, your account: {0} does not exist
user.password.not.match=User does not exist/Password error
user.password.retry.limit.count=Password input error {0} times
user.password.retry.limit.exceed=Password input error {0} times, account locked for {1} minutes
user.password.delete=Sorry, your account?{0} has been deleted
user.blocked=Sorry, your account: {0} has been disabled. Please contact the administrator
role.blocked=Role disabled?please contact administrators
user.logout.success=Exit successful
length.not.valid=The length must be between {min} and {max} characters
user.username.not.blank=Username cannot be blank
user.username.not.valid=* 2 to 20 chinese characters, letters, numbers or underscores, and must start with a non number
user.username.length.valid=Account length must be between {min} and {max} characters
user.password.not.blank=Password cannot be empty
user.password.length.valid=Password length must be between {min} and {max} characters
user.password.not.valid=* 5-50 characters
user.email.not.valid=Mailbox format error
user.email.not.blank=Mailbox cannot be blank
user.phonenumber.not.blank=Phone number cannot be blank
user.mobile.phone.number.not.valid=Phone number format error
user.login.success=Login successful
user.register.success=Register successful
user.register.save.error=Failed to save user {0}, The registered account already exists
user.register.error=Register failed, please contact system administrator
user.notfound=Please login again
user.forcelogout=The administrator is forced to exit?please login again
user.unknown.error=Unknown error, please login again
auth.grant.type.error=Auth grant type error
auth.grant.type.blocked=Auth grant type disabled
auth.grant.type.not.blank=Auth grant type cannot be blank
auth.clientid.not.blank=Auth clientid cannot be blank
##??????
upload.exceed.maxSize=The uploaded file size exceeds the limit file size?<br/>the maximum allowed file size is?{0}MB?
upload.filename.exceed.length=The maximum length of uploaded file name is {0} characters
##??
no.permission=You do not have permission to the data?please contact your administrator to add permissions [{0}]
no.create.permission=You do not have permission to create data?please contact your administrator to add permissions [{0}]
no.update.permission=You do not have permission to modify data?please contact your administrator to add permissions [{0}]
no.delete.permission=You do not have permission to delete data?please contact your administrator to add permissions [{0}]
no.export.permission=You do not have permission to export data?please contact your administrator to add permissions [{0}]
no.view.permission=You do not have permission to view data?please contact your administrator to add permissions [{0}]
repeat.submit.message=Repeat submit is not allowed, please try again later
rate.limiter.message=Visit too frequently, please try again later
sms.code.not.blank=Sms code cannot be blank
sms.code.retry.limit.count=Sms code input error {0} times
sms.code.retry.limit.exceed=Sms code input error {0} times, account locked for {1} minutes
email.code.not.blank=Email code cannot be blank
email.code.retry.limit.count=Email code input error {0} times
email.code.retry.limit.exceed=Email code input error {0} times, account locked for {1} minutes
xcx.code.not.blank=Mini program [code] cannot be blank
social.source.not.blank=Social login platform [source] cannot be blank
social.code.not.blank=Social login platform [code] cannot be blank
social.state.not.blank=Social login platform [state] cannot be blank
##??
tenant.number.not.blank=Tenant number cannot be blank
tenant.not.exists=Sorry, your tenant does not exist. Please contact the administrator
tenant.blocked=Sorry, your tenant is disabled. Please contact the administrator
tenant.expired=Sorry, your tenant has expired. Please contact the administrator.

View File

@@ -0,0 +1,61 @@
#错误消息
not.null=* 必须填写
user.jcaptcha.error=验证码错误
user.jcaptcha.expire=验证码已失效
user.not.exists=对不起, 您的账号:{0} 不存在.
user.password.not.match=用户不存在/密码错误
user.password.retry.limit.count=密码输入错误{0}次
user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定{1}分钟
user.password.delete=对不起,您的账号:{0} 已被删除
user.blocked=对不起,您的账号:{0} 已禁用,请联系管理员
role.blocked=角色已封禁,请联系管理员
user.logout.success=退出成功
length.not.valid=长度必须在{min}到{max}个字符之间
user.username.not.blank=用户名不能为空
user.username.not.valid=* 2到20个汉字、字母、数字或下划线组成且必须以非数字开头
user.username.length.valid=账户长度必须在{min}到{max}个字符之间
user.password.not.blank=用户密码不能为空
user.password.length.valid=用户密码长度必须在{min}到{max}个字符之间
user.password.not.valid=* 5-50个字符
user.email.not.valid=邮箱格式错误
user.email.not.blank=邮箱不能为空
user.phonenumber.not.blank=用户手机号不能为空
user.mobile.phone.number.not.valid=手机号格式错误
user.login.success=登录成功
user.register.success=注册成功
user.register.save.error=保存用户 {0} 失败,注册账号已存在
user.register.error=注册失败,请联系系统管理人员
user.notfound=请重新登录
user.forcelogout=管理员强制退出,请重新登录
user.unknown.error=未知错误,请重新登录
auth.grant.type.error=认证权限类型错误
auth.grant.type.blocked=认证权限类型已禁用
auth.grant.type.not.blank=认证权限类型不能为空
auth.clientid.not.blank=认证客户端id不能为空
##文件上传消息
upload.exceed.maxSize=上传的文件大小超出限制的文件大小!<br/>允许的文件最大大小是:{0}MB
upload.filename.exceed.length=上传的文件名最长{0}个字符
##权限
no.permission=您没有数据的权限,请联系管理员添加权限 [{0}]
no.create.permission=您没有创建数据的权限,请联系管理员添加权限 [{0}]
no.update.permission=您没有修改数据的权限,请联系管理员添加权限 [{0}]
no.delete.permission=您没有删除数据的权限,请联系管理员添加权限 [{0}]
no.export.permission=您没有导出数据的权限,请联系管理员添加权限 [{0}]
no.view.permission=您没有查看数据的权限,请联系管理员添加权限 [{0}]
repeat.submit.message=不允许重复提交,请稍候再试
rate.limiter.message=访问过于频繁,请稍候再试
sms.code.not.blank=短信验证码不能为空
sms.code.retry.limit.count=短信验证码输入错误{0}次
sms.code.retry.limit.exceed=短信验证码输入错误{0}次,帐户锁定{1}分钟
email.code.not.blank=邮箱验证码不能为空
email.code.retry.limit.count=邮箱验证码输入错误{0}次
email.code.retry.limit.exceed=邮箱验证码输入错误{0}次,帐户锁定{1}分钟
xcx.code.not.blank=小程序[code]不能为空
social.source.not.blank=第三方登录平台[source]不能为空
social.code.not.blank=第三方登录平台[code]不能为空
social.state.not.blank=第三方登录平台[state]不能为空
##租户
tenant.number.not.blank=租户编号不能为空
tenant.not.exists=对不起, 您的租户不存在,请联系管理员
tenant.blocked=对不起,您的租户已禁用,请联系管理员
tenant.expired=对不起,您的租户已过期,请联系管理员

Binary file not shown.

View File

@@ -0,0 +1,129 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="log.path" value="./logs"/>
<property name="console.log.pattern"
value="%red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}%n) - %msg%n"/>
<property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"/>
<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${console.log.pattern}</pattern>
<charset>utf-8</charset>
</encoder>
</appender>
<!-- 控制台输出 -->
<appender name="file_console" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-console.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/sys-console.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大 1天 -->
<maxHistory>1</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
<charset>utf-8</charset>
</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<!-- 过滤的级别 -->
<level>INFO</level>
</filter>
</appender>
<!-- 系统日志输出 -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-info.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>INFO</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-error.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>ERROR</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- info异步输出 -->
<appender name="async_info" class="ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>512</queueSize>
<!-- 添加附加的appender,最多只能添加一个 -->
<appender-ref ref="file_info"/>
</appender>
<!-- error异步输出 -->
<appender name="async_error" class="ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>512</queueSize>
<!-- 添加附加的appender,最多只能添加一个 -->
<appender-ref ref="file_error"/>
</appender>
<!-- 整合 skywalking 控制台输出 tid -->
<!-- <appender name="console" class="ch.qos.logback.core.ConsoleAppender">-->
<!-- <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">-->
<!-- <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">-->
<!-- <pattern>[%tid] ${console.log.pattern}</pattern>-->
<!-- </layout>-->
<!-- <charset>utf-8</charset>-->
<!-- </encoder>-->
<!-- </appender>-->
<!-- 整合 skywalking 推送采集日志 -->
<!-- <appender name="sky_log" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">-->
<!-- <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">-->
<!-- <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">-->
<!-- <pattern>[%tid] ${console.log.pattern}</pattern>-->
<!-- </layout>-->
<!-- <charset>utf-8</charset>-->
<!-- </encoder>-->
<!-- </appender>-->
<!--系统操作日志-->
<root level="info">
<appender-ref ref="console" />
<appender-ref ref="async_info" />
<appender-ref ref="async_error" />
<appender-ref ref="file_console" />
<!-- <appender-ref ref="sky_log"/>-->
</root>
</configuration>

View File

@@ -0,0 +1,45 @@
package org.dromara.test;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
/**
* 断言单元测试案例
*
* @author Lion Li
*/
@DisplayName("断言单元测试案例")
public class AssertUnitTest {
@DisplayName("测试 assertEquals 方法")
@Test
public void testAssertEquals() {
Assertions.assertEquals("666", new String("666"));
Assertions.assertNotEquals("666", new String("666"));
}
@DisplayName("测试 assertSame 方法")
@Test
public void testAssertSame() {
Object obj = new Object();
Object obj1 = obj;
Assertions.assertSame(obj, obj1);
Assertions.assertNotSame(obj, obj1);
}
@DisplayName("测试 assertTrue 方法")
@Test
public void testAssertTrue() {
Assertions.assertTrue(true);
Assertions.assertFalse(true);
}
@DisplayName("测试 assertNull 方法")
@Test
public void testAssertNull() {
Assertions.assertNull(null);
Assertions.assertNotNull(null);
}
}

View File

@@ -0,0 +1,72 @@
package org.dromara.test;
import org.dromara.common.core.enums.UserType;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.NullSource;
import org.junit.jupiter.params.provider.ValueSource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
/**
* 带参数单元测试案例
*
* @author Lion Li
*/
@DisplayName("带参数单元测试案例")
public class ParamUnitTest {
@DisplayName("测试 @ValueSource 注解")
@ParameterizedTest
@ValueSource(strings = {"t1", "t2", "t3"})
public void testValueSource(String str) {
System.out.println(str);
}
@DisplayName("测试 @NullSource 注解")
@ParameterizedTest
@NullSource
public void testNullSource(String str) {
System.out.println(str);
}
@DisplayName("测试 @EnumSource 注解")
@ParameterizedTest
@EnumSource(UserType.class)
public void testEnumSource(UserType type) {
System.out.println(type.getUserType());
}
@DisplayName("测试 @MethodSource 注解")
@ParameterizedTest
@MethodSource("getParam")
public void testMethodSource(String str) {
System.out.println(str);
}
public static Stream<String> getParam() {
List<String> list = new ArrayList<>();
list.add("t1");
list.add("t2");
list.add("t3");
return list.stream();
}
@BeforeEach
public void testBeforeEach() {
System.out.println("@BeforeEach ==================");
}
@AfterEach
public void testAfterEach() {
System.out.println("@AfterEach ==================");
}
}

View File

@@ -0,0 +1,54 @@
package org.dromara.test;
import org.junit.jupiter.api.*;
import org.springframework.boot.test.context.SpringBootTest;
/**
* 标签单元测试案例
*
* @author Lion Li
*/
@SpringBootTest
@DisplayName("标签单元测试案例")
public class TagUnitTest {
@Tag("dev")
@DisplayName("测试 @Tag dev")
@Test
public void testTagDev() {
System.out.println("dev");
}
@Tag("prod")
@DisplayName("测试 @Tag prod")
@Test
public void testTagProd() {
System.out.println("prod");
}
@Tag("local")
@DisplayName("测试 @Tag local")
@Test
public void testTagLocal() {
System.out.println("local");
}
@Tag("exclude")
@DisplayName("测试 @Tag exclude")
@Test
public void testTagExclude() {
System.out.println("exclude");
}
@BeforeEach
public void testBeforeEach() {
System.out.println("@BeforeEach ==================");
}
@AfterEach
public void testAfterEach() {
System.out.println("@AfterEach ==================");
}
}