diff --git a/backend.txt b/backend.txt new file mode 100644 index 0000000..555cff4 --- /dev/null +++ b/backend.txt @@ -0,0 +1,67364 @@ +--- File: .gitignore --- +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +target +.idea +*.iml +nb-configuration.xml +nbactions.xml +.project +.settings +*/.settings +*/.project +.classpath +*/.idea +.idea/ +.vscode/ +.settings/ +target/ +ideaproj/ +*/bin +.DS_Store +*.ipr +*.iws +bin/ +nbproject/ +.springBeans +/log/ +/logs/ +/storage/ +/var/log/* +*.factorypath +/storage/ + +--- File: README.md --- +# PeiPei 后端项目 + +基于 Spring Boot 的多模块项目,为 PeiPei 应用提供后端服务。 + +## 项目结构 + +- **play-admin**: 主要的 Spring Boot 应用模块 +- **play-common**: 公共工具类和共享代码 +- **play-generator**: 代码生成工具 + +## 构建要求 + +- **Java 11** (必须) +- **Maven 3.6+** + +## 快速开始 + +### 1. 安装 Java 11 + +在 macOS 上使用 Homebrew: +```bash +brew install --cask zulu@11 +``` + +设置 Java 11 为默认版本: + +#### 临时设置 (当前会话): +```bash +export JAVA_HOME=$(/usr/libexec/java_home -v 11) +``` + +#### 永久设置方法: + +**方法1: Shell 配置 (推荐)** +添加到 `~/.zshrc` 或 `~/.bash_profile`: +```bash +export JAVA_HOME=$(/usr/libexec/java_home -v 11) +export PATH="$JAVA_HOME/bin:$PATH" +``` + +**方法2: Maven 专用** +创建 `~/.mavenrc`: +```bash +export JAVA_HOME=$(/usr/libexec/java_home -v 11) +``` + +**方法3: VS Code 项目配置** +项目已配置 `.vscode/settings.json` 使用 Java 11: +```json +{ + "java.configuration.runtimes": [ + { + "name": "JavaSE-11", + "path": "/usr/libexec/java_home -v 11" + } + ], + "java.jdt.ls.java.home": "/usr/libexec/java_home -v 11" +} +``` + +### 2. 构建项目 + +```bash +# 清理并构建所有模块 +mvn clean install + +# 或者仅编译 +mvn clean compile +``` + +### 3. 运行应用 + +```bash +# 运行主应用 +java -jar play-admin/target/play-admin-1.0.jar + +# 或使用 Maven +cd play-admin +mvn spring-boot:run +``` + +## 配置说明 + +项目在所有模块中统一使用 Java 11: +- 所有模块都配置为 Java 11 源码和目标版本 +- Lombok 注解自动处理 +- 无需显式配置注解处理器 + +## 开发说明 + +- 项目已更新为所有模块统一使用 Java 11 +- Lombok 依赖使用 `scope=provided` 启用自动注解处理 +- Maven 编译插件继承 Spring Boot 父 POM 配置 + +### 代码格式化和质量检查 + +项目集成了 Spotless 和 Checkstyle 插件: + +#### Spotless (代码格式化) +- 基于空格的缩进 (4个空格) +- 自动清理尾随空白字符 +- 文件末尾添加换行符 +- 基本的导入组织 + +常用命令: +```bash +# 检查代码格式 +mvn spotless:check + +# 自动格式化代码 +mvn spotless:apply +``` + +#### Checkstyle (代码规范检查) +- 使用 Sun Java 编码规范 (比 Google 规范更宽松) +- 在编译时自动检查代码规范 +- 与 Java 11 和 Lombok 兼容 + +常用命令: +```bash +# 检查代码规范 +mvn checkstyle:check + +# 生成规范检查报告 +mvn checkstyle:checkstyle +``` + +#### 集成命令 +```bash +# 格式化代码并编译 +mvn spotless:apply compile + +# 完整检查 (格式化 + 规范检查 + 编译) +mvn spotless:apply checkstyle:check compile +``` + +## 模块介绍 + +### play-admin +主要的 Spring Boot 应用,包含: +- REST API 接口 +- 安全配置 +- 数据库集成 +- 微信集成 + +### play-common +共享工具库,包含: +- 公共域对象 +- 工具类 +- Redis 配置 +- 安全工具 + +### play-generator +代码生成工具,包含: +- MyBatis Plus 代码生成 +- 基于模板的代码生成 + +## 故障排除 + +### 常见问题 + +**编译失败: "cannot find symbol" 错误** +- 确保使用 Java 11: `java -version` 应显示 Java 11 +- 设置正确的 JAVA_HOME: `export JAVA_HOME=$(/usr/libexec/java_home -v 11)` +- 清理并重新编译: `mvn clean compile` + +**Maven 使用错误的 Java 版本** +- 检查 Maven 版本: `mvn -version` +- 创建 `~/.mavenrc` 文件设置 JAVA_HOME +- 或在命令前加环境变量: `JAVA_HOME=$(/usr/libexec/java_home -v 11) mvn clean compile` + +**VS Code Java 支持问题** +- 确保安装了 Extension Pack for Java +- 检查 `.vscode/settings.json` 中的 Java 配置 +- 重新加载窗口: Cmd+Shift+P → "Developer: Reload Window" + +**Spotless 格式化问题** +- 修复格式问题: `mvn spotless:apply` +- 跳过格式检查: `mvn compile -Dspotless.check.skip=true` + +### 验证配置 +```bash +# 验证 Java 版本 +java -version + +# 验证 Maven Java 版本 +mvn -version + +# 验证编译 +mvn clean compile + +# 验证完整构建 +mvn clean install +``` + +## 构建状态 + +✅ 所有模块使用 Java 11 编译成功 +✅ Lombok 注解自动处理 +✅ 模块间配置一致 +✅ Spotless 代码格式化已配置 +✅ Checkstyle 代码规范检查已配置 +✅ VS Code Java 配置已设置 + +--- File: deploy.sh --- +#!/bin/sh +# 发包脚本 +set -e +echo "发布开始,当前时间是:$current_time" +#mvn clean install +scp ./play-admin/target/play-admin-1.0.jar root@122.51.20.105:/www/wwwroot/july.hucs.top +ssh root@122.51.20.105 "source /etc/profile;cd /www/wwwroot/july.hucs.top;sh start.sh restart" +# 获取当前时间并格式化为指定格式 +current_time=$(date +"%Y-%m-%d %H:%M:%S") + +echo "发布完成,当前时间是:$current_time" + +--- File: docker/Dockerfile --- +FROM openjdk:11-jre-slim + +# 设置工作目录 +WORKDIR /app + +# 只复制应用程序JAR包,不复制lib目录 +COPY ./*.jar app.jar + +# 设置环境变量 +ENV APP_NAME=app.jar + +# 暴露应用端口 +EXPOSE 8080 + +# 设置启动命令 +CMD ["sh", "-c", "java -Dloader.path=./lib/ -Xms2g -Xmx2g -jar $APP_NAME --spring.profiles.active=test"] + + +--- File: docker/docker-compose.yml --- +version: '3' + +services: + spring-boot-app: + build: . + container_name: spring-boot-app + ports: + - "7003:7002" + volumes: + - ./lib:/app/lib # 挂载主机的lib目录到容器内的lib目录 + - ./log:/app/log # 挂载日志目录到主机 + restart: always + + +--- File: fetch-log.sh --- +#!/bin/sh +# 拉取日志脚本 +set -e + +# 获取当前时间并格式化为指定格式 +current_time=$(date +"%Y-%m-%d %H:%M:%S") +echo "开始拉取日志,当前时间是:$current_time" + +# 创建本地log目录(如果不存在) +mkdir -p ./log + +# 从远程服务器拉取整个log文件夹 +echo "正在从远程服务器拉取日志文件..." +scp -r root@122.51.20.105:/www/wwwroot/july.hucs.top/log/* ./log/ + +# 获取当前时间并格式化为指定格式 +current_time=$(date +"%Y-%m-%d %H:%M:%S") +echo "日志拉取完成,当前时间是:$current_time" + +--- File: play-admin/pom.xml --- + + + 4.0.0 + + com.starry + play-with + 1.0 + + + play-admin + + + 11 + 11 + 11 + UTF-8 + + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.flywaydb + flyway-core + + + + com.starry + play-common + 1.0 + + + + com.starry + play-generator + + + + + + io.jsonwebtoken + jjwt + + + + mysql + mysql-connector-java + 8.0.26 + + + com.github.yulichang + mybatis-plus-join-boot-starter + + + + com.alibaba + easyexcel + + + + org.springframework.boot + spring-boot-starter-aop + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + com.aliyun.oss + aliyun-sdk-oss + + + + com.github.binarywang + wx-java-mp-spring-boot-starter + + + com.github.wxpay + wxpay-sdk + + + + + ws.schild + jave-core + + + + ws.schild + jave-nativebin-linux64 + + + + com.github.binarywang + weixin-java-pay + 4.5.0 + + + + com.squareup.okio + okio + + + + com.tencentcloudapi + tencentcloud-sdk-java-dnspod + 3.1.322 + + + okio + com.squareup.okio + + + + + + + org.projectlombok + lombok + provided + + + + org.projectlombok + lombok-mapstruct-binding + 0.2.0 + + + + + + ruoyi-admin-mrwho + + + org.apache.maven.plugins + maven-compiler-plugin + + + + org.projectlombok + lombok + 1.18.30 + + + + + + org.flywaydb + flyway-maven-plugin + 7.15.0 + + + org.springframework.boot + spring-boot-maven-plugin + 2.7.9 + + ZIP + + + nothing + nothing + + + + + + + repackage + + + + + + + + +--- File: play-admin/src/main/java/com/starry/admin/Application.java --- +package com.starry.admin; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +/** + * @author admin + */ +@EnableTransactionManagement +@SpringBootApplication +@EnableScheduling +@ComponentScan("com.starry") +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/common/aspect/ClerkUserLogin.java --- +package com.starry.admin.common.aspect; + +import java.lang.annotation.*; + +/** + * 陪聊登录注解 + * + * @author ruoyi + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface ClerkUserLogin { + + boolean manage() default false; +} + + +--- File: play-admin/src/main/java/com/starry/admin/common/aspect/ClerkUserLoginAspect.java --- +package com.starry.admin.common.aspect; + +import com.starry.admin.common.conf.ThreadLocalRequestDetail; +import com.starry.admin.common.exception.ServiceException; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity; +import com.starry.admin.modules.clerk.service.impl.PlayClerkUserInfoServiceImpl; +import com.starry.admin.modules.weichat.service.WxTokenService; +import com.starry.common.constant.Constants; +import com.starry.common.constant.HttpStatus; +import com.starry.common.utils.StringUtils; +import java.util.Objects; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.springframework.stereotype.Component; + +/** + * 限流处理 + * + * @author ruoyi + */ +@Slf4j +@Aspect +@Component +public class ClerkUserLoginAspect { + + @Resource + private PlayClerkUserInfoServiceImpl clerkUserInfoService; + + @Resource + private WxTokenService tokenService; + @Resource + private HttpServletRequest request; + + @Before("@annotation(clerkUserLogin)") + public void doBefore(JoinPoint point, ClerkUserLogin clerkUserLogin) { + String userToken = request.getHeader(Constants.CLERK_USER_LOGIN_TOKEN); + if (StringUtils.isEmpty(userToken)) { + throw new ServiceException("token为空", HttpStatus.UNAUTHORIZED); + } + if (userToken.startsWith(Constants.TOKEN_PREFIX)) { + userToken = userToken.replace(Constants.TOKEN_PREFIX, ""); + } + // 解析token + String userId; + try { + userId = tokenService.getWxUserIdByToken(userToken); + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new ServiceException("获取用户信息异常", HttpStatus.UNAUTHORIZED); + } + PlayClerkUserInfoEntity entity = clerkUserInfoService.selectById(userId); + if (Objects.isNull(entity)) { + throw new ServiceException("未查询到有效用户", HttpStatus.UNAUTHORIZED); + } + if (!userToken.equals(entity.getToken())) { + throw new ServiceException("token异常", HttpStatus.UNAUTHORIZED); + } + ThreadLocalRequestDetail.setRequestDetail(entity); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/common/aspect/CustomUserLogin.java --- +package com.starry.admin.common.aspect; + +import java.lang.annotation.*; + +/** + * 客户登录注解 + * + * @author ruoyi + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface CustomUserLogin { + + boolean manage() default false; +} + + +--- File: play-admin/src/main/java/com/starry/admin/common/aspect/CustomUserLoginAspect.java --- +package com.starry.admin.common.aspect; + +import com.starry.admin.common.conf.ThreadLocalRequestDetail; +import com.starry.admin.common.exception.ServiceException; +import com.starry.admin.modules.custom.module.entity.PlayCustomUserInfoEntity; +import com.starry.admin.modules.custom.service.impl.PlayCustomUserInfoServiceImpl; +import com.starry.admin.modules.weichat.service.WxTokenService; +import com.starry.common.constant.Constants; +import com.starry.common.constant.HttpStatus; +import com.starry.common.utils.StringUtils; +import java.util.Objects; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.springframework.stereotype.Component; + +/** + * 限流处理 + * + * @author ruoyi + */ +@Slf4j +@Aspect +@Component +public class CustomUserLoginAspect { + + @Resource + private PlayCustomUserInfoServiceImpl customUserInfoService; + + @Resource + private WxTokenService tokenService; + @Resource + private HttpServletRequest request; + + @Before("@annotation(customUserLogin)") + public void doBefore(JoinPoint point, CustomUserLogin customUserLogin) { + String userToken = request.getHeader(Constants.CUSTOM_USER_LOGIN_TOKEN); + if (StringUtils.isEmpty(userToken)) { + throw new ServiceException("token为空", HttpStatus.UNAUTHORIZED); + } + if (userToken.startsWith(Constants.TOKEN_PREFIX)) { + userToken = userToken.replace(Constants.TOKEN_PREFIX, ""); + } + // 解析token + String userId; + try { + userId = tokenService.getWxUserIdByToken(userToken); + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new ServiceException("获取用户信息异常", HttpStatus.UNAUTHORIZED); + } + PlayCustomUserInfoEntity entity = customUserInfoService.selectById(userId); + if (Objects.isNull(entity)) { + throw new ServiceException("未查询到有效用户", HttpStatus.UNAUTHORIZED); + } + if (!userToken.equals(entity.getToken())) { + throw new ServiceException("token异常", HttpStatus.UNAUTHORIZED); + } + ThreadLocalRequestDetail.setRequestDetail(entity); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/common/aspect/DataScopeAspect.java --- +package com.starry.admin.common.aspect; + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.StrUtil; +import com.starry.admin.common.domain.LoginUser; +import com.starry.admin.modules.system.module.entity.SysRoleEntity; +import com.starry.admin.modules.system.module.entity.SysUserEntity; +import com.starry.admin.utils.SecurityUtils; +import com.starry.common.annotation.DataScope; +import com.starry.common.context.CustomSecurityContextHolder; +import com.starry.common.domain.BaseEntity; +import com.starry.common.utils.StringUtils; +import java.util.ArrayList; +import java.util.List; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.springframework.stereotype.Component; + +/** + * 数据过滤处理 + * + * @author vctgo + */ +@Aspect +@Component +public class DataScopeAspect { + /** + * 全部数据权限 + */ + public static final String DATA_SCOPE_ALL = "1"; + + /** + * 自定数据权限 + */ + public static final String DATA_SCOPE_CUSTOM = "2"; + + /** + * 部门数据权限 + */ + public static final String DATA_SCOPE_DEPT = "3"; + + /** + * 部门及以下数据权限 + */ + public static final String DATA_SCOPE_DEPT_AND_CHILD = "4"; + + /** + * 仅本人数据权限 + */ + public static final String DATA_SCOPE_SELF = "5"; + + /** + * 数据权限过滤关键字 + */ + public static final String DATA_SCOPE = "dataScope"; + + /** + * 数据范围过滤 + * + * @param joinPoint + * 切点 + * @param user + * 用户 + * @param deptAlias + * 部门别名 + * @param userAlias + * 用户别名 + * @param permission + * 权限字符 + */ + public static void dataScopeFilter(JoinPoint joinPoint, SysUserEntity user, String deptAlias, String userAlias, + String permission) { + StringBuilder sqlString = new StringBuilder(); + List conditions = new ArrayList<>(); + for (SysRoleEntity role : user.getRoles()) { + String dataScope = role.getDataScope(); + if (!DATA_SCOPE_CUSTOM.equals(dataScope) && conditions.contains(dataScope)) { + continue; + } + if (StrUtil.isNotBlank(permission) && StringUtils.isNotEmpty(role.getPermissions()) + && !StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission))) { + continue; + } + if (DATA_SCOPE_ALL.equals(dataScope)) { + sqlString = new StringBuilder(); + break; + } else if (DATA_SCOPE_CUSTOM.equals(dataScope)) { + sqlString.append(StringUtils.format( + " OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias, + role.getRoleId())); + } else if (DATA_SCOPE_DEPT.equals(dataScope)) { + sqlString.append(StringUtils.format(" OR {}.dept_id = {} ", deptAlias, user.getDeptId())); + } else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) { + sqlString.append(StringUtils.format( + " OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )", + deptAlias, user.getDeptId(), user.getDeptId())); + } else if (DATA_SCOPE_SELF.equals(dataScope)) { + if (StringUtils.isNotBlank(userAlias)) { + sqlString.append(StringUtils.format(" OR {}.user_id = {} ", userAlias, user.getUserId())); + } else { + // 数据权限为仅本人且没有userAlias别名不查询任何数据 + sqlString.append(StringUtils.format(" OR {}.dept_id = 0 ", deptAlias)); + } + } + conditions.add(dataScope); + } + + if (StringUtils.isNotBlank(sqlString.toString())) { + Object params = joinPoint.getArgs()[0]; + if (StringUtils.isNotNull(params) && params instanceof BaseEntity) { + BaseEntity baseEntity = (BaseEntity) params; + baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")"); + } + } + } + + @Before("@annotation(controllerDataScope)") + public void doBefore(JoinPoint point, DataScope controllerDataScope) { + clearDataScope(point); + handleDataScope(point, controllerDataScope); + } + + protected void handleDataScope(final JoinPoint joinPoint, DataScope controllerDataScope) { + if (controllerDataScope == null) { + return; + } + // 获取当前的用户 + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (StringUtils.isNotNull(loginUser)) { + SysUserEntity currentUser = loginUser.getUser(); + // 如果是超级管理员,则不过滤数据 + if (StringUtils.isNotNull(currentUser) && SysUserEntity.isAdmin(currentUser)) { + String permission = StringUtils.defaultIfEmpty(controllerDataScope.permission(), + CustomSecurityContextHolder.getPermission()); + dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(), + controllerDataScope.userAlias(), permission); + } + } + } + + /** + * 拼接权限sql前先清空params.dataScope参数防止注入 + */ + private void clearDataScope(final JoinPoint joinPoint) { + Object params = joinPoint.getArgs()[0]; + if (StringUtils.isNotNull(params) && params instanceof BaseEntity) { + BaseEntity baseEntity = (BaseEntity) params; + baseEntity.getParams().put(DATA_SCOPE, ""); + } + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/common/aspect/LogAspect.java --- +package com.starry.admin.common.aspect; + +import cn.hutool.extra.servlet.ServletUtil; +import com.alibaba.fastjson2.JSON; +import com.starry.admin.common.domain.LoginUser; +import com.starry.admin.modules.system.module.entity.SysOperationLogEntity; +import com.starry.admin.modules.system.service.ISysOperationLogService; +import com.starry.admin.utils.SecurityUtils; +import com.starry.common.annotation.Log; +import com.starry.common.utils.ServletUtils; +import com.starry.common.utils.StringUtils; +import java.util.Collection; +import java.util.Date; +import java.util.Map; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.AfterReturning; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.http.HttpMethod; +import org.springframework.stereotype.Component; +import org.springframework.validation.BindingResult; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.servlet.HandlerMapping; + +/** + * @author admin + */ +@Aspect +@Component +@Slf4j +public class LogAspect { + + @Resource + private ISysOperationLogService operLogService; + + /** + * 处理完请求后执行 + * + * @param joinPoint + * 切点 + */ + @AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult") + public void doAfterReturn(JoinPoint joinPoint, Log controllerLog, Object jsonResult) { + handleLog(joinPoint, controllerLog, jsonResult); + } + + protected void handleLog(final JoinPoint joinPoint, Log controllerLog, Object jsonResult) { + try { + // 获取当前的用户 + LoginUser loginUser = SecurityUtils.getLoginUser(); + + // 日志记录 + SysOperationLogEntity operLog = new SysOperationLogEntity(); + operLog.setStatus(0); + // 请求的IP地址 + String iP = ServletUtil.getClientIP(ServletUtils.getRequest()); + if ("0:0:0:0:0:0:0:1".equals(iP)) { + iP = "127.0.0.1"; + } + operLog.setOperIp(iP); + operLog.setOperUrl(ServletUtils.getRequest().getRequestURI()); + if (loginUser != null) { + operLog.setOperName(loginUser.getUsername()); + } + if (null != null) { + operLog.setStatus(1); + operLog.setErrorMsg(StringUtils.substring(((Exception) null).getMessage(), 0, 2000)); + } + // 设置方法名称 + String className = joinPoint.getTarget().getClass().getName(); + String methodName = joinPoint.getSignature().getName(); + operLog.setMethod(className + "." + methodName + "()"); + operLog.setRequestMethod(ServletUtils.getRequest().getMethod()); + operLog.setOperTime(new Date()); + // 处理设置注解上的参数 + getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult); + // 保存数据库 + operLogService.save(operLog); + + } catch (Exception exp) { + log.error("异常信息:{}", exp.getMessage()); + } + } + + /** + * 获取注解中对方法的描述信息 用于Controller层注解 + * + * @param log + * 日志 + * @param operLog + * 操作日志 + */ + public void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysOperationLogEntity operLog, + Object jsonResult) { + // 设置操作业务类型 + operLog.setBusinessType(log.businessType().ordinal()); + // 设置标题 + operLog.setTitle(log.title()); + // 是否需要保存request,参数和值 + if (log.isSaveRequestData()) { + // 设置参数的信息 + setRequestValue(joinPoint, operLog); + } + // 是否需要保存response,参数和值 + if (log.isSaveResponseData() && StringUtils.isNotNull(jsonResult)) { + operLog.setJsonResult(StringUtils.substring(JSON.toJSONString(jsonResult), 0, 2000)); + } + } + + /** + * 获取请求的参数,放到log中 + * + * @param operLog + * 操作日志 + */ + private void setRequestValue(JoinPoint joinPoint, SysOperationLogEntity operLog) { + String requsetMethod = operLog.getRequestMethod(); + if (HttpMethod.PUT.name().equals(requsetMethod) || HttpMethod.POST.name().equals(requsetMethod)) { + String params = argsArrayToString(joinPoint.getArgs()); + operLog.setOperParam(StringUtils.substring(params, 0, 2000)); + } else { + Map paramsMap = (Map) ServletUtils.getRequest() + .getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE); + operLog.setOperParam(StringUtils.substring(paramsMap.toString(), 0, 2000)); + } + } + + /** + * 参数拼装 + */ + private String argsArrayToString(Object[] paramsArray) { + StringBuilder params = new StringBuilder(); + if (paramsArray != null) { + for (Object object : paramsArray) { + // 不为空 并且是不需要过滤的 对象 + if (StringUtils.isNotNull(object) && !isFilterObject(object)) { + Object jsonObj = JSON.toJSON(object); + params.append(jsonObj.toString()).append(" "); + } + } + } + return params.toString().trim(); + } + + /** + * 判断是否需要过滤的对象。 + * + * @param object + * 对象信息。 + * @return 如果是需要过滤的对象,则返回true;否则返回false。 + */ + @SuppressWarnings("rawtypes") + public boolean isFilterObject(final Object object) { + Class clazz = object.getClass(); + if (clazz.isArray()) { + return clazz.getComponentType().isAssignableFrom(MultipartFile.class); + } else if (Collection.class.isAssignableFrom(clazz)) { + Collection collection = (Collection) object; + for (Object value : collection) { + return value instanceof MultipartFile; + } + } else if (Map.class.isAssignableFrom(clazz)) { + Map map = (Map) object; + for (Object value : map.entrySet()) { + Map.Entry entry = (Map.Entry) value; + return entry.getValue() instanceof MultipartFile; + } + } + return object instanceof MultipartFile || object instanceof HttpServletRequest + || object instanceof HttpServletResponse || object instanceof BindingResult; + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/common/aspect/MybatisAspectj.java --- +package com.starry.admin.common.aspect; + +import com.baomidou.mybatisplus.core.conditions.AbstractWrapper; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.stereotype.Component; + +/** + * @Author: huchuansai + * @Date: 2023/8/2 4:38 PM + * @Description: + */ +@Aspect +@Component +public class MybatisAspectj { + + // 配置织入点 + @Pointcut("execution(public * com.baomidou.mybatisplus.core.mapper.BaseMapper.selectOne(..))") + public void selectOneAspect() { + } + + @Before("selectOneAspect()") + public void beforeSelect(JoinPoint point) { + Object arg = point.getArgs()[0]; + if (arg instanceof AbstractWrapper) { + arg = (AbstractWrapper) arg; + ((AbstractWrapper) arg).last("limit 1"); + } + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/common/component/JwtToken.java --- +package com.starry.admin.common.component; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.servlet.ServletUtil; +import cn.hutool.http.useragent.UserAgent; +import cn.hutool.http.useragent.UserAgentUtil; +import com.starry.admin.common.domain.LoginUser; +import com.starry.admin.common.security.entity.JwtUser; +import com.starry.common.constant.CacheConstants; +import com.starry.common.constant.Constants; +import com.starry.common.constant.SecurityConstants; +import com.starry.common.context.CustomSecurityContextHolder; +import com.starry.common.redis.RedisCache; +import com.starry.common.utils.IdUtils; +import com.starry.common.utils.ServletUtils; +import com.starry.common.utils.ip.AddressUtils; +import com.starry.common.utils.ip.IpUtils; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.stereotype.Component; + +/** + * @author admin token 组件 + * @since 2021/9/6 + */ +@Slf4j +@Component +public class JwtToken { + + private static final String CLAIM_KEY_USERNAME = "sub"; + private static final String CLAIM_KEY_CREATED = "created"; + private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L; + + @Value("${jwt.secret}") + private String secret; + @Value("${jwt.expiration}") + private Long expire; + @Value("${jwt.tokenHeader}") + private String tokenHeader; + @Value("${jwt.tokenHead}") + private String tokenHead; + + @Resource + private RedisCache redisCache; + + /** + * 从token中获取登录用户名 + */ + public String getUserNameFromToken(String token) { + String username; + try { + Claims claims = getClaimsFromToken(token); + username = claims.getSubject(); + } catch (Exception e) { + username = null; + } + return username; + } + + /** + * 校验token + */ + public boolean validateToken(String token, UserDetails userDetails) { + String username = getUserNameFromToken(token); + return username.equals(userDetails.getUsername()) && !isTokenExpired(token); + } + + /** + * 根据用户信息生成token + */ + public String generateToken(UserDetails userDetails) { + Map claims = new HashMap<>(); + claims.put(CLAIM_KEY_USERNAME, userDetails.getUsername()); + claims.put(CLAIM_KEY_CREATED, new Date()); + return generateToken(claims); + } + + /** + * 创建令牌 + * + * @param jwtUser + * 用户信息 + * @return 令牌 + */ + public String createToken(JwtUser jwtUser) { + String token = IdUtils.getUuid(); + jwtUser.setToken(token); + setUserAgent(jwtUser); + refersToken(jwtUser); + + Map claims = new HashMap<>(); + claims.put(Constants.LOGIN_USER_KEY, token); + return createToken(claims); + } + + /** + * 从数据声明生成令牌 + * + * @param claims + * 数据声明 + * @return 令牌 + */ + private String createToken(Map claims) { + String token = Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS512, secret).compact(); + return token; + } + + /** + * 判断token是否已经失效 + */ + private boolean isTokenExpired(String token) { + Date expiredDate = getClaimsFromToken(token).getExpiration(); + return expiredDate.before(new Date()); + } + + private String generateToken(Map claims) { + return Jwts.builder().setClaims(claims).setExpiration(generateExpirationDate()) + // 签名算法 + .signWith(SignatureAlgorithm.HS512, secret).compact(); + } + + /** + * 生成token的过期时间 + */ + private Date generateExpirationDate() { + return new Date(System.currentTimeMillis() + expire * 1000); + } + + /** + * 从令牌中获取数据声明 + * + * @param token + * 令牌 + * @return 数据声明 + */ + private Claims getClaimsFromToken(String token) { + Claims claims = null; + try { + claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody(); + } catch (Exception e) { + log.info("JWT格式验证失败:{}", token); + } + return claims; + } + + /** + * 设置用户代理信息 + * + * @param jwtUser + * 登录信息 + */ + public void setUserAgent(JwtUser jwtUser) { + UserAgent userAgent = UserAgentUtil.parse(ServletUtils.getRequest().getHeader("User-Agent")); + String ip = ServletUtil.getClientIP(ServletUtils.getRequest()); + jwtUser.setIpaddr(ip); + jwtUser.setLoginLocation(AddressUtils.getRealAddressByIp(ip)); + jwtUser.setBrowser(userAgent.getBrowser().getName()); + jwtUser.setOs(userAgent.getOs().getName()); + } + + public void refersToken(JwtUser jwtUser) { + jwtUser.setLoginTime(System.currentTimeMillis()); + jwtUser.setExpireTime(jwtUser.getLoginTime() + expire * 1000); + String userKey = getTokenKey(jwtUser.getToken()); + redisCache.setCacheObject(userKey, jwtUser, expire, TimeUnit.SECONDS); + String key = "login:resource:" + jwtUser.getUserId(); + redisCache.setCacheObject(key, userKey, expire, TimeUnit.SECONDS); + } + + private String getTokenKey(String uuid) { + return CacheConstants.LOGIN_TOKEN_KEY + uuid; + } + + /** + * 获取登录用户身份信息 + * + * @return 用户信息 + */ + public JwtUser getLoginUser(HttpServletRequest request) { + String token = getToken(request); + if (StrUtil.isNotBlank(token)) { + try { + Claims claims = getClaimsFromToken(token); + String uuid = (String) claims.get(Constants.LOGIN_USER_KEY); + String userKey = getTokenKey(uuid); + JwtUser user = redisCache.getCacheObject(userKey); + return user; + } catch (Exception e) { + + } + } + return null; + } + + /** + * 获取请求token + * + * @param request + * @return token + */ + private String getToken(HttpServletRequest request) { + // 获取请求头 + String token = request.getHeader(tokenHeader); + if (StrUtil.isNotBlank(token) && token.startsWith(tokenHead)) { + token = token.replace(tokenHead, ""); + } + return token; + } + + /** + * 验证令牌有效期,相差不足20分钟,自动刷新缓存 + * + * @param jwtUser + * @return 令牌 + */ + + /** + * 删除用户身份信息 + */ + public void removeJwtUser(String token) { + if (StrUtil.isNotBlank(token)) { + String userKey = getTokenKey(token); + redisCache.deleteObject(userKey); + } + } + + /** + * 创建令牌 + */ + public Map createToken(LoginUser loginUser) { + String token = IdUtils.getUuid(); + String userId = loginUser.getUser().getUserId(); + String userName = loginUser.getUser().getUserCode(); + String tenantId = loginUser.getUser().getTenantId(); + Long deptId = loginUser.getUser().getDeptId(); + loginUser.setToken(token); + loginUser.setUserId(userId); + loginUser.setUserName(userName); + loginUser.setIpaddr(IpUtils.getIpAddr(ServletUtils.getRequest())); + // 添加地址信息 + setUserAgent(loginUser); + String userRedisKey = refreshToken(loginUser); + + String key = "login:resource:" + loginUser.getUserId(); + redisCache.setCacheObject(key, userRedisKey, expire, TimeUnit.SECONDS); + + // Jwt存储信息 + Map claimsMap = new HashMap<>(8); + claimsMap.put(SecurityConstants.USER_KEY, token); + claimsMap.put(SecurityConstants.DETAILS_USER_ID, userId); + claimsMap.put(SecurityConstants.DETAILS_USERNAME, userName); + // 租户id + claimsMap.put(SecurityConstants.DETAILS_TENANT_ID, tenantId); + // 部门id + claimsMap.put(SecurityConstants.DETAILS_DEPT_ID, deptId); + // 接口返回信息 + Map rspMap = new HashMap<>(); + rspMap.put("token", this.createToken(claimsMap)); + rspMap.put("expires_in", expire); + rspMap.put("tenant_id", tenantId); + rspMap.put("tokenHead", tokenHead); + return rspMap; + } + + /** + * 设置用户代理信息 + * + * @param loginUser + * 登录信息 + */ + public void setUserAgent(LoginUser loginUser) { + UserAgent userAgent = UserAgentUtil.parse(ServletUtils.getRequest().getHeader("User-Agent")); + String ip = ServletUtil.getClientIP(ServletUtils.getRequest()); + loginUser.setIpaddr(ip); + loginUser.setLoginLocation(AddressUtils.getRealAddressByIp(ip)); + loginUser.setBrowser(userAgent.getBrowser().getName()); + loginUser.setOs(userAgent.getOs().getName()); + } + + /** + * 刷新令牌有效期 + * + * @param loginUser + * 登录信息 + * @return + */ + public String refreshToken(LoginUser loginUser) { + loginUser.setLoginTime(System.currentTimeMillis()); + loginUser.setExpireTime(loginUser.getLoginTime() + expire * 1000); + // 根据uuid将loginUser缓存 + String userKey = getTokenKey(loginUser.getToken()); + redisCache.setCacheObject(userKey, loginUser, expire, TimeUnit.MINUTES); + return userKey; + } + + /** + * 获取登录用户身份信息 + * + * @return 用户信息 + */ + public LoginUser getNewLoginUser(HttpServletRequest request) { + String token = getToken(request); + if (StrUtil.isNotBlank(token)) { + try { + Claims claims = getClaimsFromToken(token); + String uuid = (String) claims.get(SecurityConstants.USER_KEY); + String userKey = getTokenKey(uuid); + LoginUser loginUser = redisCache.getCacheObject(userKey); + CustomSecurityContextHolder.set(SecurityConstants.DETAILS_TENANT_ID, loginUser.getUser().getTenantId()); + CustomSecurityContextHolder.set(SecurityConstants.LOGIN_USER, loginUser); + return loginUser; + } catch (Exception e) { + log.error("getNewLoginUser error", e); + } + } + return null; + } + + /** + * 验证令牌有效期,相差不足20分钟,自动刷新缓存 + * + * @param loginUser + * @return 令牌 + */ + public void verifyToken(LoginUser loginUser) { + long expireTime = loginUser.getExpireTime(); + long currentTime = System.currentTimeMillis(); + if (expireTime - currentTime <= MILLIS_MINUTE_TEN) { + refreshToken(loginUser); + } + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/common/component/PermissionService.java --- +package com.starry.admin.common.component; + +import com.starry.admin.common.domain.LoginUser; +import com.starry.admin.modules.system.module.entity.SysRoleEntity; +import com.starry.admin.utils.SecurityUtils; +import java.util.Set; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +/** + * 自定义权限实现,ss取自SpringSecurity首字母 + * + * @author admin + */ +@Service("customSs") +public class PermissionService { + /** + * 所有权限标识 + */ + private static final String ALL_PERMISSION = "*:*:*"; + + /** + * 管理员角色权限标识 + */ + private static final String SUPER_ADMIN = "admin"; + + private static final String ROLE_DELIMITER = ","; + + private static final String PERMISSION_DELIMETER = ","; + + /** + * 验证用户是否具备某权限 + * + * @param permission + * 权限字符串 + * @return 用户是否具备某权限 + */ + public boolean hasPermission(String permission) { + if (StringUtils.isEmpty(permission)) { + return false; + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (loginUser == null || CollectionUtils.isEmpty(loginUser.getPermissions())) { + return false; + } + return hasPermissions(loginUser.getPermissions(), permission); + } + + /** + * 验证用户是否不具备某权限,与 hasPermission逻辑相反 + * + * @param permission + * 权限字符串 + * @return 用户是否不具备某权限 + */ + public boolean lacksPermission(String permission) { + return hasPermission(permission) != true; + } + + /** + * 验证用户是否具有以下任意一个权限 + * + * @param permissions + * 以 PERMISSION_NAMES_DELIMETER 为分隔符的权限列表 + * @return 用户是否具有以下任意一个权限 + */ + public boolean hasAnyPermission(String permissions) { + if (StringUtils.isEmpty(permissions)) { + return false; + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (loginUser == null || CollectionUtils.isEmpty(loginUser.getPermissions())) { + return false; + } + Set authorities = loginUser.getPermissions(); + for (String permission : permissions.split(PERMISSION_DELIMETER)) { + if (permission != null && hasPermissions(authorities, permission)) { + return true; + } + } + return false; + } + + /** + * 判断用户是否拥有某个角色 + * + * @param role + * 角色字符串 + * @return 用户是否具备某角色 + */ + public boolean hasRole(String role) { + if (StringUtils.isEmpty(role)) { + return false; + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (loginUser == null || CollectionUtils.isEmpty(loginUser.getUser().getRoles())) { + return false; + } + for (SysRoleEntity sysRoleEntity : loginUser.getUser().getRoles()) { + String roleKey = sysRoleEntity.getRoleKey(); + if (SUPER_ADMIN.equals(roleKey) || roleKey.equals(StringUtils.trim(role))) { + return true; + } + } + return false; + } + + /** + * 验证用户是否不具备某角色,与 isRole逻辑相反。 + * + * @param role + * 角色名称 + * @return 用户是否不具备某角色 + */ + public boolean lacksRole(String role) { + return !hasRole(role); + } + + /** + * 验证用户是否具有以下任意一个角色 + * + * @param roles + * 以 ROLE_NAMES_DELIMITER 为分隔符的角色列表 + * @return 用户是否具有以下任意一个角色 + */ + public boolean hasAnyRoles(String roles) { + if (StringUtils.isEmpty(roles)) { + return false; + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (loginUser == null || CollectionUtils.isEmpty(loginUser.getUser().getRoles())) { + return false; + } + for (String role : roles.split(ROLE_DELIMITER)) { + if (hasRole(role)) { + return true; + } + } + return false; + } + + /** + * 判断是否包含权限 + * + * @param permissions + * 权限列表 + * @param permission + * 权限字符串 + * @return 用户是否具备某权限 + */ + private boolean hasPermissions(Set permissions, String permission) { + return permissions.contains(ALL_PERMISSION) || permissions.contains(StringUtils.trim(permission)); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/common/conf/AbstractListTypeHandler.java --- +package com.starry.admin.common.conf; + +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.TypeReference; +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.apache.ibatis.type.BaseTypeHandler; +import org.apache.ibatis.type.JdbcType; +import org.apache.ibatis.type.MappedJdbcTypes; +import org.apache.ibatis.type.MappedTypes; + +/** + * 数据库数据-String 和 List 自动转换 + * + * @author admin + */ +@Slf4j +@MappedJdbcTypes(JdbcType.VARCHAR) +@MappedTypes({List.class}) +public abstract class AbstractListTypeHandler extends BaseTypeHandler> { + @Override + public void setNonNullParameter(PreparedStatement ps, int i, List parameter, JdbcType jdbcType) + throws SQLException { + String content = StrUtil.isEmptyIfStr(parameter) ? null : JSON.toJSONString(parameter); + ps.setString(i, content); + } + + @Override + public List getNullableResult(ResultSet rs, String columnName) throws SQLException { + return this.getListByJsonArrayString(rs.getString(columnName)); + } + + @Override + public List getNullableResult(ResultSet rs, int columnIndex) throws SQLException { + return this.getListByJsonArrayString(rs.getString(columnIndex)); + } + + @Override + public List getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { + return this.getListByJsonArrayString(cs.getString(columnIndex)); + } + + private List getListByJsonArrayString(String content) { + return StrUtil.isEmptyIfStr(content) ? new ArrayList<>() : JSON.parseObject(content, this.specificType()); + } + + /** + * 具体类型,由子类提供 + * + * @return 具体类型 + */ + protected abstract TypeReference> specificType(); +} + + +--- File: play-admin/src/main/java/com/starry/admin/common/conf/DataSourceConfig.java --- +package com.starry.admin.common.conf; + +import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder; +import javax.sql.DataSource; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; + +@Configuration +public class DataSourceConfig { + + // For flyway only + @Bean(name = "primaryDataSource") + @Primary + public DataSource dataSource() { + return DruidDataSourceBuilder.create().build(); + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/common/conf/StringTypeHandler.java --- +package com.starry.admin.common.conf; + +import com.alibaba.fastjson2.TypeReference; +import java.util.List; + +/** + * @author admin + */ +public class StringTypeHandler extends AbstractListTypeHandler { + @Override + protected TypeReference> specificType() { + return new TypeReference>() { + }; + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/common/conf/ThreadLocalRequestDetail.java --- +package com.starry.admin.common.conf; + +import com.alibaba.ttl.TransmittableThreadLocal; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity; +import com.starry.admin.modules.custom.module.entity.PlayCustomUserInfoEntity; + +/** + * @author : huchuansai + * @since : 2024/4/2 12:10 AM + */ +public class ThreadLocalRequestDetail { + private static final TransmittableThreadLocal THREAD_LOCAL = new TransmittableThreadLocal<>(); + + /** + * 设置请求信息到当前线程中 + */ + public static void setRequestDetail(Object data) { + THREAD_LOCAL.set(data); + } + + /** + * 从当前线程中获取请求信息 + */ + public static Object getRequestDetail() { + return THREAD_LOCAL.get(); + } + + public static PlayClerkUserInfoEntity getClerkUserInfo() { + return (PlayClerkUserInfoEntity) THREAD_LOCAL.get(); + } + + public static PlayCustomUserInfoEntity getCustomUserInfo() { + return (PlayCustomUserInfoEntity) THREAD_LOCAL.get(); + } + + /** + * 销毁 + */ + public static void remove() { + THREAD_LOCAL.remove(); + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/common/domain/LoginUser.java --- +package com.starry.admin.common.domain; + +import com.starry.admin.modules.system.module.entity.SysUserEntity; +import java.util.Collection; +import java.util.Date; +import java.util.Set; +import lombok.Data; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +/** + * @author admin + */ +@Data +public class LoginUser implements UserDetails { + private static final long serialVersionUID = 1L; + + /** + * 用户唯一标识 + */ + private String token; + /** + * 用户名id + */ + private String userId; + + /** + * 用户名 + */ + private String userName; + + /** + * 登录时间 + */ + private Long loginTime; + + /** + * 过期时间 + */ + private Long expireTime; + + /** + * 登录IP地址 + */ + private String ipaddr; + /** + * 登录地点 + */ + private String loginLocation; + + /** + * 浏览器类型 + */ + private String browser; + + /** + * 操作系统 + */ + private String os; + + /** + * 权限列表 + */ + private Set permissions; + + /** + * 角色列表 + */ + private Set roles; + + /** + * 用户信息 + */ + private SysUserEntity user; + + /** + * 租户租赁截止日期--dhr + */ + private Date tenantEndDate; + + /** + * 租户状态 + */ + private Integer tenantStatus; + + // 当前角色 + private String currentRole; + + @Override + public Collection getAuthorities() { + return null; + } + + @Override + public String getPassword() { + return user.getPassWord(); + } + + @Override + public String getUsername() { + return user.getUserCode(); + } + + /** + * 账户是否未过期 + **/ + @Override + public boolean isAccountNonExpired() { + return true; + } + + /** + * 账户是否未锁定 + **/ + @Override + public boolean isAccountNonLocked() { + return true; + } + + /** + * 密码是否未过期 + **/ + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + /** + * 账户是否激活 + **/ + @Override + public boolean isEnabled() { + return user.getStatus() == 0; + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/common/domain/TreeSelect.java --- +package com.starry.admin.common.domain; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.starry.admin.modules.system.module.entity.SysDeptEntity; +import com.starry.admin.modules.system.module.entity.SysMenuEntity; +import java.io.Serializable; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; + +/** + * @author Treeselect树结构实体类 + * @since 2022/7/4 + */ +@Data +public class TreeSelect implements Serializable { + + /** + * 节点ID + */ + private Long id; + + /** + * 节点名称 + */ + private String label; + + /** + * 子节点 + */ + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private List children; + + public TreeSelect(SysMenuEntity menu) { + this.id = menu.getMenuId(); + this.label = menu.getMenuName(); + this.children = menu.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList()); + } + + public TreeSelect(SysDeptEntity dept) { + this.id = dept.getDeptId(); + this.label = dept.getDeptName(); + this.children = dept.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList()); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/common/exception/CustomException.java --- +package com.starry.admin.common.exception; + +/** + * 自定义异常处理器 * * @author admin + */ +public class CustomException extends RuntimeException { + public CustomException(String msg) { + super(msg); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/common/exception/ServiceException.java --- +package com.starry.admin.common.exception; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @author 业务异常 + * @since 2023/3/9 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class ServiceException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + /** + * 错误码 + */ + private Integer code; + + /** + * 错误提示 + */ + private String message; + + /** + * 错误明细,内部调试错误 + */ + private String detailMessage; + + /** + * 空构造方法,避免反序列化问题 + */ + public ServiceException() { + } + + public ServiceException(String message) { + this.message = message; + } + + public ServiceException(String message, Integer code) { + this.message = message; + this.code = code; + } + + public ServiceException setDetailMessage(String detailMessage) { + this.detailMessage = detailMessage; + return this; + } + + @Override + public String getMessage() { + return message; + } + + public ServiceException setMessage(String message) { + this.message = message; + return this; + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/common/exception/handler/GlobalExceptionHandler.java --- +package com.starry.admin.common.exception.handler; + +import com.fasterxml.jackson.databind.exc.MismatchedInputException; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.common.exception.ServiceException; +import com.starry.common.result.R; +import com.starry.common.utils.StringUtils; +import javax.servlet.http.HttpServletRequest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindingResult; +import org.springframework.validation.FieldError; +import org.springframework.web.HttpRequestMethodNotSupportedException; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.MissingServletRequestParameterException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +/** + * @author 全局异常处理 + * @since 2023/3/9 + */ +@RestControllerAdvice +public class GlobalExceptionHandler { + private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class); + + /** + * 业务异常 + */ + @ExceptionHandler(ServiceException.class) + public R handleServiceException(ServiceException e, HttpServletRequest request) { + if ("token异常".equals(e.getMessage()) || "token为空".equals(e.getMessage())) { + log.error("用户token异常"); + } else { + log.error(e.getMessage(), e); + } + Integer code = e.getCode(); + return StringUtils.isNotNull(code) ? R.error(code, e.getMessage()) : R.error(e.getMessage()); + } + + /** + * 拦截未知的运行时异常 + */ + @ExceptionHandler(RuntimeException.class) + public R handleRuntimeException(RuntimeException e, HttpServletRequest request) { + String requestUrl = request.getRequestURI(); + log.error("请求地址'{}',发生未知异常.", requestUrl, e); + return R.error(e.getMessage()); + } + + /** + * 系统异常 + */ + @ExceptionHandler(Exception.class) + public R handleException(Exception e, HttpServletRequest request) { + String requestUrl = request.getRequestURI(); + log.error("请求地址'{}',发生系统异常.", requestUrl, e); + return R.error("系统出现内部错误,请联系管理员"); + } + + /** + * 请求方法异常 + */ + @ExceptionHandler(HttpRequestMethodNotSupportedException.class) + public R httpRequestMethodNotSupportedException() { + return R.error("请求方法异常"); + } + + /** + * 请求参数异常 + * + * @param e + * HttpRequestMethodNotSupportedException + */ + @ExceptionHandler(MethodArgumentNotValidException.class) + public R methodArgumentNotValidException(MethodArgumentNotValidException e) { + BindingResult bindingResult = e.getBindingResult(); + StringBuilder errorMessageBuilder = new StringBuilder(); + for (FieldError error : bindingResult.getFieldErrors()) { + errorMessageBuilder.append(error.getDefaultMessage()); + } + return R.error("请求参数异常," + errorMessageBuilder); + } + + @ExceptionHandler(MismatchedInputException.class) + public R mismatchedInputException(MismatchedInputException e) { + return R.error("请求参数格式异常"); + } + + @ExceptionHandler(HttpMessageNotReadableException.class) + public R httpMessageNotReadableException(HttpMessageNotReadableException e) { + return R.error("请求参数格式异常"); + } + + @ExceptionHandler(MissingServletRequestParameterException.class) + public R missingServletRequestParameterException(MissingServletRequestParameterException e) { + return R.error("请求参数格式异常"); + } + + /** + * 自定义异常 + * + * @param e + * CustomException + */ + @ExceptionHandler(CustomException.class) + public R customException(CustomException e) { + if ("token异常".equals(e.getMessage()) || "token为空".equals(e.getMessage())) { + log.error("用户token异常"); + } else { + log.error(e.getMessage(), e); + } + + return R.error(e.getMessage()); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/common/mybatis/config/MybatisPlusConfig.java --- +package com.starry.admin.common.mybatis.config; + +import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder; +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor; +import com.starry.admin.common.mybatis.handler.MyTenantLineHandler; +import javax.sql.DataSource; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +/** + * @author admin + */ +@Configuration +@MapperScan("com.starry.**.mapper") +@EnableTransactionManagement +public class MybatisPlusConfig { + + /** + * druid注入 + * + * @return dataSource + */ + @Bean(name = "dataSource") + @ConfigurationProperties(prefix = "spring.datasource.druid") + public DataSource dataSource() { + return DruidDataSourceBuilder.create().build(); + } + + /** + * 配置事物管理器 + * + * @return DataSourceTransactionManager + */ + @Bean(name = "transactionManager") + public DataSourceTransactionManager transactionManager() { + return new DataSourceTransactionManager(dataSource()); + } + + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + // 租户插件 + interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new MyTenantLineHandler())); + // 分页插件 + interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); + // 乐观锁插件 + interceptor.addInnerInterceptor(optimisticLockerInnerInterceptor()); + // 阻断插件 + interceptor.addInnerInterceptor(blockAttackInnerInterceptor()); + return interceptor; + } + + /** + * 乐观锁 + */ + @Bean + public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor() { + return new OptimisticLockerInnerInterceptor(); + } + + /** + * 防止全表更新与删除 + */ + @Bean + public BlockAttackInnerInterceptor blockAttackInnerInterceptor() { + return new BlockAttackInnerInterceptor(); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/common/mybatis/handler/MyMetaObjectHandler.java --- +package com.starry.admin.common.mybatis.handler; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; +import com.starry.admin.modules.weichat.service.WxTokenService; +import com.starry.admin.utils.SecurityUtils; +import com.starry.common.constant.Constants; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.Date; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import org.apache.ibatis.reflection.MetaObject; +import org.springframework.stereotype.Component; + +/** + * @author admin 字段默认值处理类 + * @since 2021/9/1 + */ +@Slf4j +@Component +public class MyMetaObjectHandler implements MetaObjectHandler { + + @Resource + private HttpServletRequest request; + + @Resource + private WxTokenService tokenService; + + @Override + public void insertFill(MetaObject metaObject) { + + this.setFieldValByName("createdTime", new Date(), metaObject); + this.setFieldValByName("deleted", false, metaObject); + this.setFieldValByName("version", 1L, metaObject); + Object createUser = this.getFieldValByName("createdBy", metaObject); + if (createUser == null) { + if (SecurityUtils.isLogin()) { + this.setFieldValByName("createdBy", getOperatorId(), metaObject); + } + } + } + + @Override + public void updateFill(MetaObject metaObject) { + this.setFieldValByName("updatedTime", getDate(), metaObject); + Object createUser = this.getFieldValByName("updatedBy", metaObject); + if (createUser == null) { + this.setFieldValByName("createdBy", getOperatorId(), metaObject); + } + } + + public Date getDate() { + + LocalDateTime localDateTime = LocalDateTime.now(); + return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()); + // return Date.from(localDateTime.toInstant(ZoneOffset.ofHours(8))); + } + + public String getOperatorId() { + try { + if (request.getServletPath().startsWith("/wx/")) { + String tenantKey = request.getHeader("tenantkey"); + if (StrUtil.isBlankIfStr(tenantKey)) { + String clerkToken = request.getHeader(Constants.CLERK_USER_LOGIN_TOKEN); + String customToken = request.getHeader(Constants.CUSTOM_USER_LOGIN_TOKEN); + if (clerkToken != null) { + return tokenService.getWxUserIdByToken(clerkToken); + } + if (customToken != null) { + return tokenService.getWxUserIdByToken(customToken); + } + } + return ""; + } else { + if (SecurityUtils.isLogin()) { + return SecurityUtils.getUserId(); + } + } + } catch (Exception ignored) { + if (SecurityUtils.isLogin()) { + return SecurityUtils.getUserId(); + } + } + return ""; + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/common/mybatis/handler/MyTenantLineHandler.java --- +package com.starry.admin.common.mybatis.handler; + +import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler; +import com.starry.admin.utils.SecurityUtils; +import com.starry.common.utils.StringUtils; +import java.util.Arrays; +import lombok.extern.slf4j.Slf4j; +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.StringValue; +import org.springframework.stereotype.Component; + +/** + * @author admin 多租户处理器 + * @since 2023/3/7 + */ +@Slf4j +@Component +public class MyTenantLineHandler implements TenantLineHandler { + + /** + * 排除过滤的表 + */ + private static final String[] TABLE_FILTER = {"sys_login_log", "sys_menu", "sys_tenant_package", "sys_tenant", + "sys_dict", "sys_dict_data", "sys_administrative_area_dict_info"}; + + /** + * 排除过滤的表前缀 + */ + private static final String[] TABLE_PRE = {"qrtz", "gen"}; + + @Override + public Expression getTenantId() { + // 取出当前请求的服务商ID,通过解析器注入到SQL中。 + String tenantId = SecurityUtils.getTenantId(); + // if (!StrUtil.isBlankIfStr(tenantId)) { + // throw new CustomException("租户信息获取异常"); + // } + return new StringValue(tenantId); + } + + /** + * 跳过不需要加多租户的表 + */ + @Override + public boolean ignoreTable(String tableName) { + String prefix = StringUtils.substringBefore(tableName, "_"); + return Arrays.asList(TABLE_FILTER).contains(tableName) || Arrays.asList(TABLE_PRE).contains(prefix); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/common/oss/OssProperties.java --- +package com.starry.admin.common.oss; + +import lombok.Data; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +@Data +@Configuration +@ConfigurationProperties(prefix = "aliyun") +@PropertySource(value = {"classpath:oss.properties"}) +public class OssProperties implements InitializingBean { + + public static String ENDPOINT = ""; + public static String KEY_ID = ""; + public static String KEY_SECRET = ""; + public static String BUCKET_NAME = ""; + public String endpoint = "oss-cn-hangzhou.aliyuncs.com"; + public String accessKeyId = "LTAI5t9ojt6uovFZokYZfJx5"; + public String accessKeySecret = "xfCyNM5BQlAkoaa5NbcpoeipmCKZgf"; + public String bucketName = "live-cloud-cvoon"; + + @Override + public void afterPropertiesSet() { + ENDPOINT = getEndpoint(); + KEY_ID = getAccessKeyId(); + KEY_SECRET = getAccessKeySecret(); + BUCKET_NAME = getBucketName(); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/common/oss/controller/CosController.java --- +package com.starry.admin.common.oss.controller; + +import com.starry.admin.common.oss.service.IOssFileService; +import com.starry.common.result.R; +import io.swagger.annotations.ApiOperation; +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +/** + * @author admin cos存储前端控制器 + * @since 2022/11/13 17:51 + */ +@Slf4j +@RestController +@RequestMapping("/cos") +public class CosController { + + @Resource + IOssFileService ossFileService; + + @ApiOperation(value = "照片上传") + @PostMapping("/upload/image") + public R uploadImage(MultipartFile file) throws Exception { + if (!file.isEmpty()) { + String house = ossFileService.upload(file.getInputStream(), "house", file.getOriginalFilename()); + return R.ok(house); + } + return R.error("上传照片异常,请联系管理员"); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/common/oss/service/IOssFileService.java --- +package com.starry.admin.common.oss.service; + +import java.io.InputStream; + +public interface IOssFileService { + + /** + * 文件上传只阿里云OSS + * + * @param inputStream + * 文件流 + * @param module + * 文件保存模块地址 + * @param originalFilename + * 原始文件名 + * @return String + * @author admin + * @since 2024/4/11 10:24 + **/ + String upload(InputStream inputStream, String module, String originalFilename); + + /** + * 删除文件 + * + * @param url + * 文件地址 + */ + void remove(String url); + +} + + +--- File: play-admin/src/main/java/com/starry/admin/common/oss/service/impl/OssFileServiceImpl.java --- +package com.starry.admin.common.oss.service.impl; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.io.FileTypeUtil; +import com.aliyun.oss.ClientException; +import com.aliyun.oss.OSS; +import com.aliyun.oss.OSSClientBuilder; +import com.aliyun.oss.OSSException; +import com.aliyun.oss.model.CannedAccessControlList; +import com.aliyun.oss.model.PutObjectRequest; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.common.oss.OssProperties; +import com.starry.admin.common.oss.service.IOssFileService; +import com.starry.common.utils.IdUtils; +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.springframework.stereotype.Service; + +/** + * @author admin + */ +@Service +@Slf4j +public class OssFileServiceImpl implements IOssFileService { + + @Override + public String upload(InputStream inputStream, String module, String filename) { + + BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream); + bufferedInputStream.mark(0); + String fileType = FileTypeUtil.getType(bufferedInputStream); + try { + bufferedInputStream.reset(); + } catch (IOException e) { + throw new CustomException("文件上传到OSS失败"); + } + // 创建OSSClient实例。 + OSS ossClient = new OSSClientBuilder().build(OssProperties.ENDPOINT, OssProperties.KEY_ID, + OssProperties.KEY_SECRET); + log.info("OSSClient实例创建成功"); + try { + // 判断oss实例是否存在:如果不存在则创建,如果存在则获取 + if (!ossClient.doesBucketExist(OssProperties.BUCKET_NAME)) { + // 创建bucket + ossClient.createBucket(OssProperties.BUCKET_NAME); + log.info("bucket存储空间【{}】创建成功", OssProperties.BUCKET_NAME); + // 设置oss实例的访问权限:公共读 + ossClient.setBucketAcl(OssProperties.BUCKET_NAME, CannedAccessControlList.PublicRead); + log.info("【{}】存储空间访问权限设置为公共读成功", OssProperties.BUCKET_NAME); + } + // 构建日期路径:avatar/2019/02/26/文件名 + String folder = new DateTime().toString("yyyy/MM/dd"); + // 文件名:uuid.扩展名 + + filename = IdUtils.getUuid() + "." + fileType; + // 文件根路径 + String key = module + "/" + folder + "/" + filename; + // 创建PutObjectRequest对象。 + PutObjectRequest putObjectRequest = new PutObjectRequest(OssProperties.BUCKET_NAME, key, + bufferedInputStream); + // 创建PutObject请求。 + ossClient.putObject(putObjectRequest); + log.info("oss文件上传成功"); + // 阿里云文件绝对路径 + String endpoint = OssProperties.ENDPOINT; + if (OssProperties.ENDPOINT.contains("//")) { + endpoint = OssProperties.ENDPOINT.substring(OssProperties.ENDPOINT.lastIndexOf("//") + 2); + } + // 返回文件的访问路径 + return "https://" + OssProperties.BUCKET_NAME + "." + endpoint + "/" + key; + } catch (OSSException oe) { + log.error("OSSException 文件上传失败:", oe); + throw new CustomException("OSS文件上传异常,{}" + oe.getMessage()); + } catch (ClientException ce) { + log.error("ClientException 文件上传失败:{}", ExceptionUtils.getStackTrace(ce)); + throw new CustomException("OSS文件上传异常,{}" + ce.getMessage()); + } finally { + if (ossClient != null) { + ossClient.shutdown(); + log.info("关闭ossClient"); + } + } + } + + @Override + public void remove(String url) { + OSS ossClient = new OSSClientBuilder().build(OssProperties.ENDPOINT, OssProperties.KEY_ID, + OssProperties.KEY_SECRET); + log.info("OSSClient实例创建成功"); + try { + String endpoint = OssProperties.ENDPOINT.substring(OssProperties.ENDPOINT.lastIndexOf("//") + 2); + // 文件名(服务器上的文件路径) + String host = "https://" + OssProperties.BUCKET_NAME + "." + endpoint + "/"; + String objectName = url.substring(host.length()); + // 删除文件或目录。如果要删除目录,目录必须为空。 + ossClient.deleteObject(OssProperties.BUCKET_NAME, objectName); + log.info("{}文件删除成功", objectName); + } catch (OSSException oe) { + log.error("OSSException 文件删除失败", oe); + throw new CustomException("OSS文件删除异常,{}" + oe.getMessage()); + } catch (ClientException ce) { + log.error("ClientException 文件删除失败:{}", ExceptionUtils.getStackTrace(ce)); + throw new CustomException("OSS文件删除异常,{}" + ce.getMessage()); + } finally { + if (ossClient != null) { + // 关闭OSSClient。 + ossClient.shutdown(); + log.info("关闭ossClient"); + } + } + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/common/security/config/SpringSecurityConfig.java --- +package com.starry.admin.common.security.config; + +import com.starry.admin.common.security.entity.JwtUser; +import com.starry.admin.common.security.filter.JwtAuthenticationTokenFilter; +import com.starry.admin.common.security.handler.CustomAccessDeniedHandler; +import com.starry.admin.common.security.handler.CustomAuthenticationEntryPoint; +import com.starry.admin.common.security.handler.CustomLogoutSuccessHandler; +import com.starry.admin.modules.system.module.entity.SysUserEntity; +import com.starry.admin.modules.system.service.SysMenuService; +import com.starry.admin.modules.system.service.SysUserService; +import java.util.Set; +import javax.annotation.Resource; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.CorsConfigurationSource; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; + +/** + * @author admin + */ +@Configuration +@EnableWebSecurity +@EnableGlobalMethodSecurity(prePostEnabled = true) +public class SpringSecurityConfig extends WebSecurityConfigurerAdapter { + + @Resource + private CustomAccessDeniedHandler customAccessDeniedHandler; + @Resource + private CustomAuthenticationEntryPoint customAuthenticationEntryPoint; + @Resource + private SysUserService sysUserService; + @Resource + private SysMenuService menuService; + @Resource + private CustomLogoutSuccessHandler customLogoutSuccessHandler; + + @Override + protected void configure(HttpSecurity httpSecurity) throws Exception { + httpSecurity.csrf().disable()// 由于使用的是JWT,我们这里不需要csrf + .sessionManagement()// 基于token,所以不需要session + .sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests() + // 允许对于网站静态资源的无授权访问 + .antMatchers(HttpMethod.GET, "/", "/*.html", "/favicon.ico", "/**/*.html", "/**/*.css", "/**/*.js", + "/swagger-resources/**", "/v2/api-docs/**") + .permitAll() + // 对登录注册要允许匿名访问 + .antMatchers("/login", "/captcha/get-captcha", "/wx/**").permitAll() + // 允许健康检查接口匿名访问 + .antMatchers("/health", "/health/**").permitAll() + // 跨域请求会先进行一次options请求 + .antMatchers(HttpMethod.OPTIONS).permitAll().anyRequest()// 除上面外的所有请求全部需要鉴权认证 + .authenticated().and().cors().configurationSource(this.corsConfigurationSource()); + // 禁用缓存 + httpSecurity.headers().cacheControl(); + // 添加Logout filter + httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(customLogoutSuccessHandler); + // 添加JWT filter + httpSecurity.addFilterBefore(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class); + // 添加自定义未授权和未登录结果返回 + httpSecurity.exceptionHandling().accessDeniedHandler(customAccessDeniedHandler) + .authenticationEntryPoint(customAuthenticationEntryPoint); + } + + private CorsConfigurationSource corsConfigurationSource() { + CorsConfiguration corsConfiguration = new CorsConfiguration(); + corsConfiguration.setAllowCredentials(true); + corsConfiguration.addAllowedHeader("*"); // 这个得加上,一些复杂的请求方式会带有header,不加上跨域会失效。 + corsConfiguration.addAllowedMethod("*"); + corsConfiguration.addExposedHeader("*"); + corsConfiguration.addAllowedOriginPattern("*"); + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", corsConfiguration); + return source; + } + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder()); + } + + @Bean + @Override + public UserDetailsService userDetailsService() { + // 获取登录用户信息 + return username -> { + SysUserEntity user = sysUserService.selectUserByUserName(username); + if (user != null) { + if (user.getStatus() == 1) { + throw new UsernameNotFoundException("对不起,您的账号:" + username + " 已停用"); + } + // 获取菜单权限 + Set permissionList = menuService.selectMenuPermsByUserId(user.getUserId()); + return new JwtUser(user, permissionList); + } + throw new UsernameNotFoundException("用户名或密码错误"); + }; + } + + /** + * 装载BCrypt密码编码器 + */ + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + /** + * JWT filter + */ + @Bean + public JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter() { + return new JwtAuthenticationTokenFilter(); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/common/security/entity/JwtUser.java --- +package com.starry.admin.common.security.entity; + +import com.starry.admin.modules.system.module.entity.SysUserEntity; +import java.util.Collection; +import java.util.Set; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +/** + * @author admin + */ +public class JwtUser implements UserDetails { + + /** + * 用户ID + */ + private Long userId; + /** + * 登录时间 + */ + private Long loginTime; + + /** + * 用户唯一标识 + */ + private String token; + + /** + * 过期时间 + */ + private Long expireTime; + + /** + * 登录IP地址 + */ + private String ipaddr; + + /** + * 登录地点 + */ + private String loginLocation; + + /** + * 浏览器类型 + */ + private String browser; + + /** + * 操作系统 + */ + private String os; + + /** + * 用户信息 + */ + private SysUserEntity user; + + /** + * 权限列表 + */ + private Set permissions; + + public JwtUser(SysUserEntity user, Set permissions) { + this.user = user; + this.permissions = permissions; + } + + public JwtUser(Long userId, SysUserEntity user, Set permissions) { + this.userId = userId; + this.user = user; + this.permissions = permissions; + } + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + @Override + public Collection getAuthorities() { + return null; + } + + @Override + public String getPassword() { + return user.getPassWord(); + } + + @Override + public String getUsername() { + return user.getUserCode(); + } + + /** + * 账户是否未过期 + **/ + @Override + public boolean isAccountNonExpired() { + return true; + } + + /** + * 账户是否未锁定 + **/ + @Override + public boolean isAccountNonLocked() { + return true; + } + + /** + * 密码是否未过期 + **/ + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + /** + * 账户是否激活 + **/ + @Override + public boolean isEnabled() { + return user.getStatus() == 0; + } + + public Long getLoginTime() { + return loginTime; + } + + public void setLoginTime(Long loginTime) { + this.loginTime = loginTime; + } + + public Set getPermissions() { + return permissions; + } + + public void setPermissions(Set permissions) { + this.permissions = permissions; + } + + public SysUserEntity getUser() { + return user; + } + + public void setUser(SysUserEntity user) { + this.user = user; + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public String getIpaddr() { + return ipaddr; + } + + public void setIpaddr(String ipaddr) { + this.ipaddr = ipaddr; + } + + public String getLoginLocation() { + return loginLocation; + } + + public void setLoginLocation(String loginLocation) { + this.loginLocation = loginLocation; + } + + public String getBrowser() { + return browser; + } + + public void setBrowser(String browser) { + this.browser = browser; + } + + public String getOs() { + return os; + } + + public void setOs(String os) { + this.os = os; + } + + public Long getExpireTime() { + return expireTime; + } + + public void setExpireTime(Long expireTime) { + this.expireTime = expireTime; + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/common/security/filter/JwtAuthenticationTokenFilter.java --- +package com.starry.admin.common.security.filter; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import com.starry.admin.common.component.JwtToken; +import com.starry.admin.common.domain.LoginUser; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity; +import com.starry.admin.modules.clerk.service.impl.PlayClerkUserInfoServiceImpl; +import com.starry.admin.modules.custom.module.entity.PlayCustomUserInfoEntity; +import com.starry.admin.modules.custom.service.impl.PlayCustomUserInfoServiceImpl; +import com.starry.admin.modules.system.module.entity.SysTenantEntity; +import com.starry.admin.modules.system.service.ISysTenantService; +import com.starry.admin.modules.system.service.SysUserService; +import com.starry.admin.modules.weichat.service.WxTokenService; +import com.starry.admin.utils.SecurityUtils; +import com.starry.common.constant.Constants; +import com.starry.common.redis.RedisCache; +import com.starry.common.result.R; +import com.starry.common.result.ResultCodeEnum; +import java.io.IOException; +import java.util.Arrays; +import java.util.Date; +import java.util.HashSet; +import java.util.Set; +import javax.annotation.Resource; +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.validation.constraints.NotNull; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; +import org.springframework.web.filter.OncePerRequestFilter; +import org.springframework.web.servlet.HandlerExceptionResolver; + +/** + * @author admin JWT登录授权过滤器 + * @since 2021/9/6 + */ +@Slf4j +public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { + + @Resource + WxTokenService tokenService; + + @Resource + private JwtToken jwtToken; + + @Resource + @Qualifier("handlerExceptionResolver") + private HandlerExceptionResolver resolver; + + @Resource + private PlayCustomUserInfoServiceImpl customUserInfoService; + + @Resource + private PlayClerkUserInfoServiceImpl clerkUserInfoService; + + @Resource + private ISysTenantService sysTenantService; + + @Resource + private RedisCache redisCache; + @Resource + private SysUserService userService; + + /** + * 不需要登录的的路径 + */ + Set noLoginPathRequired = new HashSet<>(Arrays.asList("/wx/common/area/tree", "/wx/common/file/upload", + "/wx/common/audio/upload", "/wx/oauth2/getConfigAddress", "/wx/clerk/user/queryByPage", + "wx/clerk/user/queryGiftById", "/wx/clerk/user/queryPriceById", "/wx/clerk/user/queryTrendsById", + "wx/clerk/user/queryEvaluateById")); + + @Override + protected void doFilterInternal(@NotNull HttpServletRequest httpServletRequest, + @NotNull HttpServletResponse httpServletResponse, @NotNull FilterChain filterChain) + throws ServletException, IOException { + log.info("url = {}", httpServletRequest.getRequestURI()); + + // 微信支付回调接口,不需要验证 + if ("/wx/pay/jsCallback".equals(httpServletRequest.getServletPath())) { + log.info("微信支付回调,不需要验证"); + filterChain.doFilter(httpServletRequest, httpServletResponse); + } else {// 微信公众号的请求,必须存在tenantkey,否则抛出异常 + if (httpServletRequest.getServletPath().startsWith("/wx/")) { + + String tenantKey = httpServletRequest.getHeader("tenantkey"); + if (StrUtil.isBlank(tenantKey)) { + resolver.resolveException(httpServletRequest, httpServletResponse, null, + new CustomException("tenantkey不能为空")); + return; + } + if (noLoginPathRequired.contains(httpServletRequest.getServletPath())) { + // 非必须登录的请求,验证租户信息是否正常 + String tenantId; + try { + tenantId = getTenantId(null, null, tenantKey); + } catch (Exception e) { + httpServletResponse.setCharacterEncoding("UTF-8"); + httpServletResponse.setContentType("application/json"); + httpServletResponse.getWriter() + .println(JSONUtil.parse(R.error(ResultCodeEnum.UNAUTHORIZED.getCode(), + ResultCodeEnum.UNAUTHORIZED.getMessage()))); + httpServletResponse.getWriter().flush(); + return; + // 返回401‘ + // + // return; + // throw new RuntimeException("token验证失败,需要重新登录"); + } + if (!checkTenantId(tenantId)) { + // 返回500 + resolver.resolveException(httpServletRequest, httpServletResponse, null, + new CustomException("租户信息异常")); + return; + } + SecurityUtils.setTenantId(tenantId); + } else { + String clerkToken = httpServletRequest.getHeader(Constants.CLERK_USER_LOGIN_TOKEN); + String customToken = httpServletRequest.getHeader(Constants.CUSTOM_USER_LOGIN_TOKEN); + String tenantId; + try { + tenantId = getTenantId(clerkToken, customToken, tenantKey); + } catch (Exception e) { + httpServletResponse.setCharacterEncoding("UTF-8"); + httpServletResponse.setContentType("application/json"); + httpServletResponse.getWriter() + .println(JSONUtil.parse(R.error(ResultCodeEnum.UNAUTHORIZED.getCode(), + ResultCodeEnum.UNAUTHORIZED.getMessage()))); + httpServletResponse.getWriter().flush(); + // 返回401 + return; + // throw new CustomException("token验证失败,需要重新登录"); + } + if (!checkTenantId(tenantId)) { + // 返回500 + resolver.resolveException(httpServletRequest, httpServletResponse, null, + new CustomException("租户信息异常")); + return; + } + SecurityUtils.setTenantId(tenantId); + } + } else { + // 管理端的请求 + LoginUser jwtUser = jwtToken.getNewLoginUser(httpServletRequest); + if (null != jwtUser && null == SecurityContextHolder.getContext().getAuthentication()) { + jwtToken.verifyToken(jwtUser); + userService.selectUserById(jwtUser.getUserId()); + UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( + jwtUser, null, jwtUser.getAuthorities()); + authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest)); + SecurityContextHolder.getContext().setAuthentication(authentication); + } + } + filterChain.doFilter(httpServletRequest, httpServletResponse); + } + } + + /** + * 微信公众号端访问时,获取当前用户租户ID 如果用户(陪聊或客户)已登录,从token中获取租户ID 如果用户未登录,从tenantKey中获取租户ID + * + * @param clerkToken + * 陪聊登录Key + * @param customToken + * 客户登录key + * @param tenantKey + * 租户标识 + */ + public String getTenantId(String clerkToken, String customToken, String tenantKey) { + String tenantId = ""; + // 如果用户(陪聊或客户)已登录,从token中获取租户ID + if (StrUtil.isNotBlank(clerkToken) || StrUtil.isNotBlank(customToken)) { + String userId = tokenService.getWxUserIdByToken(StrUtil.isNotBlank(clerkToken) ? clerkToken : customToken); + String redisKey = "TENANT_INFO:" + userId; + SecurityUtils.setTenantId(redisCache.getCacheObject(redisKey)); + if (clerkToken != null) { + PlayClerkUserInfoEntity entity = clerkUserInfoService.selectById(userId); + if (entity == null) { + log.error("当前登录陪聊不存在,clerkToken={},tenantKey={}", clerkToken, tenantKey); + throw new CustomException("用户不存在"); + } + return entity.getTenantId(); + } else { + PlayCustomUserInfoEntity entity = customUserInfoService.selectById(userId); + if (entity == null) { + log.error("当前登录顾客不存在,customToken={},tenantKey={}", customToken, tenantKey); + throw new CustomException("用户不存在"); + } + return entity.getTenantId(); + } + } else { + // 如果用户未登录,从tenantKey中获取租户ID,然后验证租户ID是否存在,以及租户是否过期等 + SysTenantEntity entity = sysTenantService.selectByTenantKey(tenantKey); + if (entity != null) { + return entity.getTenantId(); + } + } + return tenantId; + } + + /** + * 校验租户是否正常 + * + * @param tenantId + * 租户ID + * @return true:租户正常,false:租户不正常 + */ + public boolean checkTenantId(String tenantId) { + if (StrUtil.isBlankIfStr(tenantId)) { + return false; + } + if (tenantId.equals("-1")) { + return true; + } + SysTenantEntity entity = sysTenantService.selectSysTenantByTenantId(tenantId); + if (entity == null) { + return false; + } + // 判断租户是否过期 + if (DateUtil.compare(entity.getTenantTime(), new Date()) < 0) { + return false; + } + // ... + // 校验通过 + return true; + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/common/security/handler/CustomAccessDeniedHandler.java --- +package com.starry.admin.common.security.handler; + +import cn.hutool.json.JSONUtil; +import com.starry.common.result.R; +import com.starry.common.result.ResultCodeEnum; +import java.io.IOException; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.web.access.AccessDeniedHandler; +import org.springframework.stereotype.Component; + +/** + * @author admin 当访问接口没有权限时,自定义的返回结果 + * @since 2021/9/6 + */ +@Component +public class CustomAccessDeniedHandler implements AccessDeniedHandler { + + @Override + public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, + AccessDeniedException e) throws IOException, ServletException { + httpServletResponse.setCharacterEncoding("UTF-8"); + httpServletResponse.setContentType("application/json"); + httpServletResponse.getWriter().println( + JSONUtil.parse(R.error(ResultCodeEnum.FORBIDDEN.getCode(), ResultCodeEnum.FORBIDDEN.getMessage()))); + httpServletResponse.getWriter().flush(); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/common/security/handler/CustomAuthenticationEntryPoint.java --- +package com.starry.admin.common.security.handler; + +import cn.hutool.json.JSONUtil; +import com.starry.common.result.R; +import com.starry.common.result.ResultCodeEnum; +import java.io.IOException; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.stereotype.Component; + +/** + * @author admin 当未登录或者token失效访问接口时,自定义的返回结果 + * @since 2021/9/6 + */ +@Component +public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint { + @Override + public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, + AuthenticationException e) throws IOException, ServletException { + httpServletResponse.setCharacterEncoding("UTF-8"); + httpServletResponse.setContentType("application/json"); + httpServletResponse.getWriter().println(JSONUtil + .parse(R.error(ResultCodeEnum.UNAUTHORIZED.getCode(), ResultCodeEnum.UNAUTHORIZED.getMessage()))); + httpServletResponse.getWriter().flush(); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/common/security/handler/CustomLogoutSuccessHandler.java --- +package com.starry.admin.common.security.handler; + +import com.alibaba.fastjson2.JSON; +import com.starry.admin.common.component.JwtToken; +import com.starry.admin.common.security.entity.JwtUser; +import com.starry.admin.manager.AsyncManager; +import com.starry.admin.manager.factory.AsyncFactory; +import com.starry.common.constant.Constants; +import com.starry.common.result.R; +import com.starry.common.utils.ServletUtils; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; +import org.springframework.stereotype.Component; + +/** + * @author admin 自定义退出处理类 返回成功 + * @since 2022/7/8 + */ +@Component +public class CustomLogoutSuccessHandler implements LogoutSuccessHandler { + + @Resource + private JwtToken jwtToken; + + @Override + public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, + Authentication authentication) { + JwtUser jwtUser = jwtToken.getLoginUser(httpServletRequest); + if (null != jwtUser) { + // 删除用户缓存记录 + jwtToken.removeJwtUser(jwtUser.getToken()); + // 记录用户退出日志 + AsyncManager.me().execute(AsyncFactory.recordLoginLog(jwtUser.getUsername(), Constants.LOGOUT, "退出成功")); + } + ServletUtils.renderString(httpServletResponse, JSON.toJSONString(R.ok("退出成功"))); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/common/task/ClerkPkJob.java --- +package com.starry.admin.common.task; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.starry.admin.modules.clerk.module.entity.ClerkPkEnum; +import com.starry.admin.modules.clerk.module.entity.PlayClerkPkEntity; +import com.starry.admin.modules.clerk.service.IPlayClerkPkService; +import java.util.Date; +import javax.annotation.Resource; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +/** + * @Author: huchuansai + * @Date: 2024/8/2 4:31 PM + * @Description: + */ +@Component +public class ClerkPkJob { + + @Resource + private IPlayClerkPkService playClerkPkService; + + @Scheduled(fixedRate = 60000) + public void pkJobStatus() { + // 更新状态将待开始的状态改为进行中 + playClerkPkService.update(Wrappers.lambdaUpdate(PlayClerkPkEntity.class) + .eq(PlayClerkPkEntity::getStatus, ClerkPkEnum.TO_BE_STARTED.name()) + .le(PlayClerkPkEntity::getPkBeginTime, new Date()) + .set(PlayClerkPkEntity::getStatus, ClerkPkEnum.IN_PROGRESS.name())); + + playClerkPkService.update(Wrappers.lambdaUpdate(PlayClerkPkEntity.class) + .eq(PlayClerkPkEntity::getStatus, ClerkPkEnum.IN_PROGRESS.name()) + .le(PlayClerkPkEntity::getPkEndTime, new Date()) + .set(PlayClerkPkEntity::getStatus, ClerkPkEnum.FINISHED.name())); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/common/task/ClerkWagesSettlementTask.java --- +package com.starry.admin.common.task; + +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity; +import com.starry.admin.modules.clerk.module.entity.PlayClerkWagesDetailsInfoEntity; +import com.starry.admin.modules.clerk.module.entity.PlayClerkWagesInfoEntity; +import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService; +import com.starry.admin.modules.clerk.service.IPlayClerkWagesDetailsInfoService; +import com.starry.admin.modules.clerk.service.IPlayClerkWagesInfoService; +import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity; +import com.starry.admin.modules.order.service.IPlayOrderInfoService; +import com.starry.admin.modules.system.module.entity.SysTenantEntity; +import com.starry.admin.modules.system.service.ISysTenantService; +import com.starry.admin.utils.SecurityUtils; +import com.starry.common.utils.IdUtils; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.List; +import javax.annotation.Resource; +import org.springframework.stereotype.Component; + +/** + * 订单工资结算 + * + * @author admin + * @since 2024/5/28 下午2:42 + **/ +@Component +public class ClerkWagesSettlementTask { + + @Resource + ISysTenantService sysTenantService; + + @Resource + private IPlayClerkUserInfoService clerkUserInfoService; + + @Resource + private IPlayOrderInfoService playOrderInfoService; + + @Resource + private IPlayClerkWagesInfoService playClerkWagesInfoService; + + @Resource + private IPlayClerkWagesDetailsInfoService playClerkWagesDetailsInfoService; + + /** + * 每分钟查询未结算订单 如果订单完成时间超过24小时,可进行结算,生成工资 + */ + // @Scheduled(cron = "0 0/1 * * * ?") + public void dailyRanking() { + // 1、查询所有的租户信息 + List tenantEntities = sysTenantService.listAll(); + for (SysTenantEntity tenantEntity : tenantEntities) { + SecurityUtils.setTenantId(tenantEntity.getTenantId()); + List clerkUserReturnVos = clerkUserInfoService.listAll(); + // 生成每个人的工资信息 + for (PlayClerkUserInfoEntity clerkUserInfo : clerkUserReturnVos) { + updateClerkWagesInfo(clerkUserInfo.getId()); + } + } + } + + /** + * 活动24小时前完成的订单,对订单进行结算 + * + * @param clerkId + * 店员ID + */ + public void updateClerkWagesInfo(String clerkId) { + // 获得24小时前完成,并且未结算的订单 + LocalDateTime lastTime = LocalDateTime.now().minusDays(1); + // 查询当前店员上次结算工资到现在的订单 + List orderInfoEntities = playOrderInfoService.listByEndTime(clerkId, lastTime); + PlayClerkWagesInfoEntity entity = playClerkWagesInfoService.getLastSettlement(clerkId); + // 更新订单信息 + updateClerkWagesInfo(clerkId, entity == null ? IdUtils.getUuid() : entity.getId(), orderInfoEntities); + } + + /** + * 更新最新一次工资统计信息 更新订单记录 + * + * @param orderInfoEntities + * 订单列表 + */ + public void updateClerkWagesInfo(String clerkId, String wagesId, List orderInfoEntities) { + // 修改订单状态并且新增订单结算详情 + for (PlayOrderInfoEntity orderInfo : orderInfoEntities) { + // 修改订单状态 + orderInfo.setOrderSettlementState("1"); + orderInfo.setOrderSettlementTime(LocalDateTime.now()); + playOrderInfoService.update(orderInfo); + + PlayClerkWagesDetailsInfoEntity wagesDetailsInfo = playClerkWagesDetailsInfoService + .selectByOrderId(orderInfo.getId()); + if (wagesDetailsInfo == null) { + wagesDetailsInfo = new PlayClerkWagesDetailsInfoEntity(); + wagesDetailsInfo.setId(IdUtils.getUuid()); + } + // 新增订单结算详情 + wagesDetailsInfo.setWagesId(wagesId); + wagesDetailsInfo.setClerkId(clerkId); + wagesDetailsInfo.setOrderId(orderInfo.getId()); + wagesDetailsInfo.setOrderNo(orderInfo.getOrderNo()); + wagesDetailsInfo.setFinalAmount(orderInfo.getFinalAmount()); + wagesDetailsInfo.setEstimatedRevenue(orderInfo.getEstimatedRevenue()); + wagesDetailsInfo.setEndOrderTime(orderInfo.getOrderEndTime()); + playClerkWagesDetailsInfoService.saveOrUpdate(wagesDetailsInfo); + } + // 新增订单结算信息 + BigDecimal finalAmount = BigDecimal.ZERO; + Integer orderContinueNumber = 0; + BigDecimal orderContinueMoney = BigDecimal.ZERO; + Integer ordersExpiredNumber = 0; + BigDecimal estimatedRevenue = BigDecimal.ZERO; + Integer orderNumber = 0; + LocalDate lastTime = playClerkWagesInfoService.getLastSettlementTime(clerkId); + for (PlayClerkWagesDetailsInfoEntity entity : playClerkWagesDetailsInfoService.selectByWagesId(wagesId)) { + PlayOrderInfoEntity orderInfo = playOrderInfoService.selectOrderInfoById(entity.getOrderId()); + finalAmount = finalAmount.add(orderInfo.getFinalAmount()); + orderNumber++; + estimatedRevenue = estimatedRevenue.add(orderInfo.getEstimatedRevenue()); + if ("0".equals(orderInfo.getFirstOrder())) { + orderContinueNumber++; + orderContinueMoney = orderContinueMoney.add(orderInfo.getFinalAmount()); + } + if ("1".equals(orderInfo.getOrdersExpiredState())) { + ordersExpiredNumber++; + } + } + + PlayClerkWagesInfoEntity wagesInfo = new PlayClerkWagesInfoEntity(); + wagesInfo.setId(wagesId); + wagesInfo.setClerkId(clerkId); + wagesInfo.setStartCountDate(lastTime); + wagesInfo.setEndCountDate(LocalDate.now()); + wagesInfo.setOrderNumber(orderNumber); + wagesInfo.setFinalAmount(finalAmount); + wagesInfo.setOrderContinueNumber(orderContinueNumber); + wagesInfo.setOrderContinueMoney(orderContinueMoney); + wagesInfo.setOrdersExpiredNumber(ordersExpiredNumber); + wagesInfo.setSettlementDate(LocalDate.now()); + wagesInfo.setEstimatedRevenue(estimatedRevenue); + if (ChronoUnit.DAYS.between(LocalDate.now(), lastTime) <= 7) { + wagesInfo.setHistoricalStatistics("0"); + } else { + wagesInfo.setHistoricalStatistics("1"); + } + + playClerkWagesInfoService.saveOrUpdate(wagesInfo); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/common/task/OrderRankingSettlementTask.java --- +package com.starry.admin.common.task; + +import com.starry.admin.modules.clerk.module.entity.PlayClerkRankingInfoEntity; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity; +import com.starry.admin.modules.clerk.service.IPlayClerkRankingInfoService; +import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService; +import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity; +import com.starry.admin.modules.order.service.IPlayOrderInfoService; +import com.starry.admin.modules.system.module.entity.SysTenantEntity; +import com.starry.admin.modules.system.service.ISysTenantService; +import com.starry.admin.utils.SecurityUtils; +import com.starry.common.utils.IdUtils; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import javax.annotation.Resource; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +/** + * 订单排名结算信息 + * + * @author admin + * @since 2024/5/28 下午2:42 + **/ +@Component +public class OrderRankingSettlementTask { + + @Resource + ISysTenantService sysTenantService; + + @Resource + private IPlayClerkUserInfoService clerkUserInfoService; + + @Resource + private IPlayOrderInfoService orderInfoService; + + @Resource + private IPlayClerkRankingInfoService clerkRankingInfoService; + + DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + + /** + * 当日订单结算,查询前一日的订单信息,生成订单排名数据 每天凌晨0点5分0秒时触发执行 + */ + @Scheduled(cron = "0 5 0 * * ?") + public void dailyRanking() { + DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + String startTime = LocalDate.now().minusDays(1).atStartOfDay().format(df); + String endTime = LocalDateTime.of(LocalDate.now().minusDays(1), LocalTime.MAX).format(df); + rankingSettlement(startTime, endTime, "0"); + } + + /** + * 每周订单结算,周一凌晨30分执行,查询上一周的订单,然后生成订单排行数据 每周一凌晨0点30分0秒时触发执行 + */ + @Scheduled(cron = "0 30 0 ? * MON") + public void weeklyRankingSettlement() { + + String startTime = LocalDate.now().minusDays(8).atStartOfDay().format(df); + String endTime = LocalDateTime.of(LocalDate.now().minusDays(1), LocalTime.MAX).format(df); + rankingSettlement(startTime, endTime, "1"); + } + + /** + * 生产排行信息 1、查询所有的租户信息 2、查询每个租户的用户,以及他们在对应时间段的订单 3、根据订单生产排行信息 + * + * @param startTime + * 接单开始时间 + * @param endTime + * 接单截至时间 + * @param weeklyRanking + * weeklyRanking 日排名还是周排名(0:每日排名;1:每周排名) + * @author admin + * @since 2024/6/12 15:21 + **/ + public void rankingSettlement(String startTime, String endTime, String weeklyRanking) { + // 1、查询所有的租户信息 + List tenantEntities = sysTenantService.listAll(); + // 2、查询每个租户的用户,以及他们的订单信息 + for (SysTenantEntity tenantEntity : tenantEntities) { + SecurityUtils.setTenantId(tenantEntity.getTenantId()); + // 当前租户用户列表 + List clerkUserReturnVos = clerkUserInfoService.listAll(); + List clerkRankingInfoEntities = new ArrayList<>(); + // 查询当前租户、当前排行、的最后一次统计编号 + Integer newSerialNumber = clerkRankingInfoService.selectSerialNumber(weeklyRanking); + // 生成每个人的订单排行信息 + for (PlayClerkUserInfoEntity clerkUserInfo : clerkUserReturnVos) { + // 生成订单排行数据 + clerkRankingInfoEntities.add( + getClerkRanking(clerkUserInfo.getId(), startTime, endTime, weeklyRanking, newSerialNumber)); + } + // 更新排行名次 + clerkRankingInfoEntities.sort((p1, p2) -> p2.getOrderNumber() - p1.getOrderNumber()); + for (int i = 0; i < clerkRankingInfoEntities.size(); i++) { + PlayClerkRankingInfoEntity item = clerkRankingInfoEntities.get(i); + item.setRankingIndex(i + 1); + if (i > 0) { + item.setPreviousMoney( + clerkRankingInfoEntities.get(i - 1).getOrderMoney().subtract(item.getOrderMoney())); + } + } + // 排名数据生成后,将以往排名状态标记为历史排名 + clerkRankingInfoService.updateClerkRankingInfo(weeklyRanking, newSerialNumber); + // 插入本次排名数据 + clerkRankingInfoService.saveBatch(clerkRankingInfoEntities); + } + } + + /** + * 生产当前排行信息 + * + * @param clerkId + * 店员ID + * @param startTime + * 排行开始统计日期 yyyy-mm-dd 00:00:00 + * @param endTime + * 排行结束统计日期 yyyy-mm-dd 23:59:59 + * @param weeklyRanking + * 日排名还是周排名(0:每日排名;1:每周排名) + * @param serialNumber + * 查询当前租户、当前排行、的最后一次统计编号 + * @author admin + * @since 2024/6/7 11:43 + **/ + public PlayClerkRankingInfoEntity getClerkRanking(String clerkId, String startTime, String endTime, + String weeklyRanking, Integer serialNumber) { + List orderInfoEntities = orderInfoService.listByTime(clerkId, startTime, endTime, null); + int orderNumber = orderInfoEntities.size(); + BigDecimal orderMoney = BigDecimal.ZERO; + Integer orderContinueNumber = 0; + BigDecimal orderContinueMoney = BigDecimal.ZERO; + int ordersExpiredNumber = 0; + Set customIds = new HashSet<>(); + for (PlayOrderInfoEntity orderInfoEntity : orderInfoEntities) { + customIds.add(orderInfoEntity.getAcceptBy()); + orderMoney = orderMoney.add(orderInfoEntity.getOrderMoney()); + if ("0".equals(orderInfoEntity.getFirstOrder())) { + orderContinueNumber++; + orderContinueMoney = orderContinueMoney.add(orderInfoEntity.getOrderMoney()); + } + if ("1".equals(orderInfoEntity.getOrdersExpiredState())) { + ordersExpiredNumber++; + } + } + BigDecimal orderContinueProportion = orderNumber == 0 + ? BigDecimal.ZERO + : new BigDecimal(ordersExpiredNumber).divide(new BigDecimal(orderNumber), 4, RoundingMode.HALF_UP) + .add(new BigDecimal(100)); + BigDecimal averageUnitPrice = customIds.isEmpty() + ? BigDecimal.ZERO + : orderMoney.divide(new BigDecimal(customIds.size()), 4, RoundingMode.HALF_UP); + PlayClerkRankingInfoEntity rankingInfo = new PlayClerkRankingInfoEntity(); + rankingInfo.setId(IdUtils.getUuid()); + rankingInfo.setClerkId(clerkId); + // 默认为当前统计 + rankingInfo.setHistoricalStatistics("0"); + rankingInfo.setWeeklyRanking(weeklyRanking); + // 当前统计编号+1 + rankingInfo.setSerialNumber(serialNumber + 1); + // 每个人的名次默认为1,后面在进行排序更新名次 + rankingInfo.setRankingIndex(1); + // 统计时间 + rankingInfo.setStartCountDate(LocalDate.parse(startTime, df)); + rankingInfo.setEndCountDate(LocalDate.parse(endTime, df)); + rankingInfo.setOrderNumber(orderInfoEntities.size()); + rankingInfo.setOrderMoney(orderMoney); + rankingInfo.setOrderContinueMoney(orderContinueMoney); + rankingInfo.setOrderContinueNumber(orderContinueNumber); + rankingInfo.setOrderContinueProportion(orderContinueProportion); + rankingInfo.setOrdersExpiredNumber(ordersExpiredNumber); + rankingInfo.setCustomNumber(customIds.size()); + rankingInfo.setAverageUnitPrice(averageUnitPrice); + rankingInfo.setPreviousMoney(BigDecimal.ZERO); + rankingInfo.setSettlementDate(LocalDate.now()); + return rankingInfo; + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/common/task/OverdueOrderHandlerTask.java --- +package com.starry.admin.common.task; + +import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity; +import com.starry.admin.modules.order.service.IPlayOrderInfoService; +import com.starry.admin.utils.SecurityUtils; +import java.util.ArrayList; +import java.util.Set; +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +/** + * 超时未接单的订单退款处理任务 + * + * @author admin + * @since 2024/8/15 13:24 + **/ +@Slf4j +@Component +public class OverdueOrderHandlerTask { + + private static final String QUEUE_KEY = "random_order_queue"; + + private static final int MAX_TIME = 24 * 60 * 40; + + @Resource + private StringRedisTemplate stringRedisTemplate; + + @Resource + private IPlayOrderInfoService playOrderInfoService; + + public void enqueue(String message) { + enqueue(message, MAX_TIME); + } + + public void enqueue(String message, long delaySeconds) { + long score = System.currentTimeMillis() / 1000 + delaySeconds; + stringRedisTemplate.opsForZSet().add(QUEUE_KEY, message, score); + } + + /** + * 每10秒钟检测,判断任务是否到期 + * + * @author admin + * @since 2024/8/15 13:47 + **/ + @Scheduled(fixedRate = 10000) + public void processMessages() { + long now = System.currentTimeMillis() / 1000; + Set messages = stringRedisTemplate.opsForZSet().rangeByScore(QUEUE_KEY, 0, now); + if (messages == null) { + return; + } + for (String message : messages) { + log.info("处理消息{}", message); + // 处理消息 + // 订单退款 + String[] strs = message.split("_"); + orderHandler(strs[0], strs[1]); + // 移除已经处理的消息 + stringRedisTemplate.opsForZSet().remove(QUEUE_KEY, message); + } + } + + public void orderHandler(String orderId, String tenantId) { + SecurityUtils.setTenantId(tenantId); + PlayOrderInfoEntity orderInfo = playOrderInfoService.getById(orderId); + if (orderInfo == null) { + return; + } + // 如果订单未接单,进行退款处理 + if ("0".equals(orderInfo.getOrderStatus())) { + try { + playOrderInfoService.updateStateTo4("2", "admin", orderInfo.getId(), "订单长时间未接单", new ArrayList<>()); + } catch (Exception e) { + log.error("订单退款失败", e); + } + + } + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/manager/AsyncManager.java --- +package com.starry.admin.manager; + +import com.starry.common.utils.SpringUtils; +import com.starry.common.utils.ThreadsUtils; +import java.util.TimerTask; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +/** + * @author admin 异步任务管理器 + * @since 2022/7/25 + */ +public class AsyncManager { + + private static final AsyncManager me = new AsyncManager(); + /** + * 操作延迟10毫秒 + */ + private final int OPERATE_DELAY_TIME = 10; + /** + * 异步操作任务调度线程池 + */ + private final ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService"); + + /** + * 单例模式 + */ + private AsyncManager() { + } + + public static AsyncManager me() { + return me; + } + + /** + * 执行任务 + * + * @param task + * 任务 + */ + public void execute(TimerTask task) { + executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS); + } + + /** + * 停止任务线程池 + */ + public void shutdown() { + ThreadsUtils.shutdownAndAwaitTermination(executor); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/manager/ShutdownManager.java --- +package com.starry.admin.manager; + +import javax.annotation.PreDestroy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +/** + * 确保应用退出时能关闭后台线程 + * + * @author ruoyi + */ +@Component +public class ShutdownManager { + private static final Logger logger = LoggerFactory.getLogger("sys-user"); + + @PreDestroy + public void destroy() { + shutdownAsyncManager(); + } + + /** + * 停止异步执行任务 + */ + private void shutdownAsyncManager() { + try { + logger.info("====关闭后台任务任务线程池===="); + AsyncManager.me().shutdown(); + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/manager/factory/AsyncFactory.java --- +package com.starry.admin.manager.factory; + +import cn.hutool.extra.servlet.ServletUtil; +import cn.hutool.http.useragent.UserAgent; +import cn.hutool.http.useragent.UserAgentUtil; +import com.starry.admin.modules.system.module.entity.SysLoginLogEntity; +import com.starry.admin.modules.system.service.ISysLoginLogService; +import com.starry.common.constant.Constants; +import com.starry.common.utils.ServletUtils; +import com.starry.common.utils.SpringUtils; +import com.starry.common.utils.ip.AddressUtils; +import java.util.Date; +import java.util.TimerTask; +import lombok.extern.slf4j.Slf4j; + +/** + * @author admin + */ +@Slf4j +public class AsyncFactory { + + /** + * 记录登录信息 + * + * @param username + * 用户名 + * @param status + * 状态 + * @param message + * 消息 + * @param args + * 列表 + * @return 任务task + */ + public static TimerTask recordLoginLog(final String username, final String status, final String message, + final Object... args) { + // 客户端操作系统、浏览器等信息 + final UserAgent userAgent = UserAgentUtil.parse(ServletUtils.getRequest().getHeader("User-Agent")); + // 请求的IP地址 + final String ip = ServletUtil.getClientIP(ServletUtils.getRequest()); + return new TimerTask() { + @Override + public void run() { + String address = AddressUtils.getRealAddressByIp(ip); + // 获取客户端操作系统 + String os = userAgent.getOs().getName(); + // 获取客户端浏览器 + String browser = userAgent.getBrowser().getName(); + // 封装对象 + SysLoginLogEntity loginLog = new SysLoginLogEntity(); + loginLog.setUserCode(username); + loginLog.setIpaddr(ip); + loginLog.setLoginLocation(address); + loginLog.setBrowser(browser); + loginLog.setOs(os); + loginLog.setMsg(message); + loginLog.setLoginTime(new Date()); + // 日志状态 + if (Constants.LOGIN_FAIL.equals(status)) { + loginLog.setStatus(Integer.valueOf(Constants.FAIL)); + } else { + loginLog.setStatus(Integer.valueOf(Constants.SUCCESS)); + } + // 插入数据 + SpringUtils.getBean(ISysLoginLogService.class).create(loginLog); + } + }; + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/controller/PlayAvatarFrameInfoController.java --- +package com.starry.admin.modules.clerk.controller; + +import com.starry.admin.common.oss.service.IOssFileService; +import com.starry.admin.modules.clerk.module.entity.PlayAvatarFrameInfoEntity; +import com.starry.admin.modules.clerk.module.vo.PlayAvatarFrameInfoAddVo; +import com.starry.admin.modules.clerk.module.vo.PlayAvatarFrameInfoQueryVo; +import com.starry.admin.modules.clerk.module.vo.PlayAvatarFrameSendVo; +import com.starry.admin.modules.clerk.service.IPlayAvatarFrameInfoService; +import com.starry.admin.utils.SecurityUtils; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import com.starry.common.utils.ConvertUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.io.IOException; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +/** + * 店员头像框Controller + * + * @author admin + * @since 2024-06-06 + */ +@Api(tags = "店员头像框管理", description = "店员头像框信息管理相关接口,包括查询、新增、修改、删除和赠送等操作") +@RestController +@RequestMapping("/clerk/avatarFrame") +public class PlayAvatarFrameInfoController { + @Resource + private IPlayAvatarFrameInfoService playAvatarFrameInfoService; + + @Resource + private IOssFileService ossFileService; + + @ApiOperation(value = "分页查询头像框", notes = "分页查询店员头像框信息列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayAvatarFrameInfoEntity.class, responseContainer = "Page")}) + @PostMapping("/listByPage") + public R listByPage( + @ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayAvatarFrameInfoQueryVo vo) { + return R.ok(playAvatarFrameInfoService.selectByPage(vo)); + } + + /** + * 查询店员头像框列表 + */ + @ApiOperation(value = "查询所有头像框", notes = "获取所有店员头像框信息列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayAvatarFrameInfoEntity.class, responseContainer = "List")}) + @GetMapping("/listAll") + public R listAll() { + return R.ok(playAvatarFrameInfoService.selectAll()); + } + + @ApiOperation(value = "上传头像框图片", notes = "上传店员头像框图片文件") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = String.class, responseContainer = "R")}) + @PostMapping("/uploadFile") + public R uploadFile(@ApiParam(value = "图片文件", required = true) @RequestParam("file") MultipartFile file) + throws IOException { + String fileAddress = ossFileService.upload(file.getInputStream(), SecurityUtils.getTenantId(), + file.getOriginalFilename()); + return R.ok(fileAddress); + } + + /** + * 新增店员头像框 + */ + @ApiOperation(value = "新增头像框", notes = "创建新的店员头像框信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "添加失败")}) + @Log(title = "店员头像框", businessType = BusinessType.INSERT) + @PostMapping("/create") + public R create(@ApiParam(value = "头像框信息", required = true) @Validated @RequestBody PlayAvatarFrameInfoAddVo vo) { + boolean success = playAvatarFrameInfoService + .create(ConvertUtil.entityToVo(vo, PlayAvatarFrameInfoEntity.class)); + if (success) { + return R.ok(); + } + return R.error("添加失败"); + } + + /** + * 修改店员头像框 + */ + @ApiOperation(value = "修改头像框", notes = "根据ID修改店员头像框信息") + @ApiImplicitParam(name = "id", value = "头像框ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败")}) + @Log(title = "店员头像框", businessType = BusinessType.UPDATE) + @PostMapping(value = "/update/{id}") + public R update(@PathVariable String id, + @ApiParam(value = "头像框信息", required = true) @RequestBody PlayAvatarFrameInfoEntity playAvatarFrameInfo) { + playAvatarFrameInfo.setId(id); + boolean success = playAvatarFrameInfoService.update(playAvatarFrameInfo); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + /** + * 删除店员头像框 + */ + @ApiOperation(value = "删除头像框", notes = "根据ID批量删除店员头像框信息") + @ApiImplicitParam(name = "ids", value = "头像框ID数组", required = true, paramType = "path", dataType = "String[]", example = "1,2,3") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Integer.class)}) + @Log(title = "店员头像框", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@PathVariable String[] ids) { + return R.ok(playAvatarFrameInfoService.deletePlayAvatarFrameInfoByIds(ids)); + } + + /** + * 新增店员头像框 + */ + @ApiOperation(value = "赠送头像框", notes = "赠送头像框给指定店员") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "添加失败")}) + @Log(title = "赠送店员头像框", businessType = BusinessType.INSERT) + @PostMapping("/sendAvatarFrame") + public R sendAvatarFrame( + @ApiParam(value = "赠送信息", required = true) @Validated @RequestBody PlayAvatarFrameSendVo vo) { + return R.error("添加失败"); + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/controller/PlayClerkArticleInfoController.java --- +package com.starry.admin.modules.clerk.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.modules.clerk.module.entity.PlayClerkArticleInfoEntity; +import com.starry.admin.modules.clerk.module.vo.PlayClerkArticleQueryVo; +import com.starry.admin.modules.clerk.module.vo.PlayClerkArticleReturnVo; +import com.starry.admin.modules.clerk.module.vo.PlayClerkArticleReviewStateEditVo; +import com.starry.admin.modules.clerk.service.IPlayClerkArticleInfoService; +import com.starry.admin.modules.clerk.service.IPlayCustomArticleInfoService; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import com.starry.common.utils.ConvertUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 店员动态信息Controller + * + * @author admin + * @since 2024-05-04 + */ +@Api(tags = "店员动态管理", description = "店员动态信息管理相关接口,包括查询、审核和删除等操作") +@RestController +@RequestMapping("/clerk/article") +public class PlayClerkArticleInfoController { + @Resource + private IPlayClerkArticleInfoService playClerkArticleInfoService; + @Resource + private IPlayCustomArticleInfoService playCustomArticleInfoService; + + /** + * 查询店员动态信息列表 + */ + @ApiOperation(value = "分页查询动态列表", notes = "分页查询店员动态信息列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayClerkArticleReturnVo.class, responseContainer = "Page")}) + @PostMapping("/listByPage") + public R list(@ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayClerkArticleQueryVo vo) { + IPage list = playClerkArticleInfoService.selectByPage(vo, false); + return R.ok(list); + } + + /** + * 修改店员动态信息 + */ + @ApiOperation(value = "修改动态审核状态", notes = "更新店员动态审核状态,通过或拒绝") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败")}) + // @PreAuthorize("@customSs.hasPermission('clerk:article:update')") + @Log(title = "店员动态信息", businessType = BusinessType.UPDATE) + @PostMapping(value = "/update") + public R update(@ApiParam(value = "审核状态信息", required = true) @RequestBody PlayClerkArticleReviewStateEditVo vo) { + PlayClerkArticleInfoEntity entity = ConvertUtil.entityToVo(vo, PlayClerkArticleInfoEntity.class); + boolean success = playClerkArticleInfoService.update(entity); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + /** + * 删除店员动态信息 + */ + @ApiOperation(value = "删除动态", notes = "根据ID批量删除店员动态信息") + @ApiImplicitParam(name = "ids", value = "动态ID数组", required = true, paramType = "path", dataType = "String[]", example = "1,2,3") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + // @PreAuthorize("@customSs.hasPermission('clerk:article:delete')") + @Log(title = "店员动态信息", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@PathVariable String[] ids) { + for (String id : ids) { + playClerkArticleInfoService.deletePlayClerkArticleInfoById(id); + playCustomArticleInfoService.deleteByArticleId(id); + } + return R.ok(); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/controller/PlayClerkClassificationInfoController.java --- +package com.starry.admin.modules.clerk.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.modules.clerk.module.entity.PlayClerkClassificationInfoEntity; +import com.starry.admin.modules.clerk.service.IPlayClerkClassificationInfoService; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.util.List; +import javax.annotation.Resource; +import org.springframework.web.bind.annotation.*; + +/** + * 店员分类Controller + * + * @author admin + * @since 2024-04-06 + */ +@Api(tags = "店员分类管理", description = "店员分类信息管理相关接口,包括查询、新增、修改和删除等操作") +@RestController +@RequestMapping("/clerk/class") +public class PlayClerkClassificationInfoController { + @Resource + private IPlayClerkClassificationInfoService playClerkClassificationInfoService; + + /** + * 查询店员分类列表 + */ + @ApiOperation(value = "查询所有分类", notes = "获取所有店员分类信息列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayClerkClassificationInfoEntity.class, responseContainer = "List")}) + @GetMapping("/listAll") + public R listAll() { + List list = playClerkClassificationInfoService.selectAll(); + return R.ok(list); + } + + /** + * 查询店员分类列表 + */ + @ApiOperation(value = "分页查询分类", notes = "分页查询店员分类信息列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayClerkClassificationInfoEntity.class, responseContainer = "Page")}) + @GetMapping("/list") + public R list(@ApiParam(value = "查询条件") PlayClerkClassificationInfoEntity playClerkClassificationInfo) { + IPage list = playClerkClassificationInfoService + .selectPlayClerkClassificationInfoByPage(playClerkClassificationInfo); + return R.ok(list); + } + + /** + * 获取店员分类详细信息 + */ + @ApiOperation(value = "获取分类详情", notes = "根据ID获取店员分类详细信息") + @ApiImplicitParam(name = "id", value = "分类ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = PlayClerkClassificationInfoEntity.class)}) + @GetMapping(value = "/{id}") + public R getInfo(@PathVariable("id") String id) { + return R.ok(playClerkClassificationInfoService.selectPlayClerkClassificationInfoById(id)); + } + + /** + * 新增店员分类 + */ + @ApiOperation(value = "新增分类", notes = "创建新的店员分类信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "添加失败")}) + @Log(title = "店员分类", businessType = BusinessType.INSERT) + @PostMapping("/create") + public R create( + @ApiParam(value = "分类信息", required = true) @RequestBody PlayClerkClassificationInfoEntity playClerkClassificationInfo) { + boolean success = playClerkClassificationInfoService.create(playClerkClassificationInfo); + if (success) { + return R.ok(); + } + return R.error("添加失败"); + } + + /** + * 修改店员分类 + */ + @ApiOperation(value = "修改分类", notes = "根据ID修改店员分类信息") + @ApiImplicitParam(name = "id", value = "分类ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败")}) + @Log(title = "店员分类", businessType = BusinessType.UPDATE) + @PostMapping(value = "/update/{id}") + public R update(@PathVariable String id, + @ApiParam(value = "分类信息", required = true) @RequestBody PlayClerkClassificationInfoEntity playClerkClassificationInfo) { + playClerkClassificationInfo.setId(id); + boolean success = playClerkClassificationInfoService.update(playClerkClassificationInfo); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + /** + * 删除店员分类 + */ + @ApiOperation(value = "删除分类", notes = "根据ID批量删除店员分类信息") + @ApiImplicitParam(name = "ids", value = "分类ID数组", required = true, paramType = "path", dataType = "String[]", example = "1,2,3") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Integer.class)}) + @Log(title = "店员分类", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@PathVariable String[] ids) { + return R.ok(playClerkClassificationInfoService.deletePlayClerkClassificationInfoByIds(ids)); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/controller/PlayClerkCommodityController.java --- +package com.starry.admin.modules.clerk.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.modules.clerk.module.entity.PlayClerkCommodityEntity; +import com.starry.admin.modules.clerk.module.vo.PlayClerkCommodityQueryVo; +import com.starry.admin.modules.clerk.service.IPlayClerkCommodityService; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import com.starry.common.utils.ConvertUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.util.List; +import javax.annotation.Resource; +import org.springframework.web.bind.annotation.*; + +/** + * 陪聊服务项目Controller + * + * @author admin + * @since 2024-03-31 + */ +@Api(tags = "陪聊服务项目", description = "陪聊服务项目管理相关接口,包括查询、新增、修改和删除等操作") +@RestController +@RequestMapping("/clerk/commodity") +public class PlayClerkCommodityController { + @Resource + private IPlayClerkCommodityService playClerkCommodityService; + + /** + * 查询陪聊服务项目列表 + */ + @ApiOperation(value = "查询所有服务项目", notes = "获取所有陪聊服务项目列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayClerkCommodityQueryVo.class, responseContainer = "List")}) + @GetMapping("/listAllCommodity") + public R listAllCommodity() { + List list = playClerkCommodityService.selectAll(); + return R.ok(ConvertUtil.entityToVoList(list, PlayClerkCommodityQueryVo.class)); + } + + /** + * 查询陪聊服务项目列表 + */ + @ApiOperation(value = "分页查询服务项目", notes = "分页查询陪聊服务项目列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayClerkCommodityEntity.class, responseContainer = "Page")}) + @GetMapping("/list") + public R list(@ApiParam(value = "查询条件") PlayClerkCommodityEntity playClerkCommodity) { + IPage list = playClerkCommodityService + .selectPlayClerkCommodityByPage(playClerkCommodity); + return R.ok(list); + } + + /** + * 获取陪聊服务项目详细信息 + */ + @ApiOperation(value = "获取服务项目详情", notes = "根据ID获取陪聊服务项目详细信息") + @ApiImplicitParam(name = "id", value = "服务项目ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = PlayClerkCommodityEntity.class)}) + @GetMapping(value = "/{id}") + public R getInfo(@PathVariable("id") String id) { + return R.ok(playClerkCommodityService.selectPlayClerkCommodityById(id)); + } + + /** + * 新增陪聊服务项目 + */ + @ApiOperation(value = "新增服务项目", notes = "创建新的陪聊服务项目") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "添加失败")}) + @Log(title = "陪聊服务项目", businessType = BusinessType.INSERT) + @PostMapping("/create") + public R create( + @ApiParam(value = "服务项目信息", required = true) @RequestBody PlayClerkCommodityEntity playClerkCommodity) { + boolean success = playClerkCommodityService.create(playClerkCommodity); + if (success) { + return R.ok(); + } + return R.error("添加失败"); + } + + /** + * 修改陪聊服务项目 + */ + @ApiOperation(value = "修改服务项目", notes = "根据ID修改陪聊服务项目信息") + @ApiImplicitParam(name = "id", value = "服务项目ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败")}) + @Log(title = "陪聊服务项目", businessType = BusinessType.UPDATE) + @PostMapping(value = "/update/{id}") + public R update(@PathVariable String id, + @ApiParam(value = "服务项目信息", required = true) @RequestBody PlayClerkCommodityEntity playClerkCommodity) { + playClerkCommodity.setId(id); + boolean success = playClerkCommodityService.update(playClerkCommodity); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + /** + * 删除陪聊服务项目 + */ + @ApiOperation(value = "删除服务项目", notes = "根据ID批量删除陪聊服务项目") + @ApiImplicitParam(name = "ids", value = "服务项目ID数组", required = true, paramType = "path", dataType = "String[]", example = "1,2,3") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Integer.class)}) + @Log(title = "陪聊服务项目", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@PathVariable String[] ids) { + return R.ok(playClerkCommodityService.deletePlayClerkCommodityByIds(ids)); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/controller/PlayClerkDataReviewInfoController.java --- +package com.starry.admin.modules.clerk.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.modules.clerk.module.vo.PlayClerkDataReviewQueryVo; +import com.starry.admin.modules.clerk.module.vo.PlayClerkDataReviewReturnVo; +import com.starry.admin.modules.clerk.module.vo.PlayClerkDataReviewStateEditVo; +import com.starry.admin.modules.clerk.service.IPlayClerkDataReviewInfoService; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 店员资料审核Controller + * + * @author admin + * @since 2024-05-19 + */ +@Api(tags = "店员资料内容审核", description = "店员资料内容审核相关接口,包括昵称、头像、相册、录音等资料的审核") +@RestController +@RequestMapping("/clerk/data/review") +public class PlayClerkDataReviewInfoController { + + @Resource + private IPlayClerkDataReviewInfoService playClerkDataReviewInfoService; + + /** + * 查询店员资料审核列表 + */ + @ApiOperation(value = "查询资料审核列表", notes = "分页查询店员资料审核列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayClerkDataReviewReturnVo.class, responseContainer = "Page")}) + @PostMapping("/listByPage") + public R list(@ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayClerkDataReviewQueryVo vo) { + IPage list = playClerkDataReviewInfoService.selectByPage(vo); + return R.ok(list); + } + + /** + * 修改店员资料审核 + */ + @ApiOperation(value = "修改资料审核状态", notes = "更新店员资料审核状态,通过或拒绝") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + // @PreAuthorize("@customSs.hasPermission('clerk:dataReview:update')") + @Log(title = "店员资料审核", businessType = BusinessType.UPDATE) + @PostMapping(value = "/update") + public R update( + @ApiParam(value = "审核状态信息", required = true) @Validated @RequestBody PlayClerkDataReviewStateEditVo vo) { + playClerkDataReviewInfoService.updateDataReviewState(vo); + return R.ok(); + } + + /** + * 删除店员资料审核 + */ + @ApiOperation(value = "删除资料审核记录", notes = "根据ID批量删除店员资料审核记录") + @ApiImplicitParam(name = "ids", value = "审核记录ID数组", required = true, paramType = "path", dataType = "String[]", example = "1,2,3") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Integer.class)}) + // @PreAuthorize("@customSs.hasPermission('clerk:dataReview:delete')") + @Log(title = "店员资料审核", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@PathVariable String[] ids) { + return R.ok(playClerkDataReviewInfoService.deletePlayClerkDataReviewInfoByIds(ids)); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/controller/PlayClerkLevelInfoController.java --- +package com.starry.admin.modules.clerk.controller; + +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.clerk.module.entity.PlayClerkLevelInfoEntity; +import com.starry.admin.modules.clerk.module.vo.PlayClerkLevelAddVo; +import com.starry.admin.modules.clerk.module.vo.PlayClerkLevelEditVo; +import com.starry.admin.modules.clerk.service.IPlayClerkLevelInfoService; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import com.starry.common.utils.ConvertUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 店员等级Controller + * + * @author admin + * @since 2024-03-30 + */ +@Api(tags = "店员等级管理", description = "店员等级信息管理相关接口,包括查询、新增、修改和删除等操作") +@RestController +@RequestMapping("/clerk/level") +public class PlayClerkLevelInfoController { + @Resource + private IPlayClerkLevelInfoService playClerkLevelInfoService; + + /** + * 查询店员等级列表 + */ + @ApiOperation(value = "查询所有等级", notes = "获取所有店员等级信息列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayClerkLevelInfoEntity.class, responseContainer = "List")}) + @GetMapping("/listAll") + public R listAll() { + return R.ok(playClerkLevelInfoService.selectAll()); + } + + /** + * 获取店员等级详细信息 + */ + @ApiOperation(value = "获取等级详情", notes = "根据ID获取店员等级详细信息") + @ApiImplicitParam(name = "id", value = "等级ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = PlayClerkLevelInfoEntity.class)}) + @GetMapping(value = "/{id}") + public R getInfo(@PathVariable("id") String id) { + return R.ok(playClerkLevelInfoService.selectPlayClerkLevelInfoById(id)); + } + + /** + * 新增店员等级 + */ + @ApiOperation(value = "新增等级", notes = "创建新的店员等级信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "添加失败")}) + @Log(title = "店员等级", businessType = BusinessType.INSERT) + @PostMapping("/create") + public R create(@ApiParam(value = "等级信息", required = true) @RequestBody PlayClerkLevelAddVo vo) { + PlayClerkLevelInfoEntity entity = ConvertUtil.entityToVo(vo, PlayClerkLevelInfoEntity.class); + int level = playClerkLevelInfoService.selectMaxLevel(); + entity.setLevel(level + 1); + boolean success = playClerkLevelInfoService.create(entity); + if (success) { + return R.ok(); + } + return R.error("添加失败"); + } + + /** + * 修改店员等级 + */ + @ApiOperation(value = "修改等级", notes = "修改店员等级信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败")}) + @Log(title = "店员等级", businessType = BusinessType.UPDATE) + @PostMapping(value = "/update") + public R update(@ApiParam(value = "等级信息", required = true) @Validated @RequestBody PlayClerkLevelEditVo vo) { + PlayClerkLevelInfoEntity entity = ConvertUtil.entityToVo(vo, PlayClerkLevelInfoEntity.class); + boolean success = playClerkLevelInfoService.update(entity); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + /** + * 删除店员等级 + */ + @ApiOperation(value = "删除最高等级", notes = "删除系统中最高的店员等级") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "最后一级,不允许删除")}) + @Log(title = "店员等级", businessType = BusinessType.DELETE) + @DeleteMapping("delMaxLevel") + public R remove() { + int level = playClerkLevelInfoService.selectMaxLevel(); + if (level <= 1) { + throw new CustomException("最后一级,不允许删除"); + } + playClerkLevelInfoService.delMaxLevelByLevel(level); + return R.ok(); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/controller/PlayClerkPkController.java --- +package com.starry.admin.modules.clerk.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.modules.clerk.module.entity.PlayClerkPkEntity; +import com.starry.admin.modules.clerk.service.IPlayClerkPkService; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import javax.annotation.Resource; +import org.springframework.web.bind.annotation.*; + +/** + * 店员pkController + * + * @author admin + * @since 2024-08-02 + */ +@Api(tags = "店员PK管理", description = "店员PK信息管理相关接口,包括查询、新增、修改和删除等操作") +@RestController +@RequestMapping("/play/pk") +public class PlayClerkPkController { + @Resource + private IPlayClerkPkService playClerkPkService; + + /** + * 查询店员pk列表 + */ + @ApiOperation(value = "分页查询PK列表", notes = "分页查询店员PK信息列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayClerkPkEntity.class, responseContainer = "Page")}) + @GetMapping("/list") + public R list(@ApiParam(value = "查询条件") PlayClerkPkEntity playClerkPk) { + IPage list = playClerkPkService.selectPlayClerkPkByPage(playClerkPk); + return R.ok(list); + } + + /** + * 获取店员pk详细信息 + */ + @ApiOperation(value = "获取PK详情", notes = "根据ID获取店员PK详细信息") + @ApiImplicitParam(name = "id", value = "PK记录ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = PlayClerkPkEntity.class)}) + @GetMapping(value = "/{id}") + public R getInfo(@PathVariable("id") String id) { + return R.ok(playClerkPkService.selectPlayClerkPkById(id)); + } + + /** + * 新增店员pk + */ + @ApiOperation(value = "新增PK记录", notes = "创建新的店员PK信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "添加失败")}) + @Log(title = "店员pk", businessType = BusinessType.INSERT) + @PostMapping("/create") + public R create(@ApiParam(value = "PK信息", required = true) @RequestBody PlayClerkPkEntity playClerkPk) { + boolean success = playClerkPkService.create(playClerkPk); + if (success) { + return R.ok(); + } + return R.error("添加失败"); + } + + /** + * 修改店员pk + */ + @ApiOperation(value = "修改PK记录", notes = "根据ID修改店员PK信息") + @ApiImplicitParam(name = "id", value = "PK记录ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败")}) + @Log(title = "店员pk", businessType = BusinessType.UPDATE) + @PostMapping(value = "/update/{id}") + public R update(@PathVariable String id, + @ApiParam(value = "PK信息", required = true) @RequestBody PlayClerkPkEntity playClerkPk) { + playClerkPk.setId(id); + boolean success = playClerkPkService.update(playClerkPk); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + /** + * 删除店员pk + */ + @ApiOperation(value = "删除PK记录", notes = "根据ID批量删除店员PK信息") + @ApiImplicitParam(name = "ids", value = "PK记录ID数组", required = true, paramType = "path", dataType = "String[]", example = "1,2,3") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Integer.class)}) + @Log(title = "店员pk", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@PathVariable String[] ids) { + return R.ok(playClerkPkService.deletePlayClerkPkByIds(ids)); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/controller/PlayClerkRankingInfoController.java --- +package com.starry.admin.modules.clerk.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.modules.clerk.module.entity.IPlayClerkRankingInfoQueryVo; +import com.starry.admin.modules.clerk.module.entity.IPlayClerkRankingInfoReturnVo; +import com.starry.admin.modules.clerk.module.entity.PlayClerkRankingInfoEntity; +import com.starry.admin.modules.clerk.service.IPlayClerkRankingInfoService; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 店员排行Controller + * + * @author admin + * @since 2024-05-25 + */ +@Api(tags = "店员排行管理", description = "店员排行榜信息管理相关接口,包括查询、新增、修改和删除等操作") +@RestController +@RequestMapping("/clerk/ranking") +public class PlayClerkRankingInfoController { + @Resource + private IPlayClerkRankingInfoService playClerkRankingInfoService; + + /** + * 查询店员排行列表 + */ + @ApiOperation(value = "查询排行列表", notes = "分页查询店员排行信息列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = IPlayClerkRankingInfoReturnVo.class, responseContainer = "Page")}) + @PostMapping("/listByPage") + public R list(@ApiParam(value = "查询条件", required = true) @Validated @RequestBody IPlayClerkRankingInfoQueryVo vo) { + IPage list = playClerkRankingInfoService.selectByPage(vo); + return R.ok(list); + } + + /** + * 获取店员排行详细信息 + */ + @ApiOperation(value = "获取排行详情", notes = "根据ID获取店员排行详细信息") + @ApiImplicitParam(name = "id", value = "排行ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = PlayClerkRankingInfoEntity.class)}) + @GetMapping(value = "/{id}") + public R getInfo(@PathVariable("id") String id) { + return R.ok(playClerkRankingInfoService.selectPlayClerkRankingInfoById(id)); + } + + /** + * 新增店员排行 + */ + @ApiOperation(value = "新增排行", notes = "创建新的店员排行记录") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "添加失败")}) + // @PreAuthorize("@customSs.hasPermission('clerk:ranking:add')") + @Log(title = "店员排行", businessType = BusinessType.INSERT) + @PostMapping("/create") + public R create( + @ApiParam(value = "排行信息", required = true) @RequestBody PlayClerkRankingInfoEntity playClerkRankingInfo) { + boolean success = playClerkRankingInfoService.create(playClerkRankingInfo); + if (success) { + return R.ok(); + } + return R.error("添加失败"); + } + + /** + * 修改店员排行 + */ + @ApiOperation(value = "修改排行", notes = "根据ID修改店员排行信息") + @ApiImplicitParam(name = "id", value = "排行ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败")}) + // @PreAuthorize("@customSs.hasPermission('clerk:ranking:update')") + @Log(title = "店员排行", businessType = BusinessType.UPDATE) + @PostMapping(value = "/update/{id}") + public R update(@PathVariable String id, + @ApiParam(value = "排行信息", required = true) @RequestBody PlayClerkRankingInfoEntity playClerkRankingInfo) { + playClerkRankingInfo.setId(id); + boolean success = playClerkRankingInfoService.update(playClerkRankingInfo); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + /** + * 删除店员排行 + */ + @ApiOperation(value = "删除排行", notes = "根据ID批量删除店员排行信息") + @ApiImplicitParam(name = "ids", value = "排行ID数组", required = true, paramType = "path", dataType = "String[]", example = "1,2,3") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Integer.class)}) + // @PreAuthorize("@customSs.hasPermission('clerk:ranking:delete')") + @Log(title = "店员排行", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@PathVariable String[] ids) { + return R.ok(playClerkRankingInfoService.deletePlayClerkRankingInfoByIds(ids)); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/controller/PlayClerkTypeInfoController.java --- +package com.starry.admin.modules.clerk.controller; + +import com.starry.admin.modules.clerk.module.entity.PlayClerkTypeInfoEntity; +import com.starry.admin.modules.clerk.module.vo.PlayClerkTypeInfoAddVo; +import com.starry.admin.modules.clerk.module.vo.PlayClerkTypeInfoQueryVo; +import com.starry.admin.modules.clerk.service.IPlayClerkTypeInfoService; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import com.starry.common.utils.ConvertUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 店员分类信息Controller + * + * @author admin + * @since 2024-05-31 + */ +@Api(tags = "店员分类管理", description = "店员分类信息管理相关接口,包括查询、新增、修改和删除等操作") +@RestController +@RequestMapping("/clerk/type") +public class PlayClerkTypeInfoController { + @Resource + private IPlayClerkTypeInfoService playClerkTypeInfoService; + + /** + * 查询店员分类信息列表 + */ + @ApiOperation(value = "查询所有分类", notes = "获取所有店员分类信息列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayClerkTypeInfoEntity.class, responseContainer = "List")}) + @GetMapping("/listByAll") + public R listByAll() { + return R.ok(playClerkTypeInfoService.selectByAll()); + } + + @ApiOperation(value = "分页查询分类", notes = "分页查询店员分类信息列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayClerkTypeInfoEntity.class, responseContainer = "Page")}) + @PostMapping("/listByPage") + public R listByPage( + @ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayClerkTypeInfoQueryVo vo) { + return R.ok(playClerkTypeInfoService.selectByPage(vo)); + } + + /** + * + * /** 新增店员分类信息 + */ + @ApiOperation(value = "新增分类", notes = "创建新的店员分类信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "添加失败")}) + @Log(title = "店员分类信息", businessType = BusinessType.INSERT) + @PostMapping("/create") + public R create(@ApiParam(value = "分类信息", required = true) @Validated @RequestBody PlayClerkTypeInfoAddVo vo) { + boolean success = playClerkTypeInfoService.create(ConvertUtil.entityToVo(vo, PlayClerkTypeInfoEntity.class)); + if (success) { + return R.ok(); + } + return R.error("添加失败"); + } + + /** + * 修改店员分类信息 + */ + @ApiOperation(value = "修改分类", notes = "根据ID修改店员分类信息") + @ApiImplicitParam(name = "id", value = "分类ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败")}) + @Log(title = "店员分类信息", businessType = BusinessType.UPDATE) + @PostMapping(value = "/update/{id}") + public R update(@PathVariable String id, + @ApiParam(value = "分类信息", required = true) @RequestBody PlayClerkTypeInfoEntity playClerkTypeInfo) { + playClerkTypeInfo.setId(id); + boolean success = playClerkTypeInfoService.update(playClerkTypeInfo); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + /** + * 删除店员分类信息 + */ + @ApiOperation(value = "删除分类", notes = "根据ID批量删除店员分类信息") + @ApiImplicitParam(name = "ids", value = "分类ID数组", required = true, paramType = "path", dataType = "String[]", example = "1,2,3") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Integer.class)}) + @Log(title = "店员分类信息", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@PathVariable String[] ids) { + return R.ok(playClerkTypeInfoService.deletePlayClerkTypeInfoByIds(ids)); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/controller/PlayClerkUserInfoController.java --- +package com.starry.admin.modules.clerk.controller; + +import com.alibaba.fastjson2.JSONObject; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserQueryVo; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserReturnVo; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserTypeEditVo; +import com.starry.admin.modules.clerk.module.vo.PlayClerkUserEditVo; +import com.starry.admin.modules.clerk.module.vo.PlayClerkUserStateEditVo; +import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService; +import com.starry.admin.modules.custom.module.entity.PlayCustomUserInfoEntity; +import com.starry.admin.modules.custom.service.IPlayCustomUserInfoService; +import com.starry.admin.modules.weichat.entity.clerk.PlayClerkUserInfoQueryVo; +import com.starry.admin.modules.weichat.entity.clerk.PlayClerkUserInfoResultVo; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import com.starry.common.utils.ConvertUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.util.List; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 店员Controller + * + * @author admin + * @since 2024-03-30 + */ +@Api(tags = "店员管理", description = "店员信息管理相关接口,包括店员的增删改查、分类、分组以及状态管理等功能") +@RestController +@RequestMapping("/clerk/user") +public class PlayClerkUserInfoController { + + @Resource + private IPlayCustomUserInfoService customUserInfoService; + @Resource + private IPlayClerkUserInfoService playClerkUserInfoService; + + /** + * 查询店员列表 + */ + @ApiOperation(value = "分页查询店员列表", notes = "根据条件分页查询店员列表信息,支持多种筛选条件") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayClerkUserReturnVo.class, responseContainer = "Page")}) + @PostMapping("listByPage") + public R listByPage(@ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayClerkUserQueryVo vo) { + IPage list = playClerkUserInfoService.selectByPage(vo); + return R.ok(list); + } + + /** + * 按照店员分类查询店员列表 + */ + @ApiOperation(value = "按分类查询店员列表", notes = "根据店员分类ID查询所有属于该分类的店员列表") + @ApiImplicitParam(name = "id", value = "店员分类ID", required = true, paramType = "query", dataType = "String", example = "1") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayClerkUserInfoEntity.class, responseContainer = "List")}) + @GetMapping("listAllByTypeId") + public R listAllByTypeId(@RequestParam("id") String id) { + List list = playClerkUserInfoService.listAllByTypeId(id); + return R.ok(list); + } + + /** + * 按照店员分组查询店员列表 + */ + @ApiOperation(value = "按分组查询店员列表", notes = "根据店员分组ID查询所有属于该分组的店员列表") + @ApiImplicitParam(name = "id", value = "店员分组ID", required = true, paramType = "query", dataType = "String", example = "1") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayClerkUserInfoEntity.class, responseContainer = "List")}) + @GetMapping("listAllByGroupId") + public R listAllByGroupId(@RequestParam("id") String id) { + List list = playClerkUserInfoService.listAllByGroupId(id); + return R.ok(list); + } + + /** + * 修改店员分类 + */ + @ApiOperation(value = "修改店员分类", notes = "将指定店员分配到指定分类中,会先清空该分类下所有店员,再重新分配") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = String.class)}) + @PostMapping("editClerkType") + public R listByPage( + @ApiParam(value = "店员分类修改参数", required = true) @Validated @RequestBody PlayClerkUserTypeEditVo vo) { + // 先清空当前分类下店员 + List list = playClerkUserInfoService.listAllByTypeId(vo.getTypeId()); + for (PlayClerkUserInfoEntity clerkUserInfo : list) { + PlayClerkUserInfoEntity entity = new PlayClerkUserInfoEntity(); + entity.setId(clerkUserInfo.getId()); + entity.setTypeId(""); + playClerkUserInfoService.update(entity); + } + for (String clerkUserId : vo.getClerkUserIds()) { + PlayClerkUserInfoEntity entity = new PlayClerkUserInfoEntity(); + entity.setId(clerkUserId); + entity.setTypeId(vo.getTypeId()); + playClerkUserInfoService.update(entity); + } + + return R.ok("成功"); + } + + /** + * 1、修改店员分组 2、将对应账号角色ID设为组长 + */ + @ApiOperation(value = "修改店员分组", notes = "将指定店员分配到指定分组中,会先清空该分组下所有店员,再重新分配,并可设置组长") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = String.class)}) + @PostMapping("editClerkGroup") + public R editClerkGroup( + @ApiParam(value = "店员分组修改参数", required = true) @Validated @RequestBody PlayClerkUserTypeEditVo vo) { + // 先清空当前分类下店员 + List list = playClerkUserInfoService.listAllByGroupId(vo.getTypeId()); + for (PlayClerkUserInfoEntity clerkUserInfo : list) { + PlayClerkUserInfoEntity entity = new PlayClerkUserInfoEntity(); + entity.setId(clerkUserInfo.getId()); + entity.setGroupId(""); + playClerkUserInfoService.update(entity); + } + for (String clerkUserId : vo.getClerkUserIds()) { + PlayClerkUserInfoEntity entity = new PlayClerkUserInfoEntity(); + entity.setId(clerkUserId); + entity.setGroupId(vo.getTypeId()); + playClerkUserInfoService.update(entity); + } + + return R.ok("成功"); + } + + @ApiOperation(value = "获取简单列表", notes = "获取店员和客户的简单列表信息,用于下拉选择等场景") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = JSONObject.class)}) + @GetMapping("/simple/list") + public R simpleList() { + List clerkList = playClerkUserInfoService.simpleList(); + List customerList = customUserInfoService.simpleList(); + return R.ok(new JSONObject().fluentPut("clerkList", clerkList).fluentPut("customerList", customerList)); + } + + /** + * 查询店员列表 + */ + @ApiOperation(value = "查询店员列表", notes = "分页查询店员信息列表,支持多种条件筛选,返回详细的店员信息") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayClerkUserInfoResultVo.class, responseContainer = "Page")}) + @GetMapping("/list") + public R list(@ApiParam(value = "查询条件") PlayClerkUserInfoQueryVo vo) { + IPage list = playClerkUserInfoService.selectPlayClerkUserInfoByPage(vo); + return R.ok(list); + } + + /** + * 获取店员详细信息 + */ + @ApiOperation(value = "获取店员详情", notes = "根据店员ID获取店员的详细信息") + @ApiImplicitParam(name = "id", value = "店员ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = PlayClerkUserInfoEntity.class)}) + @GetMapping(value = "/{id}") + public R getInfo(@PathVariable("id") String id) { + return R.ok(playClerkUserInfoService.selectById(id)); + } + + // + // /** + // * 微信端口新增店员 + // */ + // @Log(title = "店员", businessType = BusinessType.INSERT) + // @PostMapping("/wx/add") + // public R add(@Validated @RequestBody PlayClerkUserAddToWxVo vo) { + // //微信申请成为店员,需要先创建账户。 + // PlayUserInfoEntity userInfoEntity = ConvertUtil.entityToVo(vo, + // PlayUserInfoEntity.class); + // userInfoEntity.setId(IdUtils.getUuid()); + // playUserInfoService.create(userInfoEntity); + // //账号创建完成后,创建店员 + // PlayClerkUserInfoEntity clerkUserInfoEntity = ConvertUtil.entityToVo(vo, + // PlayClerkUserInfoEntity.class); + // clerkUserInfoEntity.setPlayUserId(userInfoEntity.getId()); + // boolean success = playClerkUserInfoService.create(clerkUserInfoEntity); + // if (success) { + // clerkCommodityService.initClerkCommodity(userInfoEntity.getId()); + // return R.ok(); + // } + // return R.error("添加失败"); + // } + + // /** + // * 新增店员 + // */ + // @Log(title = "店员", businessType = BusinessType.INSERT) + // @PostMapping("/create") + // public R create(@Validated @RequestBody PlayClerkUserAddVo vo) { + // PlayClerkUserInfoEntity entity = ConvertUtil.entityToVo(vo, + // PlayClerkUserInfoEntity.class); + // boolean success = playClerkUserInfoService.create(entity); + // if (success) { + // clerkCommodityService.initClerkCommodity(vo.getPlayUserId()); + // return R.ok(); + // } + // return R.error("添加失败"); + // } + + /** + * 修改店员 + */ + // @PreAuthorize("@customSs.hasPermission('clerk:user:update')") + @Log(title = "店员", businessType = BusinessType.UPDATE) + @ApiOperation(value = "修改店员信息", notes = "修改店员的基本信息,如昵称、头像、签名等") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败")}) + @PostMapping(value = "/update") + public R update(@ApiParam(value = "店员信息", required = true) @Validated @RequestBody PlayClerkUserEditVo vo) { + PlayClerkUserInfoEntity entity = ConvertUtil.entityToVo(vo, PlayClerkUserInfoEntity.class); + boolean success = playClerkUserInfoService.update(entity); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + /** + * 修改店员状态 + */ + // @PreAuthorize("@customSs.hasPermission('clerk:user:update')") + @Log(title = "店员", businessType = BusinessType.UPDATE) + @ApiOperation(value = "修改店员状态", notes = "修改店员的状态信息,如上下架状态、推荐状态、在线状态等") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败")}) + @PostMapping(value = "/updateState") + public R updateState( + @ApiParam(value = "店员状态信息", required = true) @Validated @RequestBody PlayClerkUserStateEditVo vo) { + PlayClerkUserInfoEntity entity = ConvertUtil.entityToVo(vo, PlayClerkUserInfoEntity.class); + boolean success = playClerkUserInfoService.update(entity); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + /** + * 删除店员 + */ + // @PreAuthorize("@customSs.hasPermission('clerk:user:remove')") + @Log(title = "店员", businessType = BusinessType.DELETE) + @ApiOperation(value = "删除店员", notes = "根据ID批量删除店员信息") + @ApiImplicitParam(name = "ids", value = "店员ID数组", required = true, paramType = "path", dataType = "String[]", example = "1,2,3") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Integer.class)}) + @DeleteMapping("/{ids}") + public R remove(@PathVariable String[] ids) { + return R.ok(playClerkUserInfoService.deletePlayClerkUserInfoByIds(ids)); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/controller/PlayClerkUserReviewInfoController.java --- +package com.starry.admin.modules.clerk.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.modules.clerk.module.vo.PlayClerkUserReviewQueryVo; +import com.starry.admin.modules.clerk.module.vo.PlayClerkUserReviewReturnVo; +import com.starry.admin.modules.clerk.module.vo.PlayClerkUserReviewStateEditVo; +import com.starry.admin.modules.clerk.service.IPlayClerkUserReviewInfoService; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 店员资料审核Controller + * + * @author admin + * @since 2024-05-19 + */ +@Api(tags = "店员资料审核", description = "店员资料审核相关接口,包括审核列表查询、审核状态修改和删除等操作") +@RestController +@RequestMapping("/clerk/user/review") +public class PlayClerkUserReviewInfoController { + @Resource + private IPlayClerkUserReviewInfoService playClerkUserReviewInfoService; + + /** + * 查询店员资料审核列表 + */ + @ApiOperation(value = "查询审核列表", notes = "分页查询店员资料审核列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayClerkUserReviewReturnVo.class, responseContainer = "Page")}) + @PostMapping("/listByPage") + public R listByPage( + @ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayClerkUserReviewQueryVo vo) { + IPage list = playClerkUserReviewInfoService.selectByPage(vo); + return R.ok(list); + } + + /** + * 修改店员资料审核 + */ + @ApiOperation(value = "修改审核状态", notes = "更新店员资料审核状态,通过或拒绝") + @ApiResponses({@ApiResponse(code = 200, message = "修改成功")}) + // @PreAuthorize("@customSs.hasPermission('clerk:userReview:update')") + @Log(title = "店员资料审核", businessType = BusinessType.UPDATE) + @PostMapping(value = "/update") + public R update( + @ApiParam(value = "审核状态信息", required = true) @Validated @RequestBody PlayClerkUserReviewStateEditVo vo) { + playClerkUserReviewInfoService.updateDataReviewState(vo); + return R.ok("修改成功"); + } + + /** + * 删除店员资料审核 + */ + @ApiOperation(value = "删除审核记录", notes = "根据ID批量删除店员资料审核记录") + @ApiImplicitParam(name = "ids", value = "审核记录ID数组", required = true, paramType = "path", dataType = "String[]", example = "1,2,3") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Integer.class)}) + // @PreAuthorize("@customSs.hasPermission('clerk:userReview:delete')") + @Log(title = "店员资料审核", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@PathVariable String[] ids) { + return R.ok(playClerkUserReviewInfoService.deletePlayClerkUserReviewInfoByIds(ids)); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/controller/PlayClerkWagesDetailsInfoController.java --- +package com.starry.admin.modules.clerk.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.modules.clerk.module.entity.PlayClerkWagesDetailsInfoEntity; +import com.starry.admin.modules.clerk.service.IPlayClerkWagesDetailsInfoService; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import javax.annotation.Resource; +import org.springframework.web.bind.annotation.*; + +/** + * 店员工资明细信息Controller + * + * @author admin + * @since 2024-05-31 + */ +@Api(tags = "店员工资明细", description = "店员工资明细信息管理相关接口,包括查询、新增、修改和删除等操作") +@RestController +@RequestMapping("/wages/details") +public class PlayClerkWagesDetailsInfoController { + @Resource + private IPlayClerkWagesDetailsInfoService playClerkWagesDetailsInfoService; + + /** + * 查询店员工资明细信息列表 + */ + @ApiOperation(value = "查询工资明细列表", notes = "分页查询店员工资明细信息列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayClerkWagesDetailsInfoEntity.class, responseContainer = "Page")}) + @GetMapping("/list") + public R list(@ApiParam(value = "查询条件") PlayClerkWagesDetailsInfoEntity playClerkWagesDetailsInfo) { + IPage list = playClerkWagesDetailsInfoService + .selectPlayClerkWagesDetailsInfoByPage(playClerkWagesDetailsInfo); + return R.ok(list); + } + + /** + * 获取店员工资明细信息详细信息 + */ + @ApiOperation(value = "获取工资明细详情", notes = "根据ID获取店员工资明细详细信息") + @ApiImplicitParam(name = "id", value = "工资明细ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = PlayClerkWagesDetailsInfoEntity.class)}) + @GetMapping(value = "/{id}") + public R getInfo(@PathVariable("id") String id) { + return R.ok(playClerkWagesDetailsInfoService.selectPlayClerkWagesDetailsInfoById(id)); + } + + /** + * 新增店员工资明细信息 + */ + @ApiOperation(value = "新增工资明细", notes = "创建新的店员工资明细记录") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "添加失败")}) + @Log(title = "店员工资明细信息", businessType = BusinessType.INSERT) + @PostMapping("/create") + public R create( + @ApiParam(value = "工资明细信息", required = true) @RequestBody PlayClerkWagesDetailsInfoEntity playClerkWagesDetailsInfo) { + boolean success = playClerkWagesDetailsInfoService.create(playClerkWagesDetailsInfo); + if (success) { + return R.ok(); + } + return R.error("添加失败"); + } + + /** + * 修改店员工资明细信息 + */ + @ApiOperation(value = "修改工资明细", notes = "根据ID修改店员工资明细信息") + @ApiImplicitParam(name = "id", value = "工资明细ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败")}) + @Log(title = "店员工资明细信息", businessType = BusinessType.UPDATE) + @PostMapping(value = "/update/{id}") + public R update(@PathVariable String id, + @ApiParam(value = "工资明细信息", required = true) @RequestBody PlayClerkWagesDetailsInfoEntity playClerkWagesDetailsInfo) { + playClerkWagesDetailsInfo.setId(id); + boolean success = playClerkWagesDetailsInfoService.update(playClerkWagesDetailsInfo); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + /** + * 删除店员工资明细信息 + */ + @ApiOperation(value = "删除工资明细", notes = "根据ID批量删除店员工资明细信息") + @ApiImplicitParam(name = "ids", value = "工资明细ID数组", required = true, paramType = "path", dataType = "String[]", example = "1,2,3") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Integer.class)}) + @Log(title = "店员工资明细信息", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@PathVariable String[] ids) { + return R.ok(playClerkWagesDetailsInfoService.deletePlayClerkWagesDetailsInfoByIds(ids)); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/controller/PlayClerkWagesInfoController.java --- +package com.starry.admin.modules.clerk.controller; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.clerk.module.entity.PlayClerkWagesDetailsInfoEntity; +import com.starry.admin.modules.clerk.module.vo.PlayClerkUnsettledWagesInfoQueryVo; +import com.starry.admin.modules.clerk.module.vo.PlayClerkUnsettledWagesInfoReturnVo; +import com.starry.admin.modules.clerk.module.vo.PlayClerkWagesInfoQueryVo; +import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService; +import com.starry.admin.modules.clerk.service.IPlayClerkWagesDetailsInfoService; +import com.starry.admin.modules.clerk.service.IPlayClerkWagesInfoService; +import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity; +import com.starry.admin.modules.weichat.entity.wages.ClerkWagesDetailsReturnVo; +import com.starry.common.result.R; +import com.starry.common.utils.ConvertUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 店员工资结算信息Controller + * + * @author admin + * @since 2024-05-31 + */ +@Api(tags = "店员工资结算", description = "店员工资结算信息管理相关接口,包括查询历史工资、未结算工资和工资明细等") +@RestController +@RequestMapping("/clerk/wages") +public class PlayClerkWagesInfoController { + @Resource + private IPlayClerkWagesInfoService playClerkWagesInfoService; + + @Resource + private IPlayClerkWagesDetailsInfoService playClerkWagesDetailsInfoService; + + @Resource + private IPlayClerkUserInfoService playClerkUserInfoService; + + /** + * 查询店员工资结算信息列表 + */ + @ApiOperation(value = "查询历史工资列表", notes = "分页查询店员历史工资结算信息列表") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Object.class, responseContainer = "Page")}) + @PostMapping("/listByPage") + public R list(@ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayClerkWagesInfoQueryVo vo) { + return R.ok(playClerkWagesInfoService.selectHistoricalByPage(vo)); + } + + /** + * 查询店员工未结算工资 + */ + @ApiOperation(value = "查询未结算工资", notes = "分页查询店员未结算工资信息列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayClerkUnsettledWagesInfoReturnVo.class, responseContainer = "Page")}) + @PostMapping("/listUnsettledWagesByPage") + public R list( + @ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayClerkUnsettledWagesInfoQueryVo vo) { + IPage page = playClerkUserInfoService.listUnsettledWagesByPage(vo); + for (PlayClerkUnsettledWagesInfoReturnVo record : page.getRecords()) { + Integer orderState1Number = 0; + BigDecimal orderState1Money = BigDecimal.ZERO; + Integer orderState2Number = 0; + BigDecimal orderState2Money = BigDecimal.ZERO; + BigDecimal orderState2Revenue = BigDecimal.ZERO; + Integer orderState3Number = 0; + BigDecimal orderState3Money = BigDecimal.ZERO; + BigDecimal orderState3Revenue = BigDecimal.ZERO; + for (PlayOrderInfoEntity orderInfoEntity : record.getOrderInfoEntities()) { + if ("1".equals(orderInfoEntity.getOrderStatus())) { + orderState1Number++; + orderState1Money = orderState1Money.add(orderInfoEntity.getFinalAmount()); + } else if ("2".equals(orderInfoEntity.getOrderStatus())) { + orderState2Number++; + orderState2Money = orderState2Money.add(orderInfoEntity.getFinalAmount()); + orderState2Revenue = orderState2Revenue.add(orderInfoEntity.getEstimatedRevenue()); + } else if ("3".equals(orderInfoEntity.getOrderStatus())) { + orderState3Number++; + orderState3Money = orderState3Money.add(orderInfoEntity.getFinalAmount()); + orderState3Revenue = orderState3Revenue.add(orderInfoEntity.getEstimatedRevenue()); + } + } + record.setOrderState1Number(orderState1Number); + record.setOrderState1Money(orderState1Money); + record.setOrderState2Number(orderState2Number); + record.setOrderState2Money(orderState2Money); + record.setOrderState2Revenue(orderState2Revenue); + record.setOrderState3Number(orderState3Number); + record.setOrderState3Money(orderState3Money); + record.setOrderState3Revenue(orderState3Revenue); + } + return R.ok(page); + } + + @ApiOperation(value = "查询工资明细", notes = "根据工资结算ID查询工资明细信息") + @ApiImplicitParam(name = "id", value = "工资结算ID", required = true, paramType = "query", dataType = "String", example = "1") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = ClerkWagesDetailsReturnVo.class, responseContainer = "List"), + @ApiResponse(code = 500, message = "ID不能为空")}) + @GetMapping("queryWagesDetailsById") + public R clerkQueryWagesDetails(@RequestParam("id") String id) { + if (StrUtil.isBlankIfStr(id)) { + throw new CustomException("ID不能为空"); + } + List list = playClerkWagesDetailsInfoService.selectByWagesId(id); + List returnVos = new ArrayList<>(list.size()); + for (PlayClerkWagesDetailsInfoEntity entity : list) { + returnVos.add(ConvertUtil.entityToVo(entity, ClerkWagesDetailsReturnVo.class)); + } + return R.ok(returnVos); + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/controller/PlayCustomArticleInfoController.java --- +package com.starry.admin.modules.clerk.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.modules.clerk.module.entity.PlayCustomArticleInfoEntity; +import com.starry.admin.modules.clerk.service.IPlayCustomArticleInfoService; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import javax.annotation.Resource; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +/** + * 陪聊点赞动态信息Controller + * + * @author admin + * @since 2024-05-04 + */ +@Api(tags = "陪聊动态管理", description = "陪聊点赞动态信息管理相关接口,包括查询、新增、修改和删除等操作") +@RestController +@RequestMapping("/custom/article") +public class PlayCustomArticleInfoController { + @Resource + private IPlayCustomArticleInfoService playCustomArticleInfoService; + + /** + * 查询陪聊点赞动态信息列表 + */ + @ApiOperation(value = "查询动态列表", notes = "分页查询陪聊点赞动态信息列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayCustomArticleInfoEntity.class, responseContainer = "Page")}) + @GetMapping("/list") + public R list(@ApiParam(value = "查询条件") PlayCustomArticleInfoEntity playCustomArticleInfo) { + IPage list = playCustomArticleInfoService + .selectPlayCustomArticleInfoByPage(playCustomArticleInfo); + return R.ok(list); + } + + /** + * 获取陪聊点赞动态信息详细信息 + */ + @ApiOperation(value = "获取动态详情", notes = "根据ID获取陪聊点赞动态详细信息") + @ApiImplicitParam(name = "id", value = "动态ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = PlayCustomArticleInfoEntity.class)}) + @PreAuthorize("@customSs.hasPermission('play:info:query')") + @GetMapping(value = "/{id}") + public R getInfo(@PathVariable("id") String id) { + return R.ok(playCustomArticleInfoService.selectPlayCustomArticleInfoById(id)); + } + + /** + * 新增陪聊点赞动态信息 + */ + @ApiOperation(value = "新增动态", notes = "创建新的陪聊点赞动态信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "添加失败")}) + @PreAuthorize("@customSs.hasPermission('play:info:create')") + @Log(title = "陪聊点赞动态信息", businessType = BusinessType.INSERT) + @PostMapping("/create") + public R create( + @ApiParam(value = "动态信息", required = true) @RequestBody PlayCustomArticleInfoEntity playCustomArticleInfo) { + boolean success = playCustomArticleInfoService.create(playCustomArticleInfo); + if (success) { + return R.ok(); + } + return R.error("添加失败"); + } + + /** + * 修改陪聊点赞动态信息 + */ + @ApiOperation(value = "修改动态", notes = "根据ID修改陪聊点赞动态信息") + @ApiImplicitParam(name = "id", value = "动态ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败")}) + @PreAuthorize("@customSs.hasPermission('play:info:edit')") + @Log(title = "陪聊点赞动态信息", businessType = BusinessType.UPDATE) + @PostMapping(value = "/update/{id}") + public R update(@PathVariable String id, + @ApiParam(value = "动态信息", required = true) @RequestBody PlayCustomArticleInfoEntity playCustomArticleInfo) { + playCustomArticleInfo.setId(id); + boolean success = playCustomArticleInfoService.update(playCustomArticleInfo); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + /** + * 删除陪聊点赞动态信息 + */ + @ApiOperation(value = "删除动态", notes = "根据ID批量删除陪聊点赞动态信息") + @ApiImplicitParam(name = "ids", value = "动态ID数组", required = true, paramType = "path", dataType = "String[]", example = "1,2,3") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Integer.class)}) + @PreAuthorize("@customSs.hasPermission('play:info:remove')") + @Log(title = "陪聊点赞动态信息", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@PathVariable String[] ids) { + return R.ok(playCustomArticleInfoService.deletePlayCustomArticleInfoByIds(ids)); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/mapper/PlayAvatarFrameInfoMapper.java --- +package com.starry.admin.modules.clerk.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.starry.admin.modules.clerk.module.entity.PlayAvatarFrameInfoEntity; + +/** + * 店员头像框Mapper接口 + * + * @author admin + * @since 2024-06-06 + */ +public interface PlayAvatarFrameInfoMapper extends BaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/mapper/PlayClerkArticleInfoMapper.java --- +package com.starry.admin.modules.clerk.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.starry.admin.modules.clerk.module.entity.PlayClerkArticleInfoEntity; + +/** + * 店员动态信息Mapper接口 + * + * @author admin + * @since 2024-05-04 + */ +public interface PlayClerkArticleInfoMapper extends MPJBaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/mapper/PlayClerkClassificationInfoMapper.java --- +package com.starry.admin.modules.clerk.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.starry.admin.modules.clerk.module.entity.PlayClerkClassificationInfoEntity; + +/** + * 店员分类Mapper接口 + * + * @author admin + * @since 2024-04-06 + */ +public interface PlayClerkClassificationInfoMapper extends BaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/mapper/PlayClerkCommodityMapper.java --- +package com.starry.admin.modules.clerk.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.starry.admin.modules.clerk.module.entity.PlayClerkCommodityEntity; + +/** + * 陪聊服务项目Mapper接口 + * + * @author admin + * @since 2024-03-31 + */ +public interface PlayClerkCommodityMapper extends BaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/mapper/PlayClerkDataReviewInfoMapper.java --- +package com.starry.admin.modules.clerk.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.starry.admin.modules.clerk.module.entity.PlayClerkDataReviewInfoEntity; + +/** + * 店员资料审核Mapper接口 + * + * @author admin + * @since 2024-05-19 + */ +public interface PlayClerkDataReviewInfoMapper extends MPJBaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/mapper/PlayClerkLevelInfoMapper.java --- +package com.starry.admin.modules.clerk.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.starry.admin.modules.clerk.module.entity.PlayClerkLevelInfoEntity; + +/** + * 店员等级Mapper接口 + * + * @author admin + * @since 2024-03-30 + */ +public interface PlayClerkLevelInfoMapper extends BaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/mapper/PlayClerkPkMapper.java --- +package com.starry.admin.modules.clerk.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.starry.admin.modules.clerk.module.entity.PlayClerkPkEntity; + +/** + * 店员pkMapper接口 + * + * @author admin + * @since 2024-08-02 + */ +public interface PlayClerkPkMapper extends BaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/mapper/PlayClerkRankingInfoMapper.java --- +package com.starry.admin.modules.clerk.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.starry.admin.modules.clerk.module.entity.PlayClerkRankingInfoEntity; + +/** + * 店员排行Mapper接口 + * + * @author admin + * @since 2024-05-25 + */ +public interface PlayClerkRankingInfoMapper extends MPJBaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/mapper/PlayClerkTypeInfoMapper.java --- +package com.starry.admin.modules.clerk.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.starry.admin.modules.clerk.module.entity.PlayClerkTypeInfoEntity; + +/** + * 店员分类信息Mapper接口 + * + * @author admin + * @since 2024-05-31 + */ +public interface PlayClerkTypeInfoMapper extends MPJBaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/mapper/PlayClerkTypeUserInfoMapper.java --- +package com.starry.admin.modules.clerk.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.starry.admin.modules.clerk.module.entity.PlayClerkTypeUserInfoEntity; + +/** + * 店员和分类关系Mapper接口 + * + * @author admin + * @since 2024-05-31 + */ +public interface PlayClerkTypeUserInfoMapper extends BaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/mapper/PlayClerkUserInfoMapper.java --- +package com.starry.admin.modules.clerk.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity; + +/** + * 店员Mapper接口 + * + * @author admin + * @since 2024-03-30 + */ +public interface PlayClerkUserInfoMapper extends MPJBaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/mapper/PlayClerkUserReviewInfoMapper.java --- +package com.starry.admin.modules.clerk.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserReviewInfoEntity; + +/** + * 店员资料审核Mapper接口 + * + * @author admin + * @since 2024-05-19 + */ +public interface PlayClerkUserReviewInfoMapper extends MPJBaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/mapper/PlayClerkWagesDetailsInfoMapper.java --- +package com.starry.admin.modules.clerk.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.starry.admin.modules.clerk.module.entity.PlayClerkWagesDetailsInfoEntity; + +/** + * 店员工资明细信息Mapper接口 + * + * @author admin + * @since 2024-05-31 + */ +public interface PlayClerkWagesDetailsInfoMapper extends BaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/mapper/PlayClerkWagesInfoMapper.java --- +package com.starry.admin.modules.clerk.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.starry.admin.modules.clerk.module.entity.PlayClerkWagesInfoEntity; + +/** + * 店员工资结算信息Mapper接口 + * + * @author admin + * @since 2024-05-31 + */ +public interface PlayClerkWagesInfoMapper extends MPJBaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/mapper/PlayCustomArticleInfoMapper.java --- +package com.starry.admin.modules.clerk.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.starry.admin.modules.clerk.module.entity.PlayCustomArticleInfoEntity; + +/** + * 陪聊点赞动态信息Mapper接口 + * + * @author admin + * @since 2024-05-04 + */ +public interface PlayCustomArticleInfoMapper extends BaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/entity/ClerkPkEnum.java --- +package com.starry.admin.modules.clerk.module.entity; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @Author: huchuansai + * @Date: 2021/11/1 4:33 下午 + * @Description: + */ +@AllArgsConstructor +public enum ClerkPkEnum { + + TO_BE_STARTED("TO_BE_STARTED", "待开始"), IN_PROGRESS("IN_PROGRESS", "进行中"), FINISHED("FINISHED", "已完成"),; + + @Getter + private String value; + @Getter + private String desc; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/entity/IPlayClerkRankingInfoQueryVo.java --- +package com.starry.admin.modules.clerk.module.entity; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.starry.common.domain.BasePageEntity; +import java.time.LocalDate; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * @author admin + * @since 2024/6/7 上午9:49 + **/ +@EqualsAndHashCode(callSuper = true) +@Data +public class IPlayClerkRankingInfoQueryVo extends BasePageEntity { + + /** + * 日排名还是周排名(0:每日排名;1:每周排名) + */ + private String weeklyRanking; + + /** + * 是否为历史统计(1:是;0:不是) + */ + private String historicalStatistics; + + /** + * 店员ID + */ + private String clerkId; + + /** + * 店员性别 + */ + private String sex; + + /** + * 统计时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private LocalDate settlementDate; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/entity/IPlayClerkRankingInfoReturnVo.java --- +package com.starry.admin.modules.clerk.module.entity; + +import com.fasterxml.jackson.annotation.JsonFormat; +import java.math.BigDecimal; +import java.time.LocalDate; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * @author admin + * @since 2024/6/7 上午9:49 + **/ +@Data +public class IPlayClerkRankingInfoReturnVo { + + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 店员ID + */ + private String clerkId; + + /** + * 店员性别[0:未知;1:男;2:女] + */ + private String clerkSex; + + /** + * 店员昵称 + */ + private String clerkNickname; + + /** + * 店员分组名称 + */ + private String clerkGroupName; + + /** + * 排序名次 + */ + private Integer rankingIndex; + + /** + * 开始统计时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private LocalDate startCountDate; + + /** + * 结束统计时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private LocalDate endCountDate; + + /** + * 订单总数 + */ + private Integer orderNumber; + + /** + * 订单金额 + */ + private BigDecimal orderMoney; + + /** + * 续单数 + */ + private Integer orderContinueNumber; + + /** + * 续单金额 + */ + private BigDecimal orderContinueMoney; + + /** + * 超时未接单数量 + */ + private Integer ordersExpiredNumber = 0; + + /** + * 续单比例 + */ + private BigDecimal orderContinueProportion = BigDecimal.ZERO; + + /** + * 用户数 + */ + private Integer customNumber; + + /** + * 订单平均价格 + */ + private BigDecimal averageUnitPrice = BigDecimal.ZERO; + /** + * 距离前一名相差金额 + */ + private BigDecimal previousMoney; + + /** + * 统计时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private LocalDate settlementDate; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/entity/PlayAvatarFrameInfoEntity.java --- +package com.starry.admin.modules.clerk.module.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.common.domain.BaseEntity; +import java.time.LocalDateTime; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 店员头像框对象 play_avatar_frame_info + * + * @author admin + * @since 2024-06-06 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("play_avatar_frame_info") +public class PlayAvatarFrameInfoEntity extends BaseEntity { + + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 头像框名称 + */ + private String avatarFrameName; + + /** + * 头像框地址 + */ + private String avatarFrameAddress; + + /** + * 获取方式(0:手动赠送;1:自动赠送) + */ + private String accessType; + + /** + * 获取条件名称 + */ + private String accessName; + + /** + * 获取条件 + */ + private String accessValue; + + /** + * 有效期(单位:天,-1:永久有效) + */ + private String periodValidity; + + /** + * 添加时间 + */ + private LocalDateTime addTime; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/entity/PlayClerkArticleInfoEntity.java --- +package com.starry.admin.modules.clerk.module.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.admin.common.conf.StringTypeHandler; +import com.starry.common.domain.BaseEntity; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 店员动态信息对象 play_clerk_article_info + * + * @author admin + * @since 2024-05-04 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName(value = "play_clerk_article_info", autoResultMap = true) +public class PlayClerkArticleInfoEntity extends BaseEntity { + + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 陪聊用户ID + */ + private String clerkId; + + /** + * 动态内容 + */ + private String articleCon; + + /** + * 动态附件类型(0:图片;1:视频;2:音频) + */ + private String annexType; + + /** + * 动态附件内容 + */ + @TableField(typeHandler = StringTypeHandler.class) + private List annexCon; + + /** + * 发布时间 + */ + private LocalDateTime releaseTime; + + /** + * 审核状态(0:未审核:1:审核通过,2:审核不通过) + */ + private String reviewState; + + /** + * 审核时间 + */ + private LocalDateTime reviewTime; + + /** + * 备注(审核理由) + */ + private String reviewCon; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/entity/PlayClerkClassificationInfoEntity.java --- +package com.starry.admin.modules.clerk.module.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.common.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 店员分类对象 play_clerk_classification_info + * + * @author admin + * @since 2024-04-06 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("play_clerk_classification_info") +public class PlayClerkClassificationInfoEntity extends BaseEntity { + + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 类型名称 + */ + private String name; + + /** + * (排序字段) + */ + private Integer sort; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/entity/PlayClerkCommodityEntity.java --- +package com.starry.admin.modules.clerk.module.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.common.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 陪聊服务项目对象 play_clerk_commodity + * + * @author admin + * @since 2024-03-31 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("play_clerk_commodity_info") +public class PlayClerkCommodityEntity extends BaseEntity { + + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 店员用户ID + */ + private String clerkId; + + /** + * 服务项目ID + */ + private String commodityId; + + /** + * 服务项目名称 + */ + private String commodityName; + + /** + * 服务项目排序 + */ + private Integer sort; + + /** + * 服务启动状态 0:停用 1:启用 + */ + private String enablingState; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/entity/PlayClerkDataReviewInfoEditVo.java --- +package com.starry.admin.modules.clerk.module.entity; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 店员申请对象 play_clerk_data_review_info + * + * @author admin + * @since 2024-04-11 + */ +@Data +@EqualsAndHashCode(callSuper = false) +public class PlayClerkDataReviewInfoEditVo { + + /** + * UUID + */ + private String id; + + /** + * 资料类型[0:店员申请,1:头像;2:相册;3:录音] + */ + private String dataType; + + /** + * 审核状态 0:未审核 1:审核通过 2:审核未通过 + */ + private String state; + + /** + * 备注 + */ + private String remark; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/entity/PlayClerkDataReviewInfoEntity.java --- +package com.starry.admin.modules.clerk.module.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.admin.utils.ListToStringHandle; +import com.starry.common.domain.BaseEntity; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 店员资料审核对象 play_clerk_data_review_info + * + * @author admin + * @since 2024-05-19 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName(value = "play_clerk_data_review_info", autoResultMap = true) +public class PlayClerkDataReviewInfoEntity extends BaseEntity { + + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 店员ID + */ + private String clerkId; + + /** + * 资料类型[0:昵称;1:头像;2:相册;3:录音] + */ + private String dataType; + + /** + * 资料内容 + */ + @TableField(typeHandler = ListToStringHandle.class) + private List dataContent; + + /** + * 审核状态(0:未审核:1:审核通过,2:审核不通过) + */ + private String reviewState; + + /** + * 资料添加时间 + */ + private LocalDateTime addTime; + + /** + * 审核时间 + */ + private LocalDateTime reviewTime; + + /** + * 审核人 + */ + private String reviewBy; + + /** + * 审核内容 + */ + private String reviewCon; + + /** + * 备注 + */ + private String remark; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/entity/PlayClerkDataReviewInfoQueryVo.java --- +package com.starry.admin.modules.clerk.module.entity; + +import com.starry.common.domain.BasePageEntity; +import java.util.Date; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 店员申请对象 play_clerk_data_review_info + * + * @author admin + * @since 2024-04-11 + */ +@Data +@EqualsAndHashCode(callSuper = false) +public class PlayClerkDataReviewInfoQueryVo extends BasePageEntity { + + /** + * UUID + */ + private String id; + + /** + * 资料类型[0:店员申请,1:头像;2:相册;3:录音] + */ + private String dataType; + + /** + * 资料内容(JSON格式) + */ + private String content; + + /** + * 审核状态 0:未审核 1:审核通过 2:审核未通过 + */ + private String state = "0"; + + /** + * 资料添加时间 + */ + private Date addTime; + + /** + * 审核时间 + */ + private Date reviewTime; + + /** + * 审核人 + */ + private String reviewBy; + + /** + * 备注 + */ + private String remark; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/entity/PlayClerkLevelInfoEntity.java --- +package com.starry.admin.modules.clerk.module.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.common.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 店员等级对象 play_clerk_level_info + * + * @author admin + * @since 2024-03-30 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("play_clerk_level_info") +public class PlayClerkLevelInfoEntity extends BaseEntity { + + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 等级名称 + */ + private String name; + + /** + * 等级数字(排序字段) + */ + private Integer level; + + /** + * 首次固定单比例[0 - 100%] + */ + private Integer firstRegularRatio; + + /** + * 非首次固定单比例[0 - 100%] + */ + private Integer notFirstRegularRatio; + + /** + * 首次打赏比例[0 - 100%] + */ + private Integer firstRewardRatio; + + /** + * 非首次打赏比例[0 - 100%] + */ + private Integer notFirstRewardRatio; + + /** + * 首次随机单比例[0 - 100%] + */ + private Integer firstRandomRadio; + + /** + * 非首次随机单比例[0 - 100%] + */ + private Integer notFirstRandomRadio; + + private Integer styleType; + + private String styleImageUrl; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/entity/PlayClerkPkEntity.java --- +package com.starry.admin.modules.clerk.module.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.common.domain.BaseEntity; +import java.util.Date; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 店员pk对象 play_clerk_pk + * + * @author admin + * @since 2024-08-02 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("play_clerk_pk") +public class PlayClerkPkEntity extends BaseEntity { + + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 创建人的id + */ + private String createdBy; + + /** + * 创建时间 + */ + private Date createdTime; + + /** + * 修改人的id + */ + private String updatedBy; + + /** + * 修改时间 + */ + private Date updatedTime; + + /** + * 数据版本 + */ + private Long version; + + /** + * 店员A + */ + private String clerkA; + + /** + * 店员B + */ + private String clerkB; + + /** + * 比例 + */ + private Integer radio; + + /** + * 开始时间 + */ + private Date pkBeginTime; + + /** + * 结束时间 + */ + private Date pkEndTime; + + /** + * 惩罚公示时间 + */ + private Date punishmentTime; + + /** + * 状态 + */ + private String status; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/entity/PlayClerkRankingInfoEntity.java --- +package com.starry.admin.modules.clerk.module.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.starry.common.domain.BaseEntity; +import java.math.BigDecimal; +import java.time.LocalDate; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 店员排行对象 play_clerk_ranking_info + * + * @author admin + * @since 2024-05-25 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("play_clerk_ranking_info") +public class PlayClerkRankingInfoEntity extends BaseEntity { + + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 店员ID + */ + private String clerkId; + + /** + * 是否为历史统计(1:是;0:不是) + */ + private String historicalStatistics; + + /** + * 日排名还是周排名(0:每日排名;1:每周排名) + */ + private String weeklyRanking; + + /** + * 统计批次 + */ + private Integer serialNumber; + + /** + * 排序名次 + */ + private Integer rankingIndex; + + /** + * 开始统计时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private LocalDate startCountDate; + + /** + * 结束统计时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private LocalDate endCountDate; + + /** + * 订单总数 + */ + private Integer orderNumber; + + /** + * 订单金额 + */ + private BigDecimal orderMoney; + + /** + * 续单数 + */ + private Integer orderContinueNumber; + + /** + * 续单金额 + */ + private BigDecimal orderContinueMoney; + + /** + * 超时未接单数量 + */ + private Integer ordersExpiredNumber = 0; + + /** + * 续单比例 + */ + private BigDecimal orderContinueProportion = BigDecimal.ZERO; + + /** + * 用户数 + */ + private Integer customNumber; + + /** + * 订单平均价格 + */ + private BigDecimal averageUnitPrice = BigDecimal.ZERO; + /** + * 距离前一名相差金额 + */ + private BigDecimal previousMoney; + + /** + * 统计时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private LocalDate settlementDate; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/entity/PlayClerkTypeInfoEntity.java --- +package com.starry.admin.modules.clerk.module.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.common.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 店员分类信息对象 play_clerk_type_info + * + * @author admin + * @since 2024-05-31 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("play_clerk_type_info") +public class PlayClerkTypeInfoEntity extends BaseEntity { + + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 分类名称 + */ + private String typeName; + + /** + * 是否在首页显示(0:不显示,1:显示) + */ + private String homeDisplayed; + + /** + * 排序 + */ + private Integer sort; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/entity/PlayClerkTypeUserInfoEntity.java --- +package com.starry.admin.modules.clerk.module.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.common.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 店员和分类关系对象 play_clerk_type_user_info + * + * @author admin + * @since 2024-05-31 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("play_clerk_type_user_info") +public class PlayClerkTypeUserInfoEntity extends BaseEntity { + + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 分组ID + */ + private String typeId; + + /** + * 店员ID + */ + private String clerkId; + + /** + * 排序 + */ + private Integer sort; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/entity/PlayClerkUserDetailResultVo.java --- +package com.starry.admin.modules.clerk.module.entity; + +import java.util.List; +import lombok.Data; + +/** + * @author admin + */ +@Data +public class PlayClerkUserDetailResultVo { + + /** + * UUID + */ + private String id; + + /** + * 店员昵称 + */ + private String nickname; + + /** + * 店员等级 + */ + private String levelId; + + /** + * 店员等级 + */ + private String levelName; + + /** + * 性别[0:未知;1:男;2:女] + */ + private String sex; + + /** + * 头像 + */ + private String avatar; + + /** + * 头像框 + */ + private String avatarFrameId; + + /** + * 音频 + */ + private String audio; + + /** + * 标签 + */ + private String label; + + /** + * 个性签名 + */ + private String signature; + + /** + * 年龄 + */ + private Integer age; + + /** + * 关注(0:未关注,1:已关注) + */ + private String followState = "0"; + /** + * 价格 + */ + private String price; + + /** + * 礼物列表 + */ + + private List gifts; + + /** + * 服务项目 + */ + private List commodity; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/entity/PlayClerkUserEvaluateInfoEntity.java --- +package com.starry.admin.modules.clerk.module.entity; + +import java.util.Date; +import lombok.Data; + +/** + * 店员评价信息 + * + * @author admin + */ +@Data +public class PlayClerkUserEvaluateInfoEntity { + + private String id; + + /** + * 评价人ID + */ + private String evaluatorId; + + /** + * 评价人昵称 + */ + private String evaluatorUsername; + + /** + * 评价人头像 + */ + private String evaluatorAvatar; + + /** + * 评价内容 + */ + private String con; + + /** + * 评价时间 + */ + private Date evaluateTime; + + /** + * 订单ID + */ + private String orderId; + + /** + * 店员昵称 + */ + private String clerkUsername; + + /** + * 商品ID + */ + private String commodityId; + + /** + * 商品名称 + */ + private String commodityName; + + /** + * 商品单位 + */ + private String commodityUnit; + + /** + * 点赞数 + */ + public Integer likeCount; + + public PlayClerkUserEvaluateInfoEntity(String id, String evaluatorId, String evaluatorUsername, + String evaluatorAvatar, String con, Date evaluateTime, String orderId, String clerkUsername, + String commodityId, String commodityName, String commodityUnit) { + this.id = id; + this.evaluatorId = evaluatorId; + this.evaluatorUsername = evaluatorUsername; + this.evaluatorAvatar = evaluatorAvatar; + this.con = con; + this.evaluateTime = evaluateTime; + this.orderId = orderId; + this.clerkUsername = clerkUsername; + this.commodityId = commodityId; + this.commodityName = commodityName; + this.commodityUnit = commodityUnit; + } + + public PlayClerkUserEvaluateInfoEntity(String id, String evaluatorId, String evaluatorUsername, + String evaluatorAvatar, String con, Date evaluateTime, String orderId, String clerkUsername, + String commodityId, String commodityName, String commodityUnit, int likeCount) { + this.id = id; + this.evaluatorId = evaluatorId; + this.evaluatorUsername = evaluatorUsername; + this.evaluatorAvatar = evaluatorAvatar; + this.con = con; + this.evaluateTime = evaluateTime; + this.orderId = orderId; + this.clerkUsername = clerkUsername; + this.commodityId = commodityId; + this.commodityName = commodityName; + this.commodityUnit = commodityUnit; + this.likeCount = likeCount; + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/entity/PlayClerkUserInfoEntity.java --- +package com.starry.admin.modules.clerk.module.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.starry.admin.common.conf.StringTypeHandler; +import com.starry.common.domain.BaseEntity; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 店员对象 play_clerk_user_info + * + * @author admin + * @since 2024-03-30 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName(value = "play_clerk_user_info", autoResultMap = true) +public class PlayClerkUserInfoEntity extends BaseEntity { + + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 电话号码 + */ + private String phone; + + /** + * 微信号码 + */ + private String weiChatCode; + private String weiChatAvatar; + + /** + * 陪聊用户ID + */ + private String sysUserId; + + /** + * 用户的标识,对当前公众号唯一 + */ + private String openid; + + /** + * 店员昵称 + */ + private String nickname; + + /** + * 是否固定等级(0:固定等级,1:不固定) + */ + private String fixingLevel; + + /** + * 分组ID + */ + private String groupId; + + /** + * 店员等级 + */ + private String levelId; + + /** + * 店员类型 + */ + private String typeId; + + /** + * 性别[0:未知;1:男;2:女] + */ + private String sex; + + /** + * 身份证号码 + */ + private String code; + + /** + * 头像 + */ + private String avatar; + + /** + * 头像框 + */ + private String avatarFrameId; + + /** + * 音频 + */ + private String audio; + + /** + * 星座 + */ + private String constellation; + + /** + * 标签 + */ + @TableField(typeHandler = StringTypeHandler.class) + private List label; + + /** + * 个性签名 + */ + private String signature; + + /** + * 年龄 + */ + private Integer age; + + /** + * 所在国家 + */ + private String country; + + /** + * 所在省份 + */ + private String province; + + /** + * 所在城市 + */ + private String city; + + /** + * 账户余额 + */ + private BigDecimal accountBalance; + + /** + * 备注 + */ + private String remark; + + /** + * 在职状态(1:在职,0:离职) + */ + private String onboardingState; + + /** + * 入职时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private LocalDateTime entryTime; + + /** + * 离职时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private LocalDateTime resignationTime; + + /** + * 在职天数 + */ + private Integer workingHours = 0; + + /** + * 是否推荐状态(1:已推荐,0:未推荐) + */ + private String recommendationState; + + /** + * 是否置顶状态(1:已置顶,0:未置顶) + */ + private String pinToTopState; + + /** + * 在线状态【1:在线,0:离线】 + */ + private String onlineState; + + /** + * 上架状态【1:上架,0:下架】 + */ + private String listingState; + + /** + * 显示状态【1:显示,0:隐藏】 + */ + private String displayState; + + /** + * 实名状态【1:已实名,0:未实名】 + */ + private String realState; + + /** + * 是否必须实名【0:非必须实名;1:必须实名;2:跟随店铺设置】 + */ + private String mandatoryRealState; + + /** + * 随机接单状态【1:允许,0:禁止】 + */ + private String randomOrderState; + + /** + * 店员状态(0:不是陪聊,1:陪聊,2:资料审核中) + */ + private String clerkState; + /** + * 相册 + */ + @TableField(typeHandler = StringTypeHandler.class) + private List album; + /** + * 微信二维码 + **/ + private String weChatCodeImage; + + /** + * 微信收款码图片 + **/ + private String weChatPayImage; + + /** + * 支付宝收款码图片 + **/ + private String alipayImage; + + /** + * 创建时间 + **/ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime addTime; + + /** + * 最近一次登录token + */ + @JsonIgnore + private String token; + + public PlayClerkUserInfoEntity() { + } + + public PlayClerkUserInfoEntity(String id, BigDecimal accountBalance) { + this.id = id; + this.accountBalance = accountBalance; + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/entity/PlayClerkUserQueryVo.java --- +package com.starry.admin.modules.clerk.module.entity; + +import com.starry.common.domain.BasePageEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 店员对象 play_clerk_user_info + * + * @author admin + * @since 2024-03-30 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel(value = "店员分页查询参数", description = "分页查询店员列表的条件参数") +public class PlayClerkUserQueryVo extends BasePageEntity { + + /** + * UUID + */ + @ApiModelProperty(value = "店员ID", notes = "唯一标识") + private String id; + + /** + * 昵称 + */ + @ApiModelProperty(value = "店员昵称", notes = "支持模糊查询") + private String nickname; + + /** + * 电话号码 + */ + @ApiModelProperty(value = "电话号码") + private String phone; + + /** + * 分组ID + */ + @ApiModelProperty(value = "分组ID") + private String groupId; + + /** + * 性别[0:未知;1:男;2:女] + */ + @ApiModelProperty(value = "性别", notes = "0:未知;1:男;2:女") + private String sex; + + /** + * 是否固定等级(0:固定等级,1:不固定) + */ + @ApiModelProperty(value = "是否固定等级", notes = "0:固定等级,1:不固定") + private String fixingLevel; + + /** + * 店员等级 + */ + @ApiModelProperty(value = "店员等级ID") + private String levelId; + + /** + * 年龄 + */ + @ApiModelProperty(value = "年龄范围", notes = "年龄区间查询,如[18, 25]") + private List ages; + + /** + * 所在国家 + */ + @ApiModelProperty(value = "所在国家", example = "中国") + private String country; + + /** + * 所在省份 + */ + @ApiModelProperty(value = "所在省份", example = "广东省") + private String province; + + /** + * 所在城市 + */ + @ApiModelProperty(value = "所在城市", example = "深圳市") + private String city; + + /** + * 在职状态(1:在职,0:离职) + */ + @ApiModelProperty(value = "在职状态", notes = "1:在职,0:离职", example = "1") + private String onboardingState = "1"; + + /** + * 是否推荐状态(1:已推荐,0:未推荐) + */ + @ApiModelProperty(value = "是否推荐", notes = "1:已推荐,0:未推荐") + private String recommendationState; + + /** + * 是否置顶状态(1:已置顶,0:未置顶) + */ + @ApiModelProperty(value = "是否置顶", notes = "1:已置顶,0:未置顶") + private String pinToTopState; + + /** + * 在线状态【1:在线,0:离线】 + */ + @ApiModelProperty(value = "在线状态", notes = "1:在线,0:离线") + private String onlineState; + + /** + * 上架状态【1:上架,0:下架】 + */ + @ApiModelProperty(value = "上架状态", notes = "1:上架,0:下架") + private String listingState; + + /** + * 显示状态【1:显示,0:隐藏】 + */ + @ApiModelProperty(value = "显示状态", notes = "1:显示,0:隐藏") + private String displayState; + + /** + * 实名状态【1:已实名,0:未实名】 + */ + @ApiModelProperty(value = "实名状态", notes = "1:已实名,0:未实名") + private String realState; + + /** + * 是否必须实名【0:非必须实名;1:必须实名;2:跟随店铺设置】 + */ + @ApiModelProperty(value = "是否必须实名", notes = "0:非必须实名;1:必须实名;2:跟随店铺设置") + private String mandatoryRealState; + + /** + * 随机接单状态【1:允许,0:禁止】 + */ + @ApiModelProperty(value = "随机接单状态", notes = "1:允许,0:禁止") + private String randomOrderState; + + /** + * 店员状态(0:不是陪聊,1:陪聊,2:资料审核中) + */ + @ApiModelProperty(value = "店员状态", notes = "0:不是陪聊,1:陪聊,2:资料审核中", example = "1") + private String clerkState = "1"; + + /** + * 身份证号 + */ + @ApiModelProperty(value = "身份证号") + private String code; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/entity/PlayClerkUserReturnVo.java --- +package com.starry.admin.modules.clerk.module.entity; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 店员分页查询对象 + * + * @author admin + * @since 2024-03-30 + */ +@Data +@ApiModel(value = "店员详细信息返回对象", description = "分页查询店员详细信息的返回结果") +public class PlayClerkUserReturnVo { + + /** + * UUID + */ + @ApiModelProperty(value = "店员ID", notes = "唯一标识") + private String id; + + /** + * 店员昵称 + */ + @ApiModelProperty(value = "店员昵称") + private String nickname; + + /** + * 店员等级 + */ + @ApiModelProperty(value = "店员等级ID") + private String levelId; + + /** + * 店员等级 + */ + @ApiModelProperty(value = "店员等级名称") + private String levelName; + + /** + * 分组ID + */ + @ApiModelProperty(value = "分组ID") + private String groupId; + + /** + * 分组ID + */ + @ApiModelProperty(value = "分组名称") + private String groupName; + + /** + * 性别[0:未知;1:男;2:女] + */ + @ApiModelProperty(value = "性别", notes = "0:未知;1:男;2:女") + private String sex; + + /** + * 头像 + */ + @ApiModelProperty(value = "头像", notes = "头像图片URL") + private String avatar; + + /** + * 音频 + */ + @ApiModelProperty(value = "音频", notes = "音频文件URL") + private String audio; + + /** + * 星座 + */ + @ApiModelProperty(value = "星座", example = "天蝎座") + private String constellation; + + /** + * 标签 + */ + @ApiModelProperty(value = "标签列表", notes = "店员个人标签") + private List label = new ArrayList<>(); + + /** + * 相册 + */ + @ApiModelProperty(value = "相册列表", notes = "店员相册图片URL列表") + private List album = new ArrayList<>(); + + /** + * 个性签名 + */ + @ApiModelProperty(value = "个性签名") + private String signature; + + /** + * 年龄 + */ + @ApiModelProperty(value = "年龄", example = "25") + private Integer age; + + /** + * 所在省份 + */ + @ApiModelProperty(value = "所在省份", example = "广东省") + private String province; + + /** + * 所在城市 + */ + @ApiModelProperty(value = "所在城市", example = "深圳市") + private String city; + + /** + * 在线状态【1:在线,0:离线】 + */ + @ApiModelProperty(value = "在线状态", notes = "1:在线,0:离线") + private String onlineState; + + /** + * 上架状态【1:上架,0:下架】 + */ + @ApiModelProperty(value = "上架状态", notes = "1:上架,0:下架") + private String listingState; + + /** + * 实名状态【1:已实名,0:未实名】 + */ + @ApiModelProperty(value = "实名状态", notes = "1:已实名,0:未实名") + private String realState; + + /** + * 是否必须实名【0:非必须实名;1:必须实名;2:跟随店铺设置】 + */ + @ApiModelProperty(value = "是否必须实名", notes = "0:非必须实名;1:必须实名;2:跟随店铺设置") + private String mandatoryRealState; + + /** + * 随机接单状态【1:允许,0:禁止】 + */ + @ApiModelProperty(value = "随机接单状态", notes = "1:允许,0:禁止") + private String randomOrderState; + + /** + * 地址 + */ + @ApiModelProperty(value = "地址", notes = "店员所在详细地址") + private String address; + + /** + * 地址 + */ + @ApiModelProperty(value = "备注") + private String remark; + + /** + * 订单列表 + */ + @JsonIgnore + @ApiModelProperty(value = "订单列表", hidden = true) + private List orderInfos; + + /** + * 订单总数 + */ + @ApiModelProperty(value = "订单总数") + private String orderNumber; + + /** + * 续单总数 + */ + @ApiModelProperty(value = "续单总数") + private String orderContinueNumber; + + /** + * 订单总金额 + */ + @ApiModelProperty(value = "订单总金额") + private BigDecimal orderTotalAmount; + + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + @ApiModelProperty(value = "添加时间", example = "2024-01-01 12:00:00") + private LocalDateTime addTime; + + /** + * 入职时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + @ApiModelProperty(value = "入职时间", example = "2024-01-01") + private LocalDateTime entryTime; + + /** + * 离职时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + @ApiModelProperty(value = "离职时间", example = "2024-01-01") + private LocalDateTime resignationTime; + + /** + * 是否推荐状态(1:已推荐,0:未推荐) + */ + @ApiModelProperty(value = "是否推荐", notes = "1:已推荐,0:未推荐") + private String recommendationState; + + /** + * 是否置顶状态(1:已置顶,0:未置顶) + */ + @ApiModelProperty(value = "是否置顶", notes = "1:已置顶,0:未置顶") + private String pinToTopState; + + /** + * 显示状态【1:显示,0:隐藏】 + */ + @ApiModelProperty(value = "显示状态", notes = "1:显示,0:隐藏") + private String displayState; + + /** + * 是否固定等级(0:固定等级,1:不固定) + */ + @ApiModelProperty(value = "是否固定等级", notes = "0:固定等级,1:不固定") + private String fixingLevel; + + /** + * 在职状态(1:在职,0:离职) + */ + @ApiModelProperty(value = "在职状态", notes = "1:在职,0:离职") + private String onboardingState; + + /** + * 在职天数 + */ + @ApiModelProperty(value = "在职天数", example = "365") + private Integer workingHours = 0; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/entity/PlayClerkUserReviewInfoEntity.java --- +package com.starry.admin.modules.clerk.module.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.admin.common.conf.StringTypeHandler; +import com.starry.common.domain.BaseEntity; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 店员申请对象 play_clerk_user_review_info + * + * @author admin + * @since 2024-05-19 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName(value = "play_clerk_user_review_info", autoResultMap = true) +public class PlayClerkUserReviewInfoEntity extends BaseEntity { + + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 店员ID + */ + private String clerkId; + + /** + * 微信号码 + */ + private String weiChatCode; + + /** + * 手机号码 + */ + private String phone; + + /** + * 昵称 + */ + private String nickname; + + /** + * 性别[0:未知;1:男;2:女] + */ + private String sex; + + /** + * 年龄 + */ + private Integer age; + + /** + * 所在省份 + */ + private String province; + + /** + * 所在城市 + */ + private String city; + + /** + * 备注(相关经验) + */ + private String remark; + + /** + * 音频 + */ + private String audio; + + /** + * 照片 + */ + @TableField(typeHandler = StringTypeHandler.class) + private List album; + + /** + * 申请时间 + */ + private LocalDateTime addTime; + + /** + * 审核状态(0:未审核:1:审核通过,2:审核不通过) + */ + private String reviewState; + + /** + * 审核时间 + */ + private LocalDateTime reviewTime; + + /** + * 审核人 + */ + private String reviewBy; + + /** + * 审核内容 + */ + private String reviewCon; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/entity/PlayClerkUserTrendsInfoEntity.java --- +package com.starry.admin.modules.clerk.module.entity; + +import java.util.Date; +import lombok.Data; + +/** + * 店员动态 + * + * @author admin + */ +@Data +public class PlayClerkUserTrendsInfoEntity { + + private String id; + + private String title; + + /** + * 动态类型(0:照片,1:视频) + */ + private String type; + + private String con; + + private Date releaseTime; + + public PlayClerkUserTrendsInfoEntity(String id, String title, String con, Date releaseTime) { + this.id = id; + this.title = title; + this.con = con; + this.releaseTime = releaseTime; + this.type = "1"; + } + + public PlayClerkUserTrendsInfoEntity(String id, String title, String type, String con, Date releaseTime) { + this.id = id; + this.title = title; + this.type = type; + this.con = con; + this.releaseTime = releaseTime; + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/entity/PlayClerkUserTypeEditVo.java --- +package com.starry.admin.modules.clerk.module.entity; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import javax.validation.constraints.NotNull; +import lombok.Data; + +/** + * 店员对象 play_clerk_user_info + * + * @author admin + * @since 2024-03-30 + */ +@Data +@ApiModel(value = "店员分类编辑对象", description = "修改店员分类或分组的参数对象") +public class PlayClerkUserTypeEditVo { + + /** + * 店员分类ID + */ + @NotNull(message = "类型不能为空") + @ApiModelProperty(value = "店员分类/分组ID", required = true, notes = "分类ID或分组ID") + private String typeId; + + /** + * 店员列表 + */ + @NotNull(message = "店员列表不能为空") + @ApiModelProperty(value = "店员ID列表", required = true, notes = "要添加到分类/分组中的店员ID列表") + private List clerkUserIds; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/entity/PlayClerkWagesDetailsInfoEntity.java --- +package com.starry.admin.modules.clerk.module.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.common.domain.BaseEntity; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 店员工资明细信息对象 play_clerk_wages_details_info + * + * @author admin + * @since 2024-05-31 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("play_clerk_wages_details_info") +public class PlayClerkWagesDetailsInfoEntity extends BaseEntity { + + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 工资统计ID + */ + private String wagesId; + + /** + * 店员ID + */ + private String clerkId; + + /** + * 订单ID + */ + private String orderId; + + /** + * 订单编号 + */ + private String orderNo; + + /** + * 订单最终金额(支付金额) + */ + private BigDecimal finalAmount; + + /** + * 店员收入 + */ + private BigDecimal estimatedRevenue; + + /** + * 订单完成时间 + */ + private LocalDateTime endOrderTime; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/entity/PlayClerkWagesInfoEntity.java --- +package com.starry.admin.modules.clerk.module.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.starry.common.domain.BaseEntity; +import java.math.BigDecimal; +import java.time.LocalDate; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 店员工资结算信息对象 play_clerk_wages_info + * + * @author admin + * @since 2024-05-31 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("play_clerk_wages_info") +public class PlayClerkWagesInfoEntity extends BaseEntity { + + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 店员ID + */ + private String clerkId; + + /** + * 是否为往期统计(1:是;0:不是) + **/ + private String historicalStatistics; + + /** + * 统计序号 + */ + private Long serialNumber; + + /** + * 排行序号 + */ + private Long rankingIndex; + + /** + * 开始统计时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private LocalDate startCountDate; + + /** + * 结束统计时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private LocalDate endCountDate; + + /** + * 结算时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private LocalDate settlementDate; + + /** + * 订单总数 + */ + private Integer orderNumber; + + /** + * 订单金额 + */ + private BigDecimal finalAmount; + + /** + * 续单数 + */ + private Integer orderContinueNumber; + + /** + * 续单比例 + */ + private double orderContinueProportion = 0.0; + + /** + * 续单金额 + */ + private BigDecimal orderContinueMoney; + + /** + * 超时未接单数 + */ + private Integer ordersExpiredNumber; + + /** + * 店员收入 + */ + private BigDecimal estimatedRevenue; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/entity/PlayCustomArticleInfoEntity.java --- +package com.starry.admin.modules.clerk.module.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.common.domain.BaseEntity; +import java.time.LocalDateTime; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 陪聊点赞动态信息对象 play_custom_article_info + * + * @author admin + * @since 2024-05-04 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("play_custom_article_info") +public class PlayCustomArticleInfoEntity extends BaseEntity { + + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 动态ID + */ + private String articleId; + + /** + * 店员ID + */ + private String clerkId; + + /** + * 顾客ID + */ + private String customId; + + /** + * 点赞时间 + */ + private LocalDateTime endorseTime; + + /** + * 赞同状态(1:赞同,0:未赞同) + */ + private String endorseState; + + /** + * 操作类型(1:关注;0:收藏) + */ + private String endorseType; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/entity/PlayGiftInfoVo.java --- +package com.starry.admin.modules.clerk.module.entity; + +import lombok.Data; + +/** + * 礼物信息 + * + * @author admin + */ + +@Data +public class PlayGiftInfoVo { + + /** + * 礼物ID + */ + private String id; + + /** + * 礼物名称 + */ + private String name; + + /** + * 礼物地址 + */ + private String url; + + /** + * 获得数量 + */ + private Integer number; + + /** + * 礼物状态(0:正常,1:已下架) + */ + private String state; + + public PlayGiftInfoVo(String id, String name, String url, Integer number, String state) { + this.id = id; + this.name = name; + this.url = url; + this.number = number; + this.state = state; + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/vo/PlayAvatarFrameInfoAddVo.java --- +package com.starry.admin.modules.clerk.module.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import javax.validation.constraints.NotNull; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * @author admin + * @since 2024/6/6 下午11:13 + **/ +@Data +@ApiModel(value = "店员头像框添加参数", description = "新增店员头像框信息的请求参数") +public class PlayAvatarFrameInfoAddVo { + + /** + * 添加时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + @ApiModelProperty(value = "添加时间", hidden = true, notes = "系统自动生成,无需传入") + private final LocalDateTime addTime = LocalDateTime.now(); + /** + * 头像框名称 + */ + @NotNull(message = "头像框名称不能为空") + @ApiModelProperty(value = "头像框名称", required = true, example = "年度贡献者", notes = "头像框的名称") + private String avatarFrameName; + /** + * 头像框地址 + */ + @NotNull(message = "头像框图片不能为空") + @ApiModelProperty(value = "头像框地址", required = true, example = "https://example.com/frame.png", notes = "头像框图片的URL地址") + private String avatarFrameAddress; + /** + * 获取方式(0:手动赠送;1:自动赠送) + */ + @NotNull(message = "头像框获取方式不能为空") + @ApiModelProperty(value = "获取方式", required = true, example = "0", notes = "0:手动赠送;1:自动赠送") + private String accessType; + /** + * 获取条件名称 + */ + @ApiModelProperty(value = "获取条件名称", example = "年度贡献奖", notes = "获取该头像框的条件名称") + private String accessName; + /** + * 获取条件 + */ + @ApiModelProperty(value = "获取条件", example = "年度贡献超过10000元", notes = "获取该头像框的具体条件") + private String accessValue; + /** + * 有效期(单位:天,-1:永久有效) + */ + @NotNull(message = "有效期不能为空") + @ApiModelProperty(value = "有效期", required = true, example = "365", notes = "头像框的有效期,单位:天,-1表示永久有效") + private String periodValidity; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/vo/PlayAvatarFrameInfoQueryVo.java --- +package com.starry.admin.modules.clerk.module.vo; + +import com.starry.common.domain.BasePageEntity; +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @author admin + * @since 2024/6/6 下午11:13 + **/ +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel(value = "店员头像框查询参数", description = "查询店员头像框信息的条件参数") +public class PlayAvatarFrameInfoQueryVo extends BasePageEntity { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/vo/PlayAvatarFrameSendVo.java --- +package com.starry.admin.modules.clerk.module.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotNull; +import lombok.Data; + +/** + * @author admin + * @since 2024/6/6 下午11:13 + **/ +@Data +@ApiModel(value = "店员头像框赠送参数", description = "赠送头像框给店员的请求参数") +public class PlayAvatarFrameSendVo { + + @ApiModelProperty(value = "店员ID", required = true, example = "1", notes = "接收头像框的店员ID") + private String clerkId; + + @NotNull(message = "头像框获取方式不能为空") + @ApiModelProperty(value = "头像框ID", required = true, example = "1", notes = "要赠送的头像框ID") + private String avatarFrameId; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/vo/PlayClerkArticleQueryVo.java --- +package com.starry.admin.modules.clerk.module.vo; + +import com.starry.common.domain.BasePageEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @author admin 动态信息查询对象 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel(value = "店员动态查询参数", description = "查询店员动态信息的条件参数") +public class PlayClerkArticleQueryVo extends BasePageEntity { + + @ApiModelProperty(value = "动态ID", example = "1", notes = "特定动态的ID") + private String id; + + /** + * 店员ID + */ + @ApiModelProperty(value = "店员ID", example = "1", notes = "特定店员的ID") + private String clerkId; + /** + * 审核状态(0:未审核:1:审核通过,2:审核不通过) + */ + @ApiModelProperty(value = "审核状态", example = "0", notes = "0:未审核:1:审核通过,2:审核不通过") + private String reviewState; + + /** + * 发布时间 + */ + @ApiModelProperty(value = "发布时间范围", example = "['2024-01-01 00:00:00','2024-12-31 23:59:59']", notes = "动态发布时间范围,包含开始和结束时间") + private List releaseTime; + + /** + * 顾客ID + */ + @ApiModelProperty(value = "顾客ID", example = "1", notes = "特定顾客的ID") + private String customId; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/vo/PlayClerkArticleReturnVo.java --- +package com.starry.admin.modules.clerk.module.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.starry.admin.modules.clerk.module.entity.PlayCustomArticleInfoEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * @author admin 动态信息查询返回对象 + */ +@Data +@ApiModel(value = "店员动态返回数据", description = "店员动态信息的返回数据") +public class PlayClerkArticleReturnVo { + + /** + * UUID + */ + @ApiModelProperty(value = "动态ID", example = "1") + private String id; + /** + * 陪聊用户ID + */ + @ApiModelProperty(value = "店员ID", example = "1") + private String clerkId; + + /** + * 陪聊用户昵称 + */ + @ApiModelProperty(value = "店员昵称", example = "小明") + private String clerkNickname; + + /** + * 陪聊用户头像 + */ + @ApiModelProperty(value = "店员头像", example = "https://example.com/avatar.jpg") + private String clerkAvatar; + + /** + * 动态内容 + */ + @ApiModelProperty(value = "动态内容", example = "今天天气真好,感谢大家的支持!") + private String articleCon; + + /** + * 动态附件类型(0:图片;1:视频;2:音频) + */ + @ApiModelProperty(value = "附件类型", example = "0", notes = "0:图片;1:视频;2:音频") + private String annexType; + + /** + * 动态附件内容 + */ + @ApiModelProperty(value = "附件内容", example = "[\"https://example.com/photo1.jpg\"]", notes = "附件内容,根据附件类型有不同格式") + private List annexCon; + + /** + * 发布时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + @ApiModelProperty(value = "发布时间", example = "2024-01-01 12:00:00") + private LocalDateTime releaseTime; + + /** + * 备注(审核理由) + */ + @ApiModelProperty(value = "审核理由", example = "内容健康,通过审核") + private String reviewCon; + + /** + * 点赞人数 + */ + @ApiModelProperty(value = "点赞人数", example = "10") + private Integer agreedQuantity = 0; + + /** + * 审核状态(0:未审核:1:审核通过,2:审核不通过) + */ + @ApiModelProperty(value = "审核状态", example = "0", notes = "0:未审核:1:审核通过,2:审核不通过") + private String reviewState; + + /** + * 陪聊点赞动态 + */ + @JsonIgnore + @ApiModelProperty(value = "点赞动态", hidden = true) + private List articleInfoEntities; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/vo/PlayClerkArticleReviewStateEditVo.java --- +package com.starry.admin.modules.clerk.module.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Pattern; +import lombok.Data; + +/** + * @author admin 动态审核 + */ +@Data +@ApiModel(value = "店员动态审核状态修改参数", description = "修改店员动态审核状态的请求参数") +public class PlayClerkArticleReviewStateEditVo { + + @NotBlank(message = "ID不能为空") + @ApiModelProperty(value = "动态ID", required = true, example = "1", notes = "店员动态的ID") + private String id; + + /** + * 审核状态(0:未审核:1:审核通过,2:审核不通过) + */ + @NotBlank(message = "审核状态不能为空") + @Pattern(regexp = "[12]", message = "审核状态必须为1或2") + @ApiModelProperty(value = "审核状态", required = true, example = "1", notes = "1:审核通过,2:审核不通过") + private String reviewState; + + /** + * 发布时间 + */ + @ApiModelProperty(value = "备注", example = "内容健康,通过审核", notes = "审核的备注内容或拒绝原因") + private String remark; + + /** + * 审核时间 + */ + @ApiModelProperty(value = "审核时间", hidden = true, notes = "系统自动生成,无需传入") + private LocalDateTime reviewTime = LocalDateTime.now(); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/vo/PlayClerkCommodityEditVo.java --- +package com.starry.admin.modules.clerk.module.vo; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; +import lombok.Data; + +/** + * @author admin + */ +@Data +public class PlayClerkCommodityEditVo { + + /** + * 项目类型 + */ + @NotNull(message = "项目类型名称不能为空") + private String commodityType; + + /** + * 服务启动状态 0:停用 1:启用 + */ + @NotNull(message = "服务状态不能为空") + @Pattern(regexp = "[01]", message = "服务状态必须为0或1") + private String enablingState; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/vo/PlayClerkCommodityQueryVo.java --- +package com.starry.admin.modules.clerk.module.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author admin + */ +@Data +@ApiModel(value = "陪聊服务项目查询参数", description = "查询陪聊服务项目的条件参数") +public class PlayClerkCommodityQueryVo { + + /** + * 项目类型 + */ + @ApiModelProperty(value = "项目类型", example = "1", notes = "服务项目的类型") + private String commodityType; + + /** + * 服务启动状态 0:停用 1:启用 + */ + @ApiModelProperty(value = "启用状态", example = "1", notes = "0:停用,1:启用") + private String enablingState; + + public PlayClerkCommodityQueryVo(String commodityType, String enablingState) { + this.commodityType = commodityType; + this.enablingState = enablingState; + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/vo/PlayClerkDataReviewQueryVo.java --- +package com.starry.admin.modules.clerk.module.vo; + +import com.starry.common.domain.BasePageEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 店员资料审核对象 play_clerk_data_review_info + * + * @author admin + * @since 2024-05-19 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@ApiModel(value = "店员资料内容审核查询参数", description = "查询店员资料内容审核信息的条件参数") +public class PlayClerkDataReviewQueryVo extends BasePageEntity { + + /** + * UUID + */ + @ApiModelProperty(value = "店员ID", example = "1", notes = "特定店员的ID") + private String clerkId; + + /** + * 资料类型[0:昵称;1:头像;2:相册;3:录音] + */ + @ApiModelProperty(value = "资料类型", example = "1", notes = "0:昵称;1:头像;2:相册;3:录音") + private String dataType; + + /** + * 审核状态(0:未审核:1:审核通过,2:审核不通过) + */ + @ApiModelProperty(value = "审核状态", example = "0", notes = "0:未审核:1:审核通过,2:审核不通过") + private String reviewState; + + /** + * 资料添加时间 + */ + @ApiModelProperty(value = "添加时间范围", example = "['2024-01-01 00:00:00','2024-12-31 23:59:59']", notes = "资料添加时间范围,包含开始和结束时间") + private List addTime; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/vo/PlayClerkDataReviewReturnVo.java --- +package com.starry.admin.modules.clerk.module.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; + +/** + * 店员资料审核对象 play_clerk_data_review_info + * + * @author admin + * @since 2024-05-19 + */ +@Data +@ApiModel(value = "店员资料内容审核返回数据", description = "店员资料内容审核信息的返回数据") +public class PlayClerkDataReviewReturnVo { + + /** + * UUID + */ + @ApiModelProperty(value = "审核记录ID", example = "1") + private String id; + + /** + * 店员ID + */ + @ApiModelProperty(value = "店员ID", example = "1") + private String clerkId; + + /** + * 店员昵称 + */ + @ApiModelProperty(value = "店员昵称", example = "小明") + private String clerkNickname; + + /** + * 店员头像 + */ + @ApiModelProperty(value = "店员头像", example = "https://example.com/avatar.jpg") + private String clerkAvatar; + + /** + * 资料类型[0:昵称;1:头像;2:相册;3:录音] + */ + @ApiModelProperty(value = "资料类型", example = "1", notes = "0:昵称;1:头像;2:相册;3:录音") + private String dataType; + + /** + * 资料内容 + */ + @ApiModelProperty(value = "资料内容", example = "[\"https://example.com/photo1.jpg\"]", notes = "资料内容,根据资料类型有不同格式") + private List dataContent; + + /** + * 审核状态(0:未审核:1:审核通过,2:审核不通过) + */ + @ApiModelProperty(value = "审核状态", example = "0", notes = "0:未审核:1:审核通过,2:审核不通过") + private String reviewState; + + /** + * 资料添加时间 + */ + @ApiModelProperty(value = "添加时间", example = "2024-01-01 12:00:00") + private LocalDateTime addTime; + + /** + * 审核时间 + */ + @ApiModelProperty(value = "审核时间", example = "2024-01-02 12:00:00") + private LocalDateTime reviewTime; + + /** + * 审核人 + */ + @ApiModelProperty(value = "审核人", example = "admin") + private String reviewBy; + + /** + * 审核内容 + */ + @ApiModelProperty(value = "审核内容", example = "资料完整,通过审核") + private String reviewCon; + + /** + * 备注 + */ + @ApiModelProperty(value = "备注", example = "资料清晰可见") + private String remark; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/vo/PlayClerkDataReviewStateEditVo.java --- +package com.starry.admin.modules.clerk.module.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Pattern; +import lombok.Data; + +/** + * @author admin 动态审核 + */ +@Data +@ApiModel(value = "店员资料审核状态修改参数", description = "修改店员资料审核状态的请求参数") +public class PlayClerkDataReviewStateEditVo { + + @NotBlank(message = "ID不能为空") + @ApiModelProperty(value = "审核记录ID", required = true, example = "1", notes = "店员资料审核记录的ID") + private String id; + + /** + * 审核状态(0:未审核:1:审核通过,2:审核不通过) + */ + @NotBlank(message = "审核状态不能为空") + @Pattern(regexp = "[12]", message = "审核状态必须为1或2") + @ApiModelProperty(value = "审核状态", required = true, example = "1", notes = "1:审核通过,2:审核不通过") + private String reviewState; + + /** + * 审核内容 + */ + @ApiModelProperty(value = "审核内容", example = "资料完整,通过审核", notes = "审核的备注内容或拒绝原因") + private String reviewCon; + + /** + * 审核时间 + */ + @ApiModelProperty(value = "审核时间", hidden = true, notes = "系统自动生成,无需传入") + private LocalDateTime reviewTime = LocalDateTime.now(); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/vo/PlayClerkLevelAddVo.java --- +package com.starry.admin.modules.clerk.module.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +/** + * @author admin + */ +@Data +@ApiModel(value = "店员等级添加参数", description = "新增店员等级信息的请求参数") +public class PlayClerkLevelAddVo { + + /** + * 等级名称 + */ + @NotBlank(message = "等级名称不能为空") + @ApiModelProperty(value = "等级名称", required = true, example = "高级店员", notes = "店员等级的名称") + private String name; + + /** + * 首次固定单比例[0 - 100%] + */ + @ApiModelProperty(value = "首次固定单比例", example = "70", notes = "首次固定单提成比例,范围0-100%") + private Integer firstRegularRatio; + + /** + * 非首次固定单比例[0 - 100%] + */ + @ApiModelProperty(value = "非首次固定单比例", example = "60", notes = "非首次固定单提成比例,范围0-100%") + private Integer notFirstRegularRatio; + + /** + * 首次打赏比例[0 - 100%] + */ + @ApiModelProperty(value = "首次打赏比例", example = "80", notes = "首次打赏提成比例,范围0-100%") + private Integer firstRewardRatio; + + /** + * 非首次打赏比例[0 - 100%] + */ + @ApiModelProperty(value = "非首次打赏比例", example = "70", notes = "非首次打赏提成比例,范围0-100%") + private Integer notFirstRewardRatio; + + /** + * 首次随机单比例[0 - 100%] + */ + @ApiModelProperty(value = "首次随机单比例", example = "75", notes = "首次随机单提成比例,范围0-100%") + private Integer firstRandomRadio; + + /** + * 非首次随机单比例[0 - 100%] + */ + @ApiModelProperty(value = "非首次随机单比例", example = "65", notes = "非首次随机单提成比例,范围0-100%") + private Integer notFirstRandomRadio; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/vo/PlayClerkLevelEditVo.java --- +package com.starry.admin.modules.clerk.module.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +/** + * @author admin + */ +@Data +@ApiModel(value = "店员等级修改参数", description = "修改店员等级信息的请求参数") +public class PlayClerkLevelEditVo { + + /** + * 等级名称 + */ + @NotBlank(message = "ID不能为空") + @ApiModelProperty(value = "等级ID", required = true, example = "1", notes = "店员等级的ID") + private String id; + + /** + * 等级名称 + */ + @NotBlank(message = "等级名称不能为空") + @ApiModelProperty(value = "等级名称", required = true, example = "高级店员", notes = "店员等级的名称") + private String name; + + /** + * 首次固定单比例[0 - 100%] + */ + @ApiModelProperty(value = "首次固定单比例", example = "70", notes = "首次固定单提成比例,范围0-100%") + private Integer firstRegularRatio; + + /** + * 非首次固定单比例[0 - 100%] + */ + @ApiModelProperty(value = "非首次固定单比例", example = "60", notes = "非首次固定单提成比例,范围0-100%") + private Integer notFirstRegularRatio; + + /** + * 首次打赏比例[0 - 100%] + */ + @ApiModelProperty(value = "首次打赏比例", example = "80", notes = "首次打赏提成比例,范围0-100%") + private Integer firstRewardRatio; + + /** + * 非首次打赏比例[0 - 100%] + */ + @ApiModelProperty(value = "非首次打赏比例", example = "70", notes = "非首次打赏提成比例,范围0-100%") + private Integer notFirstRewardRatio; + + /** + * 首次随机单比例[0 - 100%] + */ + @ApiModelProperty(value = "首次随机单比例", example = "75", notes = "首次随机单提成比例,范围0-100%") + private Integer firstRandomRadio; + + /** + * 非首次随机单比例[0 - 100%] + */ + @ApiModelProperty(value = "非首次随机单比例", example = "65", notes = "非首次随机单提成比例,范围0-100%") + private Integer notFirstRandomRadio; + + @ApiModelProperty(value = "样式类型", example = "1", notes = "等级样式类型") + private Integer styleType; + + @ApiModelProperty(value = "样式图片URL", example = "https://example.com/style.jpg", notes = "等级样式图片URL") + private String styleImageUrl; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/vo/PlayClerkLevelQueryReturnVo.java --- +package com.starry.admin.modules.clerk.module.vo; + +import lombok.Data; + +/** + * 店员等级查询接口 + * + * @author admin + */ +@Data +public class PlayClerkLevelQueryReturnVo { + + /** + * 等级名称 + */ + private String name; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/vo/PlayClerkTypeInfoAddVo.java --- +package com.starry.admin.modules.clerk.module.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotNull; +import lombok.Data; + +/** + * @author admin + * @since 2024/6/2 下午5:59 + **/ +@Data +@ApiModel(value = "店员分类添加参数", description = "新增店员分类信息的请求参数") +public class PlayClerkTypeInfoAddVo { + + /** + * 分类名称 + */ + @NotNull(message = "分类名称不能为空") + @ApiModelProperty(value = "分类名称", required = true, example = "新人店员", notes = "店员分类的名称") + private String typeName; + + /** + * 是否在首页显示(0:不显示,1:显示) + */ + @NotNull(message = "是否在首页显示不能为空") + @ApiModelProperty(value = "是否在首页显示", required = true, example = "1", notes = "0:不显示,1:显示") + private String homeDisplayed; + + /** + * 排序 + */ + @NotNull(message = "排序不能为空") + @ApiModelProperty(value = "排序", required = true, example = "1", notes = "数字越小排序越靠前") + private Integer sort; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/vo/PlayClerkTypeInfoQueryVo.java --- +package com.starry.admin.modules.clerk.module.vo; + +import com.starry.common.domain.BasePageEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @author admin + * @since 2024/6/16 下午6:51 + **/ +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel(value = "店员分类查询参数", description = "查询店员分类信息的条件参数") +public class PlayClerkTypeInfoQueryVo extends BasePageEntity { + + @ApiModelProperty(value = "分类ID", example = "1", notes = "店员分类的ID") + private String id; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/vo/PlayClerkTypeInfoReturnVo.java --- +package com.starry.admin.modules.clerk.module.vo; + +import lombok.Data; + +/** + * @author admin + * @since 2024/6/16 下午6:51 + **/ +@Data +public class PlayClerkTypeInfoReturnVo { + + private String id; + /** + * 分类名称 + */ + private String typeName; + + /** + * 是否在首页显示(0:不显示,1:显示) + */ + private String homeDisplayed; + + /** + * 排序 + */ + private Integer sort; + + /** + * 店员数 + */ + private Integer clerkNumber; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/vo/PlayClerkUnsettledWagesInfoQueryVo.java --- +package com.starry.admin.modules.clerk.module.vo; + +import com.starry.common.domain.BasePageEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @author admin + * @since 2024/6/3 下午10:08 + **/ +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel(value = "未结算工资查询参数", description = "查询店员未结算工资信息的条件参数") +public class PlayClerkUnsettledWagesInfoQueryVo extends BasePageEntity { + + /** + * 店员ID + */ + @ApiModelProperty(value = "店员ID", example = "1", notes = "特定店员的ID") + private String clerkId; + + /** + * 店员上架状态 + */ + @ApiModelProperty(value = "店员上架状态", example = "1", notes = "1:上架,0:下架") + private String listingState; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/vo/PlayClerkUnsettledWagesInfoReturnVo.java --- +package com.starry.admin.modules.clerk.module.vo; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity; +import java.math.BigDecimal; +import java.util.List; +import lombok.Data; + +/** + * @author admin + * @since 2024/6/3 下午10:08 + **/ +@Data +public class PlayClerkUnsettledWagesInfoReturnVo { + + private String clerkId; + + private String clerkNickname; + + @JsonIgnore + private List orderInfoEntities; + + /** + * 待开始订单-数量 + */ + private Integer orderState1Number; + + /** + * 待开始订单-金额 + */ + private BigDecimal orderState1Money; + + /** + * 服务中订单-数量 + */ + private Integer orderState2Number; + + /** + * 服务中订单-金额 + */ + private BigDecimal orderState2Money; + + /** + * 服务中订单-店员收入 + */ + private BigDecimal orderState2Revenue; + + /** + * 已完成未结算订单-数量 + */ + private Integer orderState3Number; + + /** + * 已完成未结算订单-金额 + */ + private BigDecimal orderState3Money; + + /** + * 已完成未结算订单-店员收入 + */ + private BigDecimal orderState3Revenue; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/vo/PlayClerkUserAddToWxVo.java --- +package com.starry.admin.modules.clerk.module.vo; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +/** + * @author admin + */ +@Data +public class PlayClerkUserAddToWxVo { + + /** + * 店员昵称 + */ + @NotBlank(message = "昵称不能为空") + private String nickname; + + /** + * 性别[0:未知;1:男;2:女] + */ + @NotNull(message = "性别不能为空") + private Integer sex; + + /** + * 年龄 + */ + @NotNull(message = "年龄不能为空") + private int age; + + /** + * 微信号 + */ + @NotBlank(message = "微信号不能为空") + private String weChat; + + /** + * 手机号码区号 + */ + @NotBlank(message = "微信号不能为空") + private String areaCode; + + /** + * 手机号码 + */ + @NotBlank(message = "微信号不能为空") + private String phone; + + /** + * 音频 + */ + @NotBlank(message = "音频不能为空") + private String audioFrequency; + + /** + * 所在国家 + */ + private String country = "中国"; + + /** + * 所在省份 + */ + @NotBlank(message = "省份不能为空") + private String province; + + /** + * 所在城市 + */ + @NotBlank(message = "城市不能为空") + private String city; + + /** + * 备注 + */ + private String remark; + + /** + * 账户状态(1:审批通过,0:注册未审批) + */ + private String accountState = "0"; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/vo/PlayClerkUserAddVo.java --- +package com.starry.admin.modules.clerk.module.vo; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +/** + * @author admin + */ +@Data +public class PlayClerkUserAddVo { + + /** + * 账号ID + */ + @NotBlank(message = "账号不能为空") + private String playUserId; + + /** + * 用户的标识,对当前公众号唯一 + */ + private String openid; + + /** + * 店员昵称 + */ + @NotBlank(message = "昵称不能为空") + private String nickname; + + /** + * 店员等级 + */ + @NotBlank(message = "等级不能为空") + private String levelId; + + /** + * 性别[0:未知;1:男;2:女] + */ + @NotNull(message = "性别不能为空") + private Integer sex; + + /** + * 头像 + */ + @NotBlank(message = "头像不能为空") + private String avatar; + + /** + * 音频 + */ + @NotBlank(message = "音频不能为空") + private String audioFrequency; + + /** + * 星座 + */ + @NotBlank(message = "星座不能为空") + private String constellation; + + /** + * 标签 + */ + private String label; + + /** + * 个性签名 + */ + @NotBlank(message = "签名不能为空") + private String signature; + + /** + * 年龄 + */ + @NotNull(message = "年龄不能为空") + private Long age; + + /** + * 所在国家 + */ + @NotBlank(message = "国家不能为空") + private String country; + + /** + * 所在省份 + */ + @NotBlank(message = "省份不能为空") + private String province; + + /** + * 所在城市 + */ + @NotBlank(message = "城市不能为空") + private String city; + + /** + * 备注 + */ + private String remark; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/vo/PlayClerkUserEditVo.java --- +package com.starry.admin.modules.clerk.module.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +/** + * @author admin + */ +@Data +@ApiModel(value = "店员编辑对象", description = "修改店员基本信息的参数对象") +public class PlayClerkUserEditVo { + + /** + * id + */ + @NotBlank(message = "id不能为空") + @ApiModelProperty(value = "店员ID", required = true, notes = "唯一标识") + private String id; + + /** + * 账号ID + */ + @NotBlank(message = "账号不能为空") + @ApiModelProperty(value = "账号ID", required = true, notes = "关联的用户账号ID") + private String playUserId; + + /** + * 用户的标识,对当前公众号唯一 + */ + @ApiModelProperty(value = "微信OpenID", notes = "用户在微信公众号中的唯一标识") + private String openid; + + /** + * 店员昵称 + */ + @NotBlank(message = "昵称不能为空") + @ApiModelProperty(value = "店员昵称", required = true) + private String nickname; + + /** + * 店员等级 + */ + @NotBlank(message = "等级不能为空") + @ApiModelProperty(value = "店员等级ID", required = true) + private String levelId; + + /** + * 性别[0:未知;1:男;2:女] + */ + @NotNull(message = "性别不能为空") + @ApiModelProperty(value = "性别", required = true, notes = "0:未知;1:男;2:女") + private String sex; + + /** + * 头像 + */ + @NotBlank(message = "头像不能为空") + @ApiModelProperty(value = "头像", required = true, notes = "头像图片URL") + private String avatar; + + /** + * 音频 + */ + @NotBlank(message = "音频不能为空") + @ApiModelProperty(value = "音频", required = true, notes = "音频文件URL") + private String audioFrequency; + + /** + * 星座 + */ + @NotBlank(message = "星座不能为空") + @ApiModelProperty(value = "星座", required = true, example = "天蝎座") + private String constellation; + + /** + * 标签 + */ + @ApiModelProperty(value = "标签", notes = "店员个人标签,多个标签用逗号分隔") + private String label; + + /** + * 个性签名 + */ + @NotBlank(message = "签名不能为空") + @ApiModelProperty(value = "个性签名", required = true) + private String signature; + + /** + * 年龄 + */ + @NotNull(message = "年龄不能为空") + @ApiModelProperty(value = "年龄", required = true, example = "25") + private Long age; + + /** + * 所在国家 + */ + @NotBlank(message = "国家不能为空") + @ApiModelProperty(value = "所在国家", required = true, example = "中国") + private String country; + + /** + * 所在省份 + */ + @NotBlank(message = "省份不能为空") + @ApiModelProperty(value = "所在省份", required = true, example = "广东省") + private String province; + + /** + * 所在城市 + */ + @NotBlank(message = "城市不能为空") + @ApiModelProperty(value = "所在城市", required = true, example = "深圳市") + private String city; + + /** + * 备注 + */ + @ApiModelProperty(value = "备注", notes = "店员的备注信息") + private String remark; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/vo/PlayClerkUserReviewQueryVo.java --- +package com.starry.admin.modules.clerk.module.vo; + +import com.starry.common.domain.BasePageEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 店员申请审核 + * + * @author admin + * @since 2024/5/19 下午4:21 + **/ +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel(value = "店员资料审核查询参数", description = "查询店员资料审核信息的条件参数") +public class PlayClerkUserReviewQueryVo extends BasePageEntity { + + /** + * 店员ID + */ + @ApiModelProperty(value = "店员ID", example = "1", notes = "特定店员的ID") + private String clerkId; + + /** + * 店员昵称 + */ + @ApiModelProperty(value = "店员昵称", example = "小明", notes = "店员的昵称,支持模糊查询") + private String nickname; + + /** + * 性别[0:未知;1:男;2:女] + */ + @ApiModelProperty(value = "性别", example = "1", notes = "0:未知;1:男;2:女") + private String sex; + + /** + * 手机号码 + */ + @ApiModelProperty(value = "手机号码", example = "13800138000", notes = "店员的手机号码") + private String phone; + + /** + * 微信号 + */ + @ApiModelProperty(value = "微信号", example = "wx123456", notes = "店员的微信号") + private String weiChatCode; + + /** + * 审核状态(0:未审核:1:审核通过,2:审核不通过) + */ + @ApiModelProperty(value = "审核状态", example = "0", notes = "0:未审核:1:审核通过,2:审核不通过") + private String reviewState; + + /** + * 申请时间 + */ + @ApiModelProperty(value = "申请时间范围", example = "['2024-01-01 00:00:00','2024-12-31 23:59:59']", notes = "申请时间范围,包含开始和结束时间") + private List addTime; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/vo/PlayClerkUserReviewReturnVo.java --- +package com.starry.admin.modules.clerk.module.vo; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.starry.admin.common.conf.StringTypeHandler; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 店员申请审核 + * + * @author admin + * @since 2024/5/19 下午4:21 + **/ +@Data +@ApiModel(value = "店员资料审核返回数据", description = "店员资料审核信息的返回数据") +public class PlayClerkUserReviewReturnVo { + + @ApiModelProperty(value = "审核记录ID", example = "1") + private String id; + + /** + * 店员ID + */ + @ApiModelProperty(value = "店员ID", example = "1") + private String clerkId; + + /** + * 店员昵称 + */ + @ApiModelProperty(value = "店员昵称", example = "小明") + private String clerkNickname; + + /** + * 店员头像 + */ + @ApiModelProperty(value = "店员头像", example = "https://example.com/avatar.jpg") + private String clerkAvatar; + + /** + * 微信号码 + */ + @ApiModelProperty(value = "微信号", example = "wx123456") + private String weiChatCode; + + /** + * 手机号码 + */ + @ApiModelProperty(value = "手机号码", example = "13800138000") + private String phone; + + /** + * 昵称 + */ + @ApiModelProperty(value = "昵称", example = "小明") + private String nickname; + + /** + * 性别[0:未知;1:男;2:女] + */ + @ApiModelProperty(value = "性别", example = "1", notes = "0:未知;1:男;2:女") + private String sex; + + /** + * 年龄 + */ + @ApiModelProperty(value = "年龄", example = "25") + private Integer age; + + /** + * 所在省份 + */ + @ApiModelProperty(value = "所在省份", example = "广东省") + private String province; + + /** + * 所在城市 + */ + @ApiModelProperty(value = "所在城市", example = "深圳市") + private String city; + + /** + * 备注(相关经验) + */ + @ApiModelProperty(value = "备注", example = "有3年相关经验") + private String remark; + + /** + * 音频 + */ + @ApiModelProperty(value = "音频", example = "https://example.com/audio.mp3") + private String audio; + + /** + * 照片 + */ + @TableField(typeHandler = StringTypeHandler.class) + @ApiModelProperty(value = "照片", example = "[\"https://example.com/photo1.jpg\",\"https://example.com/photo2.jpg\"]") + private List album = new ArrayList<>(); + + /** + * 申请时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + @ApiModelProperty(value = "申请时间", example = "2024-01-01 12:00:00") + private LocalDateTime addTime; + + /** + * 审核状态(0:未审核:1:审核通过,2:审核不通过) + */ + @ApiModelProperty(value = "审核状态", example = "0", notes = "0:未审核:1:审核通过,2:审核不通过") + private String reviewState; + + /** + * 审核时间 + */ + @ApiModelProperty(value = "审核时间", example = "2024-01-02 12:00:00") + private LocalDateTime reviewTime; + + /** + * 审核人 + */ + @ApiModelProperty(value = "审核人", example = "admin") + private String reviewBy; + + /** + * 审核内容 + */ + @ApiModelProperty(value = "审核内容", example = "资料完整,通过审核") + private String reviewCon; + + /** + * 个性签名 + */ + @ApiModelProperty(value = "个性签名", example = "用心服务每一位客户") + private String signature; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/vo/PlayClerkUserReviewStateEditVo.java --- +package com.starry.admin.modules.clerk.module.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Pattern; +import lombok.Data; + +/** + * @author admin 动态审核 + */ +@Data +@ApiModel(value = "店员资料审核状态修改参数", description = "修改店员资料审核状态的请求参数") +public class PlayClerkUserReviewStateEditVo { + + @NotBlank(message = "ID不能为空") + @ApiModelProperty(value = "审核记录ID", required = true, example = "1", notes = "店员资料审核记录的ID") + private String id; + + /** + * 审核状态(0:未审核:1:审核通过,2:审核不通过) + */ + @NotBlank(message = "审核状态不能为空") + @Pattern(regexp = "[12]", message = "审核状态必须为1或2") + @ApiModelProperty(value = "审核状态", required = true, example = "1", notes = "1:审核通过,2:审核不通过") + private String reviewState; + + /** + * 发布时间 + */ + @ApiModelProperty(value = "审核内容", example = "资料完整,通过审核", notes = "审核的备注内容或拒绝原因") + private String reviewCon; + + /** + * 审核时间 + */ + @ApiModelProperty(value = "审核时间", hidden = true, notes = "系统自动生成,无需传入") + private LocalDateTime reviewTime = LocalDateTime.now(); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/vo/PlayClerkUserStateEditVo.java --- +package com.starry.admin.modules.clerk.module.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +/** + * @author admin + */ +@Data +@ApiModel(value = "店员状态编辑对象", description = "修改店员状态信息的参数对象") +public class PlayClerkUserStateEditVo { + + /** + * id + */ + @NotBlank(message = "id不能为空") + @ApiModelProperty(value = "店员ID", required = true, notes = "唯一标识") + private String id; + + /** + * 是否推荐状态(1:已推荐,0:未推荐) + */ + @ApiModelProperty(value = "是否推荐", notes = "1:已推荐,0:未推荐") + private String recommendationState; + + private String avatar; + + /** + * 是否置顶状态(1:已置顶,0:未置顶) + */ + @ApiModelProperty(value = "是否置顶", notes = "1:已置顶,0:未置顶") + private String pinToTopState; + + /** + * 在线状态【1:在线,0:离线】 + */ + @ApiModelProperty(value = "在线状态", notes = "1:在线,0:离线") + private String onlineState; + + /** + * 上架状态【1:上架,0:下架】 + */ + @ApiModelProperty(value = "上架状态", notes = "1:上架,0:下架") + private String listingState; + + /** + * 显示状态【1:显示,0:隐藏】 + */ + @ApiModelProperty(value = "显示状态", notes = "1:显示,0:隐藏") + private String displayState; + + /** + * 实名状态【1:已实名,0:未实名】 + */ + @ApiModelProperty(value = "实名状态", notes = "1:已实名,0:未实名") + private String realState; + + /** + * 是否必须实名【0:非必须实名;1:必须实名;2:跟随店铺设置】 + */ + @ApiModelProperty(value = "是否必须实名", notes = "0:非必须实名;1:必须实名;2:跟随店铺设置") + private String mandatoryRealState; + + /** + * 随机接单状态【1:允许,0:禁止】 + */ + @ApiModelProperty(value = "随机接单状态", notes = "1:允许,0:禁止") + private String randomOrderState; + + /** + * 是否固定等级(0:固定等级,1:不固定) + */ + @ApiModelProperty(value = "是否固定等级", notes = "0:固定等级,1:不固定") + private String fixingLevel; + + /** + * 在职状态(1:在职,0:离职) + */ + @ApiModelProperty(value = "在职状态", notes = "1:在职,0:离职", example = "1") + private String onboardingState = "1"; + + /** + * 在职状态(1:在职,0:离职) + */ + @ApiModelProperty(value = "店员等级ID") + private String levelId; + + @ApiModelProperty(value = "备注", notes = "店员状态的备注信息") + private String remark; + + @ApiModelProperty(value = "性别", notes = "0:未知;1:男;2:女") + private String sex; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/vo/PlayClerkWagesInfoQueryVo.java --- +package com.starry.admin.modules.clerk.module.vo; + +import com.starry.common.domain.BasePageEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @author admin + * @since 2024/6/3 下午10:08 + **/ +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel(value = "工资历史查询参数", description = "查询店员历史工资结算信息的条件参数") +public class PlayClerkWagesInfoQueryVo extends BasePageEntity { + + /** + * 店员ID + */ + @ApiModelProperty(value = "店员ID", example = "1", notes = "特定店员的ID") + private String clerkId; + + /** + * 店员分组 + */ + @ApiModelProperty(value = "店员分组ID", example = "1", notes = "店员所属分组的ID") + private String groupId; + /** + * 店员上架状态 + */ + @ApiModelProperty(value = "店员上架状态", example = "1", notes = "1:上架,0:下架") + private String listingState; + + /** + * 统计时间 + */ + @ApiModelProperty(value = "统计时间", example = "2024-06", notes = "工资结算的月份,格式为yyyy-MM") + private String settlementDate; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/module/vo/PlayClerkWagesInfoReturnVo.java --- +package com.starry.admin.modules.clerk.module.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * @author admin + * @since 2024/6/3 下午10:08 + **/ +@Data +public class PlayClerkWagesInfoReturnVo { + + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 店员ID + */ + private String clerkId; + + /** + * 店员昵称 + */ + private String clerkNickname; + + /** + * 是否为往期统计(1:是;0:不是) + **/ + private String historicalStatistics; + + /** + * 统计序号 + */ + private Long serialNumber; + + /** + * 排行序号 + */ + private Long rankingIndex; + + /** + * 开始统计时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private LocalDate startCountDate; + + /** + * 结束统计时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private LocalDate endCountDate; + + /** + * 结算时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private LocalDateTime settlementDate; + + /** + * 订单总数 + */ + private Integer orderNumber; + + /** + * 订单金额 + */ + private BigDecimal finalAmount; + + /** + * 续单数 + */ + private Integer orderContinueNumber; + + /** + * 续单金额 + */ + private BigDecimal orderContinueMoney; + + /** + * 超时未接单数 + */ + private Integer ordersExpiredNumber; + + /** + * 店员收入 + */ + private BigDecimal estimatedRevenue = BigDecimal.ZERO; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/service/IPlayAvatarFrameInfoService.java --- +package com.starry.admin.modules.clerk.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.clerk.module.entity.PlayAvatarFrameInfoEntity; +import com.starry.admin.modules.clerk.module.vo.PlayAvatarFrameInfoQueryVo; +import java.util.List; + +/** + * 店员头像框Service接口 + * + * @author admin + * @since 2024-06-06 + */ +public interface IPlayAvatarFrameInfoService extends IService { + /** + * 查询店员头像框 + * + * @param id + * 店员头像框主键 + * @return 店员头像框 + */ + PlayAvatarFrameInfoEntity selectPlayAvatarFrameInfoById(String id); + + /** + * 查询店员头像框列表 + * + * @return 店员头像框集合 + */ + List selectAll(); + + /** + * 查询店员头像框列表 + * + * @param vo + * 店员头像框 + * @return 店员头像框集合 + */ + IPage selectByPage(PlayAvatarFrameInfoQueryVo vo); + + /** + * 查询店员头像框列表 + * + * @param playAvatarFrameInfo + * 店员头像框 + * @return 店员头像框集合 + */ + IPage selectPlayAvatarFrameInfoByPage(PlayAvatarFrameInfoEntity playAvatarFrameInfo); + + /** + * 新增店员头像框 + * + * @param playAvatarFrameInfo + * 店员头像框 + * @return 结果 + */ + boolean create(PlayAvatarFrameInfoEntity playAvatarFrameInfo); + + /** + * 修改店员头像框 + * + * @param playAvatarFrameInfo + * 店员头像框 + * @return 结果 + */ + boolean update(PlayAvatarFrameInfoEntity playAvatarFrameInfo); + + /** + * 批量删除店员头像框 + * + * @param ids + * 需要删除的店员头像框主键集合 + * @return 结果 + */ + int deletePlayAvatarFrameInfoByIds(String[] ids); + + /** + * 删除店员头像框信息 + * + * @param id + * 店员头像框主键 + * @return 结果 + */ + int deletePlayAvatarFrameInfoById(String id); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/service/IPlayClerkArticleInfoService.java --- +package com.starry.admin.modules.clerk.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.clerk.module.entity.PlayClerkArticleInfoEntity; +import com.starry.admin.modules.clerk.module.vo.PlayClerkArticleQueryVo; +import com.starry.admin.modules.clerk.module.vo.PlayClerkArticleReturnVo; +import com.starry.admin.modules.weichat.entity.article.PlayClerkArticleCustomQueryVo; +import com.starry.admin.modules.weichat.entity.article.PlayClerkArticleCustomReturnVo; + +/** + * 店员动态信息Service接口 + * + * @author admin + * @since 2024-05-04 + */ +public interface IPlayClerkArticleInfoService extends IService { + /** + * 查询店员动态信息 + * + * @param id + * 店员动态信息主键 + * @return 店员动态信息 + */ + PlayClerkArticleInfoEntity selectPlayClerkArticleInfoById(String id); + + /** + * 查询店员动态信息列表 + * + * @param vo + * 店员动态信息查询对象 + * @param searchByYourself + * 查询人是否是自己 + * + * @return 店员动态信息集合 + */ + IPage selectByPage(PlayClerkArticleQueryVo vo, boolean searchByYourself); + + /** + * 顾客查询动态列表 + * + * @param customId + * 顾客ID + * @param customId + * 动态查询对象 + * @return PlayClerkArticleCustomReturnVo + */ + IPage customSelectByPage(PlayClerkArticleCustomQueryVo vo, String customId); + + /** + * 新增店员动态信息 + * + * @param playClerkArticleInfo + * 店员动态信息 + * @return 结果 + */ + boolean create(PlayClerkArticleInfoEntity playClerkArticleInfo); + + /** + * 修改店员动态信息 + * + * @param playClerkArticleInfo + * 店员动态信息 + * @return 结果 + */ + boolean update(PlayClerkArticleInfoEntity playClerkArticleInfo); + + /** + * 批量删除店员动态信息 + * + * @param ids + * 需要删除的店员动态信息主键集合 + * @return 结果 + */ + int deletePlayClerkArticleInfoByIds(String[] ids); + + /** + * 删除店员动态信息信息 + * + * @param id + * 店员动态信息主键 + * @return 结果 + */ + int deletePlayClerkArticleInfoById(String id); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/service/IPlayClerkClassificationInfoService.java --- +package com.starry.admin.modules.clerk.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.clerk.module.entity.PlayClerkClassificationInfoEntity; +import java.util.List; + +/** + * 店员分类Service接口 + * + * @author admin + * @since 2024-04-06 + */ +public interface IPlayClerkClassificationInfoService extends IService { + /** + * 查询店员分类 + * + * @param id + * 店员分类主键 + * @return 店员分类 + */ + PlayClerkClassificationInfoEntity selectPlayClerkClassificationInfoById(String id); + + /** + * 查询店员分类列表 + * + * @return 店员分类集合 + */ + List selectAll(); + + /** + * 查询店员分类列表 + * + * @param playClerkClassificationInfo + * 店员分类 + * @return 店员分类集合 + */ + IPage selectPlayClerkClassificationInfoByPage( + PlayClerkClassificationInfoEntity playClerkClassificationInfo); + + /** + * 新增店员分类 + * + * @param playClerkClassificationInfo + * 店员分类 + * @return 结果 + */ + boolean create(PlayClerkClassificationInfoEntity playClerkClassificationInfo); + + /** + * 修改店员分类 + * + * @param playClerkClassificationInfo + * 店员分类 + * @return 结果 + */ + boolean update(PlayClerkClassificationInfoEntity playClerkClassificationInfo); + + /** + * 批量删除店员分类 + * + * @param ids + * 需要删除的店员分类主键集合 + * @return 结果 + */ + int deletePlayClerkClassificationInfoByIds(String[] ids); + + /** + * 删除店员分类信息 + * + * @param id + * 店员分类主键 + * @return 结果 + */ + int deletePlayClerkClassificationInfoById(String id); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/service/IPlayClerkCommodityService.java --- +package com.starry.admin.modules.clerk.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.clerk.module.entity.PlayClerkCommodityEntity; +import java.util.List; + +/** + * 陪聊服务项目Service接口 + * + * @author admin + * @since 2024-03-31 + */ +public interface IPlayClerkCommodityService extends IService { + + /** + * 初始化当前陪聊服务项目 + * + * @param playUserId + * 账号ID + */ + void initClerkCommodity(String playUserId); + + /** + * 根据用户ID,查询当前用户的服务项目类型 + * + * @param userId + * 用户ID + * @param enablingState + * 服务启动状态[0:停用;1:启用] + * @return 服务项目类型 + */ + List getClerkCommodityList(String userId, String enablingState); + + /** + * 根据用户ID,查询当前店员所有服务项目 + * + * @param userId + * 用户ID + * @param enablingState + * 服务启动状态[0:停用;1:启用] + * @return List + */ + List selectCommodityTypeByUser(String userId, String enablingState); + + /** + * 根据用户ID,查询当前用户的服务项目 + * + * @param playUserId + * 用户ID + * @return List + */ + List selectByUser(String playUserId); + + /** + * 查询当前陪聊所有服务项目 + * + * @return List + */ + List selectAll(); + + /** + * 启停当前陪聊服务项目 + * + * @param type + * 项目名称 + * @param enablingState + * 启停状态 + * @param clerkUserId + * 陪聊ID + */ + void startStopClerkItem(String type, String enablingState, String clerkUserId); + + /** + * 查询陪聊服务项目 + * + * @param id + * 陪聊服务项目主键 + * @return 陪聊服务项目 + */ + PlayClerkCommodityEntity selectPlayClerkCommodityById(String id); + + /** + * 查询陪聊服务项目列表 + * + * @param playClerkCommodity + * 陪聊服务项目 + * @return 陪聊服务项目集合 + */ + IPage selectPlayClerkCommodityByPage(PlayClerkCommodityEntity playClerkCommodity); + + /** + * 新增陪聊服务项目 + * + * @param playClerkCommodity + * 陪聊服务项目 + * @return 结果 + */ + boolean create(PlayClerkCommodityEntity playClerkCommodity); + + /** + * 修改陪聊服务项目 + * + * @param playClerkCommodity + * 陪聊服务项目 + * @return 结果 + */ + boolean update(PlayClerkCommodityEntity playClerkCommodity); + + /** + * 批量删除陪聊服务项目 + * + * @param ids + * 需要删除的陪聊服务项目主键集合 + * @return 结果 + */ + int deletePlayClerkCommodityByIds(String[] ids); + + /** + * 删除陪聊服务项目信息 + * + * @param id + * 陪聊服务项目主键 + * @return 结果 + */ + int deletePlayClerkCommodityById(String id); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/service/IPlayClerkDataReviewInfoService.java --- +package com.starry.admin.modules.clerk.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.clerk.module.entity.PlayClerkDataReviewInfoEntity; +import com.starry.admin.modules.clerk.module.vo.PlayClerkDataReviewQueryVo; +import com.starry.admin.modules.clerk.module.vo.PlayClerkDataReviewReturnVo; +import com.starry.admin.modules.clerk.module.vo.PlayClerkDataReviewStateEditVo; +import java.util.List; + +/** + * 店员资料审核Service接口 + * + * @author admin + * @since 2024-05-19 + */ +public interface IPlayClerkDataReviewInfoService extends IService { + /** + * 查询店员资料审核 + * + * @param id + * 店员资料审核主键 + * @return 店员资料审核 + */ + PlayClerkDataReviewInfoEntity selectPlayClerkDataReviewInfoById(String id); + + /** + * 查询店员资料申请 + * + * @param clerkId + * 店员ID + * @param reviewState + * 审核状态(0:未审核:1:审核通过,2:审核不通过) + * @return PlayClerkDataReviewInfoEntity + */ + List queryByClerkId(String clerkId, String reviewState); + + /** + * 查询店员资料申请 + * + * @param clerkId + * 店员ID + * @param dataType + * 资料类型[0:昵称;1:头像;2:相册;3:录音] + * @param reviewState + * 审核状态(0:未审核:1:审核通过,2:审核不通过) + * @return PlayClerkDataReviewInfoEntity + */ + PlayClerkDataReviewInfoEntity queryByClerkId(String clerkId, String dataType, String reviewState); + + /** + * 查询店员资料审核列表 + * + * @param vo + * 店员资料审核 + * @return 店员资料审核集合 + */ + IPage selectByPage(PlayClerkDataReviewQueryVo vo); + + /** + * 新增店员资料审核 + * + * @param playClerkDataReviewInfo + * 店员资料审核 + * @return 结果 + */ + boolean create(PlayClerkDataReviewInfoEntity playClerkDataReviewInfo); + + /** + * 修改店员资料审核状态 + * + * @param vo + * PlayClerkDataReviewStateEditVo + */ + void updateDataReviewState(PlayClerkDataReviewStateEditVo vo); + /** + * 修改店员资料审核 + * + * @param playClerkDataReviewInfo + * 店员资料审核 + * @return 结果 + */ + boolean update(PlayClerkDataReviewInfoEntity playClerkDataReviewInfo); + + /** + * 批量删除店员资料审核 + * + * @param ids + * 需要删除的店员资料审核主键集合 + * @return 结果 + */ + int deletePlayClerkDataReviewInfoByIds(String[] ids); + + /** + * 删除店员资料审核信息 + * + * @param id + * 店员资料审核主键 + * @return 结果 + */ + int deletePlayClerkDataReviewInfoById(String id); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/service/IPlayClerkLevelInfoService.java --- +package com.starry.admin.modules.clerk.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.clerk.module.entity.PlayClerkLevelInfoEntity; +import com.starry.admin.modules.system.module.entity.SysTenantEntity; +import java.util.List; + +/** + * 店员等级Service接口 + * + * @author admin + * @since 2024-03-30 + */ +public interface IPlayClerkLevelInfoService extends IService { + + /** + * 初始化店员等级 + * + * @param sysTenantEntity + * 租户信息 + * @author admin + * @since 2024/7/19 15:13 + **/ + void initDefaultLevel(SysTenantEntity sysTenantEntity); + + /** + * 获取新增陪聊时,默认最低等级ID + * + * @return PlayClerkLevelInfoEntity + */ + PlayClerkLevelInfoEntity getDefaultLevel(); + + /** + * 查询店员等级 + * + * @param id + * 店员等级主键 + * @return 店员等级 + */ + PlayClerkLevelInfoEntity selectPlayClerkLevelInfoById(String id); + + /** + * 查询店员等级列表 + * + * @return 店员等级集合 + */ + List selectAll(); + + /** + * 分页查询店员等级列表 + * + * @param playClerkLevelInfo + * 店员等级 + * @return 店员等级集合 + */ + IPage selectPlayClerkLevelInfoByPage(PlayClerkLevelInfoEntity playClerkLevelInfo); + + /** + * 新增店员等级 + * + * @param playClerkLevelInfo + * 店员等级 + * @return 结果 + */ + boolean create(PlayClerkLevelInfoEntity playClerkLevelInfo); + + /** + * 修改店员等级 + * + * @param playClerkLevelInfo + * 店员等级 + * @return 结果 + */ + boolean update(PlayClerkLevelInfoEntity playClerkLevelInfo); + + /** + * 批量删除店员等级 + * + * @param ids + * 需要删除的店员等级主键集合 + * @return 结果 + */ + int deletePlayClerkLevelInfoByIds(String[] ids); + + /** + * 删除店员等级信息 + * + * @param id + * 店员等级主键 + * @return 结果 + */ + int deletePlayClerkLevelInfoById(String id); + + /** + * 查询最大等级 + * + * @return 最大等级 + */ + int selectMaxLevel(); + + /** + * 删除最大等级 + */ + void delMaxLevelByLevel(Integer level); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/service/IPlayClerkPkService.java --- +package com.starry.admin.modules.clerk.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.clerk.module.entity.PlayClerkPkEntity; + +/** + * 店员pkService接口 + * + * @author admin + * @since 2024-08-02 + */ +public interface IPlayClerkPkService extends IService { + /** + * 查询店员pk + * + * @param id + * 店员pk主键 + * @return 店员pk + */ + PlayClerkPkEntity selectPlayClerkPkById(String id); + + /** + * 查询店员pk列表 + * + * @param playClerkPk + * 店员pk + * @return 店员pk集合 + */ + IPage selectPlayClerkPkByPage(PlayClerkPkEntity playClerkPk); + + /** + * 新增店员pk + * + * @param playClerkPk + * 店员pk + * @return 结果 + */ + boolean create(PlayClerkPkEntity playClerkPk); + + /** + * 修改店员pk + * + * @param playClerkPk + * 店员pk + * @return 结果 + */ + boolean update(PlayClerkPkEntity playClerkPk); + + /** + * 批量删除店员pk + * + * @param ids + * 需要删除的店员pk主键集合 + * @return 结果 + */ + int deletePlayClerkPkByIds(String[] ids); + + /** + * 删除店员pk信息 + * + * @param id + * 店员pk主键 + * @return 结果 + */ + int deletePlayClerkPkById(String id); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/service/IPlayClerkRankingInfoService.java --- +package com.starry.admin.modules.clerk.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.clerk.module.entity.IPlayClerkRankingInfoQueryVo; +import com.starry.admin.modules.clerk.module.entity.IPlayClerkRankingInfoReturnVo; +import com.starry.admin.modules.clerk.module.entity.PlayClerkRankingInfoEntity; +import com.starry.admin.modules.weichat.entity.order.PlayOrderHistoryRankingReturnVo; +import com.starry.admin.modules.weichat.entity.order.PlayOrderRankingReturnVo; +import java.time.LocalDate; +import java.util.List; + +/** + * 店员排行Service接口 + * + * @author admin + * @since 2024-05-25 + */ +public interface IPlayClerkRankingInfoService extends IService { + + /** + * 分页查询店员排行 + * + * @param vo + * 店员排行查询对象 + * @return 店员排查询对象 + */ + IPage selectByPage(IPlayClerkRankingInfoQueryVo vo); + + /** + * 查询店员排行 + * + * @param id + * 店员排行主键 + * @return 店员排行 + */ + PlayClerkRankingInfoEntity selectPlayClerkRankingInfoById(String id); + + /** + * 查询店员排行列表 + * + * @param playClerkRankingInfo + * 店员排行 + * @return 店员排行集合 + */ + IPage selectPlayClerkRankingInfoByPage(PlayClerkRankingInfoEntity playClerkRankingInfo); + + /** + * 根据统计批次更新排名数据 + * + * @param weeklyRanking + * 日排名还是周排名(0:每日排名;1:每周排名) + * @param serialNumber + * 统计批次 + * @author admin + * @since 2024/6/12 15:47 + **/ + void updateClerkRankingInfo(String weeklyRanking, Integer serialNumber); + + /** + * 查询当前排行榜最后一个批次值 + * + * @param weeklyRanking + * 日排名还是周排名(0:每日排名;1:每周排名) + * @return Integer 当前排行榜最后一个批次值 + * @author admin + * @since 2024/6/7 11:53 + **/ + Integer selectSerialNumber(String weeklyRanking); + + /** + * 查询当前排行榜最大批次 + * + * @param weeklyRanking + * 日排名还是周排名(0:每日排名;1:每周排名) + * @return List + * @author admin + * @since 2024/6/7 11:55 + **/ + List selectMaxSerialNumber(String weeklyRanking); + + /** + * 根据时间查询店员排行 + * + * @param clerkId + * 店员ID + * @param startTime + * 开始时间 + * @param endTime + * 结束时间 + * @return 店员排行集合 + */ + PlayClerkRankingInfoEntity selectByTime(String clerkId, LocalDate startTime, LocalDate endTime); + + /** + * 店员分页查询本期排行信息 + * + * @param clerkId + * 店员ID + * @return 店员排行集合 + */ + PlayOrderRankingReturnVo selectCurrentRanking(String clerkId); + + /** + * 店员分页查询本期历史排行 + * + * @param clerkId + * 店员ID + * @return 店员排行集合 + */ + List selectHistoryRanking(String clerkId); + + /** + * 新增店员排行 + * + * @param playClerkRankingInfo + * 店员排行 + * @return 结果 + */ + boolean create(PlayClerkRankingInfoEntity playClerkRankingInfo); + + /** + * 修改店员排行 + * + * @param playClerkRankingInfo + * 店员排行 + * @return 结果 + */ + boolean update(PlayClerkRankingInfoEntity playClerkRankingInfo); + + /** + * 批量删除店员排行 + * + * @param ids + * 需要删除的店员排行主键集合 + * @return 结果 + */ + int deletePlayClerkRankingInfoByIds(String[] ids); + + /** + * 删除店员排行信息 + * + * @param id + * 店员排行主键 + * @return 结果 + */ + int deletePlayClerkRankingInfoById(String id); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/service/IPlayClerkTypeInfoService.java --- +package com.starry.admin.modules.clerk.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.clerk.module.entity.PlayClerkTypeInfoEntity; +import com.starry.admin.modules.clerk.module.vo.PlayClerkTypeInfoQueryVo; +import com.starry.admin.modules.clerk.module.vo.PlayClerkTypeInfoReturnVo; +import java.util.List; + +/** + * 店员分类信息Service接口 + * + * @author admin + * @since 2024-05-31 + */ +public interface IPlayClerkTypeInfoService extends IService { + /** + * 查询店员分类信息 + * + * @param id + * 店员分类信息主键 + * @return 店员分类信息 + */ + PlayClerkTypeInfoEntity selectPlayClerkTypeInfoById(String id); + + /** + * 查询店员分类信息列表 + * + * @return 店员分类信息集合 + */ + List selectByAll(); + + /** + * 查询店员分类信息列表 + * + * @param vo + * 店员分类信息 + * @return 店员分类信息集合 + */ + IPage selectByPage(PlayClerkTypeInfoQueryVo vo); + + /** + * 新增店员分类信息 + * + * @param playClerkTypeInfo + * 店员分类信息 + * @return 结果 + */ + boolean create(PlayClerkTypeInfoEntity playClerkTypeInfo); + + /** + * 修改店员分类信息 + * + * @param playClerkTypeInfo + * 店员分类信息 + * @return 结果 + */ + boolean update(PlayClerkTypeInfoEntity playClerkTypeInfo); + + /** + * 批量删除店员分类信息 + * + * @param ids + * 需要删除的店员分类信息主键集合 + * @return 结果 + */ + int deletePlayClerkTypeInfoByIds(String[] ids); + + /** + * 删除店员分类信息信息 + * + * @param id + * 店员分类信息主键 + * @return 结果 + */ + int deletePlayClerkTypeInfoById(String id); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/service/IPlayClerkTypeUserInfoService.java --- +package com.starry.admin.modules.clerk.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.clerk.module.entity.PlayClerkTypeUserInfoEntity; + +/** + * 店员和分类关系Service接口 + * + * @author admin + * @since 2024-05-31 + */ +public interface IPlayClerkTypeUserInfoService extends IService { + /** + * 查询店员和分类关系 + * + * @param id + * 店员和分类关系主键 + * @return 店员和分类关系 + */ + PlayClerkTypeUserInfoEntity selectPlayClerkTypeUserInfoById(String id); + + /** + * 查询店员和分类关系列表 + * + * @param playClerkTypeUserInfo + * 店员和分类关系 + * @return 店员和分类关系集合 + */ + IPage selectPlayClerkTypeUserInfoByPage( + PlayClerkTypeUserInfoEntity playClerkTypeUserInfo); + + /** + * 新增店员和分类关系 + * + * @param playClerkTypeUserInfo + * 店员和分类关系 + * @return 结果 + */ + boolean create(PlayClerkTypeUserInfoEntity playClerkTypeUserInfo); + + /** + * 修改店员和分类关系 + * + * @param playClerkTypeUserInfo + * 店员和分类关系 + * @return 结果 + */ + boolean update(PlayClerkTypeUserInfoEntity playClerkTypeUserInfo); + + /** + * 批量删除店员和分类关系 + * + * @param ids + * 需要删除的店员和分类关系主键集合 + * @return 结果 + */ + int deletePlayClerkTypeUserInfoByIds(String[] ids); + + /** + * 删除店员和分类关系信息 + * + * @param id + * 店员和分类关系主键 + * @return 结果 + */ + int deletePlayClerkTypeUserInfoById(String id); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/service/IPlayClerkUserInfoService.java --- +package com.starry.admin.modules.clerk.service; + +import com.alibaba.fastjson2.JSONObject; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.clerk.module.entity.PlayClerkLevelInfoEntity; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserQueryVo; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserReturnVo; +import com.starry.admin.modules.clerk.module.vo.PlayClerkUnsettledWagesInfoQueryVo; +import com.starry.admin.modules.clerk.module.vo.PlayClerkUnsettledWagesInfoReturnVo; +import com.starry.admin.modules.statistics.module.vo.PlayClerkPerformanceInfoQueryVo; +import com.starry.admin.modules.weichat.entity.PlayClerkUserLoginResponseVo; +import com.starry.admin.modules.weichat.entity.clerk.PlayClerkUserInfoQueryVo; +import com.starry.admin.modules.weichat.entity.clerk.PlayClerkUserInfoResultVo; +import java.math.BigDecimal; +import java.util.List; + +/** + * 店员Service接口 + * + * @author admin + * @since 2024-03-30 + */ +public interface IPlayClerkUserInfoService extends IService { + + /** + * 根据分组ID查询店员列表 + * + * @param typeId + * 分类ID + * @return 店员列表 + */ + List listAllByTypeId(String typeId); + + /** + * 根据分组ID查询店员列表 + * + * @param groupId + * 分组ID + * @return 店员列表 + */ + List listAllByGroupId(String groupId); + + /** + * 查询当前租户店员总数 + * + * @param tenantId + * 租户ID + * @return 店员总数 + */ + Long getTotalClerkUser(String tenantId); + + /** + * 获取当前店员抽成信息 + * + * @param clerkId + * 店员ID + * @return com.starry.admin.modules.clerk.module.entity.PlayClerkLevelInfoEntity + * @author admin + * @since 2024/6/3 11:29 + **/ + PlayClerkLevelInfoEntity queryLevelCommission(String clerkId); + + /** + * 查询店员 + * + * @param openId + * 微信ID + * @return 店员 + */ + PlayClerkUserInfoEntity selectByOpenid(String openId); + + /** + * 查询店员 + * + * @param id + * 店员主键 + * @return 店员 + */ + PlayClerkUserInfoEntity selectById(String id); + + /** + * 获得陪聊用户登录返回信息 + * + * @param vo + * PlayClerkUserInfoEntity + * @return PlayClerkUserLoginResponseVo + */ + PlayClerkUserLoginResponseVo getVo(PlayClerkUserInfoEntity vo); + + /** + * 更新token + * + * @param id + * 用户ID + * @param token + * token + * @author admin + * @since 2024/4/9 14:30 + **/ + void updateTokenById(String id, String token); + + /** + * 更新账号余额 + * + * @param id + * 用户ID + * @param accountBalance + * 账户余额 + * @author admin + * @since 2024/4/9 14:33 + **/ + void updateAccountBalanceById(String id, BigDecimal accountBalance); + + /** + * 更新店员账户余额信息 + * + * @param userId + * 用户ID + * @param balanceBeforeOperation + * 操作前余额 + * @param balanceAfterOperation + * 操作后余额 + * @param operationType + * 操作类型(0:充值;1:消费;2:服务) + * @param operationAction + * 操作动作 + * @param balanceMoney + * 操作金额 + * @param orderId + * 订单ID + */ + void updateAccountBalanceById(String userId, BigDecimal balanceBeforeOperation, BigDecimal balanceAfterOperation, + String operationType, String operationAction, BigDecimal balanceMoney, String orderId); + + /** + * 查询当前租户下所有店员 + * + * @return 店员列表 + */ + List listAll(); + + /** + * 查询店员未结算订单 + * + * @param vo + * 未结算订单查询对象 + * @return 未结算订单 + */ + IPage listUnsettledWagesByPage(PlayClerkUnsettledWagesInfoQueryVo vo); + + /** + * 管理端分页查询店员信息 + * + * @param vo + * 店员查询实体 + * @return 店员列表 + */ + + IPage selectByPage(PlayClerkPerformanceInfoQueryVo vo); + + /** + * 管理端分页查询店员信息 + * + * @param vo + * 店员查询实体 + * @return 店员列表 + */ + + IPage selectByPage(PlayClerkUserQueryVo vo); + + /** + * 查询店员列表 + * + * @param vo + * 店员查询对象 + * @param customUserId + * 顾客ID + * @return 店员列表 + */ + IPage selectByPage(PlayClerkUserInfoQueryVo vo, String customUserId); + + /** + * 查询店员列表 + * + * @param vo + * 店员查询对象 + * @return 店员集合 + */ + IPage selectPlayClerkUserInfoByPage(PlayClerkUserInfoQueryVo vo); + + /** + * 新增店员 + * + * @param playClerkUserInfo + * 店员 + * @return 结果 + */ + boolean create(PlayClerkUserInfoEntity playClerkUserInfo); + + /** + * 修改店员 + * + * @param playClerkUserInfo + * 店员 + * @return 结果 + */ + boolean update(PlayClerkUserInfoEntity playClerkUserInfo); + + /** + * 批量删除店员 + * + * @param ids + * 需要删除的店员主键集合 + * @return 结果 + */ + int deletePlayClerkUserInfoByIds(String[] ids); + + /** + * 删除店员信息 + * + * @param id + * 店员主键 + * @return 结果 + */ + int deletePlayClerkUserInfoById(String id); + + List simpleList(); + + JSONObject getPcData(PlayClerkUserInfoEntity entity); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/service/IPlayClerkUserReviewInfoService.java --- +package com.starry.admin.modules.clerk.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserReviewInfoEntity; +import com.starry.admin.modules.clerk.module.vo.PlayClerkUserReviewQueryVo; +import com.starry.admin.modules.clerk.module.vo.PlayClerkUserReviewReturnVo; +import com.starry.admin.modules.clerk.module.vo.PlayClerkUserReviewStateEditVo; + +/** + * 店员资料审核Service接口 + * + * @author admin + * @since 2024-05-19 + */ +public interface IPlayClerkUserReviewInfoService extends IService { + /** + * 查询店员资料审核 + * + * @param id + * 店员资料审核主键 + * @return 店员资料审核 + */ + PlayClerkUserReviewInfoEntity selectPlayClerkUserReviewInfoById(String id); + + /** + * 根据店员ID,查询未审核的申请 + * + * @param clerkId + * 店员ID + * @param reviewState + * 审核状态(0:未审核:1:审核通过,2:审核不通过) + * @return 店员申请审核对象 + */ + PlayClerkUserReviewInfoEntity queryByClerkId(String clerkId, String reviewState); + + /** + * 分页查询店员申请 + * + * @param vo + * 店员申请对象 + * @return 店员申请对象 + */ + IPage selectByPage(PlayClerkUserReviewQueryVo vo); + + /** + * 查询店员资料审核列表 + * + * @param playClerkUserReviewInfo + * 店员资料审核 + * @return 店员资料审核集合 + */ + IPage selectPlayClerkUserReviewInfoByPage( + PlayClerkUserReviewInfoEntity playClerkUserReviewInfo); + + /** + * 新增店员资料审核 + * + * @param playClerkUserReviewInfo + * 店员资料审核 + * @return 结果 + */ + boolean create(PlayClerkUserReviewInfoEntity playClerkUserReviewInfo); + + boolean update(PlayClerkUserReviewInfoEntity entity); + + /** + * 修改店员资料审核 + * + * @param vo + * 店员资料审核对象 + */ + void updateDataReviewState(PlayClerkUserReviewStateEditVo vo); + + /** + * 批量删除店员资料审核 + * + * @param ids + * 需要删除的店员资料审核主键集合 + * @return 结果 + */ + int deletePlayClerkUserReviewInfoByIds(String[] ids); + + /** + * 删除店员资料审核信息 + * + * @param id + * 店员资料审核主键 + * @return 结果 + */ + int deletePlayClerkUserReviewInfoById(String id); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/service/IPlayClerkWagesDetailsInfoService.java --- +package com.starry.admin.modules.clerk.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.clerk.module.entity.PlayClerkWagesDetailsInfoEntity; +import java.util.List; + +/** + * 店员工资明细信息Service接口 + * + * @author admin + * @since 2024-05-31 + */ +public interface IPlayClerkWagesDetailsInfoService extends IService { + + /** + * 查询店员工资明细信息 + * + * @param wagesId + * 店员工资统计ID + * @return 店员工资明细信息 + */ + List selectByWagesId(String wagesId); + + /** + * 根据订单ID + * + * @param orderId + * 订单ID + * @return 工资详情 + */ + PlayClerkWagesDetailsInfoEntity selectByOrderId(String orderId); + + /** + * 根据工资结算ID和店员ID查询工资详情 + * + * @param wagesId + * 结算ID + * @param clerkId + * 店员ID + * @return 工资详情 + */ + PlayClerkWagesDetailsInfoEntity selectByClerkIdAndWagesId(String wagesId, String clerkId); + /** + * 查询店员工资明细信息 + * + * @param id + * 店员工资明细信息主键 + * @return 店员工资明细信息 + */ + PlayClerkWagesDetailsInfoEntity selectPlayClerkWagesDetailsInfoById(String id); + + /** + * 查询店员工资明细信息列表 + * + * @param playClerkWagesDetailsInfo + * 店员工资明细信息 + * @return 店员工资明细信息集合 + */ + IPage selectPlayClerkWagesDetailsInfoByPage( + PlayClerkWagesDetailsInfoEntity playClerkWagesDetailsInfo); + + /** + * 新增店员工资明细信息 + * + * @param playClerkWagesDetailsInfo + * 店员工资明细信息 + * @return 结果 + */ + boolean create(PlayClerkWagesDetailsInfoEntity playClerkWagesDetailsInfo); + + /** + * 修改店员工资明细信息 + * + * @param playClerkWagesDetailsInfo + * 店员工资明细信息 + * @return 结果 + */ + boolean update(PlayClerkWagesDetailsInfoEntity playClerkWagesDetailsInfo); + + /** + * 批量删除店员工资明细信息 + * + * @param ids + * 需要删除的店员工资明细信息主键集合 + * @return 结果 + */ + int deletePlayClerkWagesDetailsInfoByIds(String[] ids); + + /** + * 删除店员工资明细信息信息 + * + * @param id + * 店员工资明细信息主键 + * @return 结果 + */ + int deletePlayClerkWagesDetailsInfoById(String id); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/service/IPlayClerkWagesInfoService.java --- +package com.starry.admin.modules.clerk.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.clerk.module.entity.PlayClerkWagesInfoEntity; +import com.starry.admin.modules.clerk.module.vo.PlayClerkWagesInfoQueryVo; +import com.starry.admin.modules.clerk.module.vo.PlayClerkWagesInfoReturnVo; +import java.time.LocalDate; +import java.util.List; + +/** + * 店员工资结算信息Service接口 + * + * @author admin + * @since 2024-05-31 + */ +public interface IPlayClerkWagesInfoService extends IService { + + /** + * 根据店员ID查询店员工资结算信息 + * + * @param clerkId + * 店员ID + * @return 店员工资结算信息 + */ + PlayClerkWagesInfoEntity selectCurrentPeriodWagesByClerkId(String clerkId); + + /** + * 根据店员ID查询店员往期工资 + * + * @param clerkId + * 店员ID + * @return 店员工资结算信息 + */ + List selectHistoricalWagesByClerkId(String clerkId); + + /** + * 获取最后一次统计 + * + * @param clerkId + * 店员ID + * @return 上次结算时间 + */ + PlayClerkWagesInfoEntity getLastSettlement(String clerkId); + + /** + * 获取最后一次统计 + * + * @param clerkId + * 店员ID + * @return 上次结算时间 + */ + LocalDate getLastSettlementTime(String clerkId); + + /** + * 查询店员工资结算信息 + * + * @param id + * 店员工资结算信息主键 + * @return 店员工资结算信息 + */ + PlayClerkWagesInfoEntity selectPlayClerkWagesInfoById(String id); + + /** + * 分页查询工资统计信息 + * + * @param vo + * 统计统计查询对象 + * @return 查询工资统计信息 + */ + IPage selectHistoricalByPage(PlayClerkWagesInfoQueryVo vo); + + /** + * 查询店员工资结算信息列表 + * + * @param playClerkWagesInfo + * 店员工资结算信息 + * @return 店员工资结算信息集合 + */ + IPage selectPlayClerkWagesInfoByPage(PlayClerkWagesInfoEntity playClerkWagesInfo); + + /** + * 新增店员工资结算信息 + * + * @param playClerkWagesInfo + * 店员工资结算信息 + * @return 结果 + */ + boolean create(PlayClerkWagesInfoEntity playClerkWagesInfo); + + /** + * 修改店员工资结算信息 + * + * @param playClerkWagesInfo + * 店员工资结算信息 + * @return 结果 + */ + boolean update(PlayClerkWagesInfoEntity playClerkWagesInfo); + + /** + * 批量删除店员工资结算信息 + * + * @param ids + * 需要删除的店员工资结算信息主键集合 + * @return 结果 + */ + int deletePlayClerkWagesInfoByIds(String[] ids); + + /** + * 删除店员工资结算信息信息 + * + * @param id + * 店员工资结算信息主键 + * @return 结果 + */ + int deletePlayClerkWagesInfoById(String id); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/service/IPlayCustomArticleInfoService.java --- +package com.starry.admin.modules.clerk.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.clerk.module.entity.PlayCustomArticleInfoEntity; + +/** + * 陪聊点赞动态信息Service接口 + * + * @author admin + * @since 2024-05-04 + */ +public interface IPlayCustomArticleInfoService extends IService { + + /** + * 查询顾客操作动态数据 + * + * @param articleId + * 动态ID + * @param customId + * 客户ID + * @param endorseType + * 操作类型(1:点赞;0:收藏) + * @return PlayCustomArticleInfoEntity + */ + PlayCustomArticleInfoEntity selectByArticleId(String articleId, String customId, String endorseType); + + /** + * 查询陪聊点赞动态信息 + * + * @param id + * 陪聊点赞动态信息主键 + * @return 陪聊点赞动态信息 + */ + PlayCustomArticleInfoEntity selectPlayCustomArticleInfoById(String id); + + /** + * 查询陪聊点赞动态信息列表 + * + * @param playCustomArticleInfo + * 陪聊点赞动态信息 + * @return 陪聊点赞动态信息集合 + */ + IPage selectPlayCustomArticleInfoByPage( + PlayCustomArticleInfoEntity playCustomArticleInfo); + + /** + * 新增陪聊点赞动态信息 + * + * @param playCustomArticleInfo + * 陪聊点赞动态信息 + * @return 结果 + */ + boolean create(PlayCustomArticleInfoEntity playCustomArticleInfo); + + /** + * 修改陪聊点赞动态信息 + * + * @param playCustomArticleInfo + * 陪聊点赞动态信息 + * @return 结果 + */ + boolean update(PlayCustomArticleInfoEntity playCustomArticleInfo); + + /** + * 批量删除陪聊点赞动态信息 + * + * @param ids + * 需要删除的陪聊点赞动态信息主键集合 + * @return 结果 + */ + int deletePlayCustomArticleInfoByIds(String[] ids); + + /** + * 删除陪聊点赞动态信息信息 + * + * @param id + * 陪聊点赞动态信息主键 + * @return 结果 + */ + int deletePlayCustomArticleInfoById(String id); + + /** + * 根据动态ID删除点赞信息 + * + * @param articleId + * 动态ID + */ + void deleteByArticleId(String articleId); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/service/impl/PlayAvatarFrameInfoServiceImpl.java --- +package com.starry.admin.modules.clerk.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.starry.admin.modules.clerk.mapper.PlayAvatarFrameInfoMapper; +import com.starry.admin.modules.clerk.module.entity.PlayAvatarFrameInfoEntity; +import com.starry.admin.modules.clerk.module.vo.PlayAvatarFrameInfoQueryVo; +import com.starry.admin.modules.clerk.service.IPlayAvatarFrameInfoService; +import com.starry.common.utils.IdUtils; +import java.util.Arrays; +import java.util.List; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 店员头像框Service业务层处理 + * + * @author admin + * @since 2024-06-06 + */ +@Service +public class PlayAvatarFrameInfoServiceImpl extends ServiceImpl + implements + IPlayAvatarFrameInfoService { + @Resource + private PlayAvatarFrameInfoMapper playAvatarFrameInfoMapper; + + /** + * 查询店员头像框 + * + * @param id + * 店员头像框主键 + * @return 店员头像框 + */ + @Override + public PlayAvatarFrameInfoEntity selectPlayAvatarFrameInfoById(String id) { + return this.baseMapper.selectById(id); + } + + @Override + public List selectAll() { + return this.baseMapper.selectList(new LambdaQueryWrapper<>()); + } + + @Override + public IPage selectByPage(PlayAvatarFrameInfoQueryVo vo) { + return this.baseMapper.selectPage(new Page<>(vo.getPageNum(), vo.getPageSize()), new LambdaQueryWrapper<>()); + } + + /** + * 查询店员头像框列表 + * + * @param playAvatarFrameInfo + * 店员头像框 + * @return 店员头像框 + */ + @Override + public IPage selectPlayAvatarFrameInfoByPage( + PlayAvatarFrameInfoEntity playAvatarFrameInfo) { + Page page = new Page<>(1, 10); + return this.baseMapper.selectPage(page, new LambdaQueryWrapper<>()); + } + + /** + * 新增店员头像框 + * + * @param playAvatarFrameInfo + * 店员头像框 + * @return 结果 + */ + @Override + public boolean create(PlayAvatarFrameInfoEntity playAvatarFrameInfo) { + if (StrUtil.isBlankIfStr(playAvatarFrameInfo.getId())) { + playAvatarFrameInfo.setId(IdUtils.getUuid()); + } + return save(playAvatarFrameInfo); + } + + /** + * 修改店员头像框 + * + * @param playAvatarFrameInfo + * 店员头像框 + * @return 结果 + */ + @Override + public boolean update(PlayAvatarFrameInfoEntity playAvatarFrameInfo) { + return updateById(playAvatarFrameInfo); + } + + /** + * 批量删除店员头像框 + * + * @param ids + * 需要删除的店员头像框主键 + * @return 结果 + */ + @Override + public int deletePlayAvatarFrameInfoByIds(String[] ids) { + return playAvatarFrameInfoMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除店员头像框信息 + * + * @param id + * 店员头像框主键 + * @return 结果 + */ + @Override + public int deletePlayAvatarFrameInfoById(String id) { + return playAvatarFrameInfoMapper.deleteById(id); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/service/impl/PlayClerkArticleInfoServiceImpl.java --- +package com.starry.admin.modules.clerk.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.github.yulichang.wrapper.MPJLambdaWrapper; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.clerk.mapper.PlayClerkArticleInfoMapper; +import com.starry.admin.modules.clerk.module.entity.PlayClerkArticleInfoEntity; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity; +import com.starry.admin.modules.clerk.module.entity.PlayCustomArticleInfoEntity; +import com.starry.admin.modules.clerk.module.vo.PlayClerkArticleQueryVo; +import com.starry.admin.modules.clerk.module.vo.PlayClerkArticleReturnVo; +import com.starry.admin.modules.clerk.service.IPlayClerkArticleInfoService; +import com.starry.admin.modules.personnel.service.IPlayPersonnelGroupInfoService; +import com.starry.admin.modules.weichat.entity.article.PlayClerkArticleCustomQueryVo; +import com.starry.admin.modules.weichat.entity.article.PlayClerkArticleCustomReturnVo; +import com.starry.admin.utils.SecurityUtils; +import com.starry.common.utils.IdUtils; +import java.util.Arrays; +import java.util.List; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 店员动态信息Service业务层处理 + * + * @author admin + * @since 2024-05-04 + */ +@Service +public class PlayClerkArticleInfoServiceImpl extends ServiceImpl + implements + IPlayClerkArticleInfoService { + @Resource + private PlayClerkArticleInfoMapper playClerkArticleInfoMapper; + + @Resource + private IPlayPersonnelGroupInfoService playClerkGroupInfoService; + + /** + * 查询店员动态信息 + * + * @param id + * 店员动态信息主键 + * @return 店员动态信息 + */ + @Override + public PlayClerkArticleInfoEntity selectPlayClerkArticleInfoById(String id) { + PlayClerkArticleInfoEntity entity = this.baseMapper.selectById(id); + if (entity == null) { + throw new CustomException("动态不存在"); + } + return this.baseMapper.selectById(id); + } + + /** + * 查询店员动态信息列表 + * + * @param vo + * 店员动态信息查询对象 + * @return 店员动态信息 + */ + @Override + public IPage selectByPage(PlayClerkArticleQueryVo vo, boolean searchByYourself) { + MPJLambdaWrapper lambdaQueryWrapper = new MPJLambdaWrapper<>(); + // 查询主表全部字段 + lambdaQueryWrapper.selectAll(PlayClerkArticleInfoEntity.class); + // 陪聊用户表全部字段 + lambdaQueryWrapper.selectAs(PlayClerkUserInfoEntity::getId, "clerkId") + .selectAs(PlayClerkUserInfoEntity::getNickname, "clerkNickname") + .selectAs(PlayClerkUserInfoEntity::getAvatar, "clerkAvatar"); + // 陪聊动态表 + lambdaQueryWrapper.leftJoin(PlayClerkUserInfoEntity.class, PlayClerkUserInfoEntity::getId, + PlayClerkArticleInfoEntity::getClerkId); + // 动态点赞表 + lambdaQueryWrapper + .selectCollection(PlayCustomArticleInfoEntity.class, PlayClerkArticleReturnVo::getArticleInfoEntities) + .leftJoin(PlayCustomArticleInfoEntity.class, PlayCustomArticleInfoEntity::getArticleId, + PlayCustomArticleInfoEntity::getId); + + if (StrUtil.isNotBlank(vo.getClerkId())) { + lambdaQueryWrapper.eq(PlayClerkArticleInfoEntity::getClerkId, vo.getClerkId()); + } + if (StrUtil.isNotBlank(vo.getReviewState())) { + lambdaQueryWrapper.eq(PlayClerkArticleInfoEntity::getReviewState, vo.getReviewState()); + } + if (vo.getReleaseTime() != null && vo.getReleaseTime().size() == 2) { + lambdaQueryWrapper.between(PlayClerkArticleInfoEntity::getReleaseTime, vo.getReleaseTime().get(0), + vo.getReleaseTime().get(1)); + } + if (!searchByYourself) { + // 后台查询时,加入组员的筛选 + List clerkIdList = playClerkGroupInfoService.getValidClerkIdList(SecurityUtils.getLoginUser(), + null); + lambdaQueryWrapper.in(PlayClerkArticleInfoEntity::getClerkId, clerkIdList); + } + IPage page = this.baseMapper.selectJoinPage( + new Page<>(vo.getPageNum(), vo.getPageSize()), PlayClerkArticleReturnVo.class, lambdaQueryWrapper); + for (PlayClerkArticleReturnVo record : page.getRecords()) { + int index = 0; + for (PlayCustomArticleInfoEntity articleInfoEntity : record.getArticleInfoEntities()) { + if (articleInfoEntity.getId() == null) { + continue; + } + index++; + } + record.setAgreedQuantity(index); + } + return this.baseMapper.selectJoinPage(new Page<>(vo.getPageNum(), vo.getPageSize()), + PlayClerkArticleReturnVo.class, lambdaQueryWrapper); + } + + @Override + public IPage customSelectByPage(PlayClerkArticleCustomQueryVo vo, String customId) { + MPJLambdaWrapper lambdaQueryWrapper = new MPJLambdaWrapper<>(); + // 查询主表全部字段 + lambdaQueryWrapper.selectAll(PlayClerkArticleInfoEntity.class); + // 陪聊用户表全部字段 + lambdaQueryWrapper.selectAs(PlayClerkUserInfoEntity::getId, "clerkId") + .selectAs(PlayClerkUserInfoEntity::getNickname, "clerkNickname") + .selectAs(PlayClerkUserInfoEntity::getAvatar, "clerkAvatar") + .selectAs(PlayClerkUserInfoEntity::getSex, "clerkSex"); + // 陪聊用户表全部字段 + lambdaQueryWrapper.selectAs(PlayCustomArticleInfoEntity::getId, "id"); + // 陪聊动态表 + lambdaQueryWrapper.leftJoin(PlayClerkUserInfoEntity.class, PlayClerkUserInfoEntity::getId, + PlayClerkArticleInfoEntity::getClerkId); + if (StrUtil.isNotBlank(vo.getFollowState()) && "1".equals(vo.getFollowState())) { + // 查询本人收藏的动态列表 + lambdaQueryWrapper.innerJoin(PlayCustomArticleInfoEntity.class, PlayCustomArticleInfoEntity::getArticleId, + PlayClerkArticleInfoEntity::getId); + lambdaQueryWrapper.eq(PlayCustomArticleInfoEntity::getCustomId, customId); + lambdaQueryWrapper.eq(PlayCustomArticleInfoEntity::getEndorseType, "0"); + lambdaQueryWrapper.eq(PlayCustomArticleInfoEntity::getEndorseState, "1"); + } + // 查询指定店员动态 + if (StrUtil.isNotBlank(vo.getClerkId())) { + lambdaQueryWrapper.eq(PlayClerkArticleInfoEntity::getClerkId, vo.getClerkId()); + } + // 动态点赞表 + lambdaQueryWrapper + .selectCollection(PlayCustomArticleInfoEntity.class, PlayClerkArticleReturnVo::getArticleInfoEntities) + .leftJoin(PlayCustomArticleInfoEntity.class, PlayCustomArticleInfoEntity::getArticleId, + PlayCustomArticleInfoEntity::getId); + lambdaQueryWrapper.eq(PlayClerkArticleInfoEntity::getReviewState, "1"); + + IPage page = this.baseMapper.selectJoinPage( + new Page<>(vo.getPageNum(), vo.getPageSize()), PlayClerkArticleCustomReturnVo.class, + lambdaQueryWrapper); + for (PlayClerkArticleCustomReturnVo record : page.getRecords()) { + int index = 0; + for (PlayCustomArticleInfoEntity articleInfoEntity : record.getArticleInfoEntities()) { + // 动态操作信息为空 + if (articleInfoEntity.getId() == null) { + continue; + } + // 点赞或者动态处于激活状态 + if ("1".equals(articleInfoEntity.getEndorseState())) { + if ("1".equals(articleInfoEntity.getEndorseType())) { + index++; + record.setGreedState("1"); + } else { + record.setFollowState("1"); + } + } + } + record.setAgreedQuantity(index); + } + return page; + } + /** + * 新增店员动态信息 + * + * @param entity + * 店员动态信息 + * @return 结果 + */ + @Override + public boolean create(PlayClerkArticleInfoEntity entity) { + if (!queryClerkUnauditedArticleInfo(entity.getClerkId()).isEmpty()) { + throw new CustomException("存在未审核动态,无法新增"); + } + + if (StrUtil.isBlankIfStr(entity.getId())) { + entity.setId(IdUtils.getUuid()); + } + return save(entity); + } + + /** + * 查询店员未审核的动态 + * + * @param clerkId + * 店员ID + * @return 店员未审核的动态列表 + */ + public List queryClerkUnauditedArticleInfo(String clerkId) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayClerkArticleInfoEntity::getClerkId, clerkId); + lambdaQueryWrapper.eq(PlayClerkArticleInfoEntity::getReviewState, "0"); + return this.baseMapper.selectList(lambdaQueryWrapper); + } + + /** + * 修改店员动态信息 + * + * @param playClerkArticleInfo + * 店员动态信息 + * @return 结果 + */ + @Override + public boolean update(PlayClerkArticleInfoEntity playClerkArticleInfo) { + return updateById(playClerkArticleInfo); + } + + /** + * 批量删除店员动态信息 + * + * @param ids + * 需要删除的店员动态信息主键 + * @return 结果 + */ + @Override + public int deletePlayClerkArticleInfoByIds(String[] ids) { + return playClerkArticleInfoMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除店员动态信息信息 + * + * @param id + * 店员动态信息主键 + * @return 结果 + */ + @Override + public int deletePlayClerkArticleInfoById(String id) { + return playClerkArticleInfoMapper.deleteById(id); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/service/impl/PlayClerkClassificationInfoServiceImpl.java --- +package com.starry.admin.modules.clerk.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.starry.admin.modules.clerk.mapper.PlayClerkClassificationInfoMapper; +import com.starry.admin.modules.clerk.module.entity.PlayClerkClassificationInfoEntity; +import com.starry.admin.modules.clerk.service.IPlayClerkClassificationInfoService; +import com.starry.common.utils.IdUtils; +import java.util.Arrays; +import java.util.List; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 店员分类Service业务层处理 + * + * @author admin + * @since 2024-04-06 + */ +@Service +public class PlayClerkClassificationInfoServiceImpl + extends + ServiceImpl + implements + IPlayClerkClassificationInfoService { + @Resource + private PlayClerkClassificationInfoMapper playClerkClassificationInfoMapper; + + /** + * 查询店员分类 + * + * @param id + * 店员分类主键 + * @return 店员分类 + */ + @Override + public PlayClerkClassificationInfoEntity selectPlayClerkClassificationInfoById(String id) { + return this.baseMapper.selectById(id); + } + + /** + * 查询店员分类列表 + * + * @return 店员分类 + */ + @Override + public List selectAll() { + return this.baseMapper.selectList(new LambdaQueryWrapper<>()); + } + + /** + * 查询店员分类列表 + * + * @param playClerkClassificationInfo + * 店员分类 + * @return 店员分类 + */ + @Override + public IPage selectPlayClerkClassificationInfoByPage( + PlayClerkClassificationInfoEntity playClerkClassificationInfo) { + Page page = new Page<>(1, 10); + return this.baseMapper.selectPage(page, new LambdaQueryWrapper<>()); + } + + /** + * 新增店员分类 + * + * @param playClerkClassificationInfo + * 店员分类 + * @return 结果 + */ + @Override + public boolean create(PlayClerkClassificationInfoEntity playClerkClassificationInfo) { + if (StrUtil.isBlankIfStr(playClerkClassificationInfo.getId())) { + playClerkClassificationInfo.setId(IdUtils.getUuid()); + } + return save(playClerkClassificationInfo); + } + + /** + * 修改店员分类 + * + * @param playClerkClassificationInfo + * 店员分类 + * @return 结果 + */ + @Override + public boolean update(PlayClerkClassificationInfoEntity playClerkClassificationInfo) { + return updateById(playClerkClassificationInfo); + } + + /** + * 批量删除店员分类 + * + * @param ids + * 需要删除的店员分类主键 + * @return 结果 + */ + @Override + public int deletePlayClerkClassificationInfoByIds(String[] ids) { + return playClerkClassificationInfoMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除店员分类信息 + * + * @param id + * 店员分类主键 + * @return 结果 + */ + @Override + public int deletePlayClerkClassificationInfoById(String id) { + return playClerkClassificationInfoMapper.deleteById(id); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/service/impl/PlayClerkCommodityServiceImpl.java --- +package com.starry.admin.modules.clerk.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.clerk.mapper.PlayClerkCommodityMapper; +import com.starry.admin.modules.clerk.module.entity.PlayClerkCommodityEntity; +import com.starry.admin.modules.clerk.service.IPlayClerkCommodityService; +import com.starry.admin.modules.shop.module.entity.PlayCommodityInfoEntity; +import com.starry.admin.modules.shop.service.IPlayCommodityInfoService; +import com.starry.common.utils.IdUtils; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 陪聊服务项目Service业务层处理 + * + * @author admin + * @since 2024-03-31 + */ +@Service +public class PlayClerkCommodityServiceImpl extends ServiceImpl + implements + IPlayClerkCommodityService { + @Resource + private PlayClerkCommodityMapper playClerkCommodityMapper; + + @Resource + private IPlayCommodityInfoService playCommodityInfoService; + + @Override + public void initClerkCommodity(String userId) { + // 查询当前陪聊的所有服务项目 + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayClerkCommodityEntity::getClerkId, userId); + this.baseMapper.delete(lambdaQueryWrapper); + // 根据当前租户的服务项目,生成陪聊项目数据 + for (PlayCommodityInfoEntity commodityInfo : playCommodityInfoService.selectByType()) { + PlayClerkCommodityEntity entity = new PlayClerkCommodityEntity(); + entity.setClerkId(userId); + entity.setCommodityId(commodityInfo.getId()); + entity.setCommodityName(commodityInfo.getItemName()); + entity.setEnablingState("1"); + entity.setSort(commodityInfo.getSort()); + this.create(entity); + } + + } + + @Override + public List getClerkCommodityList(String userId, String enablingState) { + List list = this.selectCommodityTypeByUser(userId, enablingState); + return list.stream().map(PlayClerkCommodityEntity::getCommodityName).collect(Collectors.toList()); + } + + @Override + public List selectCommodityTypeByUser(String userId, String enablingState) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.orderByDesc(PlayClerkCommodityEntity::getSort); + lambdaQueryWrapper.eq(PlayClerkCommodityEntity::getClerkId, userId); + if (StrUtil.isNotBlank(enablingState)) { + lambdaQueryWrapper.eq(PlayClerkCommodityEntity::getEnablingState, enablingState); + } + return this.baseMapper.selectList(lambdaQueryWrapper); + } + + @Override + public List selectByUser(String userId) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayClerkCommodityEntity::getClerkId, userId); + return this.baseMapper.selectList(lambdaQueryWrapper); + } + + @Override + public List selectAll() { + return this.baseMapper.selectList(new LambdaQueryWrapper<>()); + } + + @Override + public void startStopClerkItem(String commodityName, String enablingState, String clerkId) { + PlayClerkCommodityEntity entity = new PlayClerkCommodityEntity(); + entity.setEnablingState(enablingState); + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayClerkCommodityEntity::getClerkId, clerkId); + lambdaQueryWrapper.eq(PlayClerkCommodityEntity::getCommodityName, commodityName); + this.baseMapper.update(entity, lambdaQueryWrapper); + } + + /** + * 查询陪聊服务项目 + * + * @param id + * 陪聊服务项目主键 + * @return 陪聊服务项目 + */ + @Override + public PlayClerkCommodityEntity selectPlayClerkCommodityById(String id) { + PlayClerkCommodityEntity entity = this.baseMapper.selectById(id); + if (entity == null) { + throw new CustomException("服务项目不存在"); + } + return entity; + } + + /** + * 查询陪聊服务项目列表 + * + * @param playClerkCommodity + * 陪聊服务项目 + * @return 陪聊服务项目 + */ + @Override + public IPage selectPlayClerkCommodityByPage(PlayClerkCommodityEntity playClerkCommodity) { + Page page = new Page<>(1, 10); + return this.baseMapper.selectPage(page, new LambdaQueryWrapper<>()); + } + + /** + * 新增陪聊服务项目 + * + * @param playClerkCommodity + * 陪聊服务项目 + * @return 结果 + */ + @Override + public boolean create(PlayClerkCommodityEntity playClerkCommodity) { + if (StrUtil.isBlankIfStr(playClerkCommodity.getId())) { + playClerkCommodity.setId(IdUtils.getUuid()); + } + return save(playClerkCommodity); + } + + /** + * 修改陪聊服务项目 + * + * @param playClerkCommodity + * 陪聊服务项目 + * @return 结果 + */ + @Override + public boolean update(PlayClerkCommodityEntity playClerkCommodity) { + return updateById(playClerkCommodity); + } + + /** + * 批量删除陪聊服务项目 + * + * @param ids + * 需要删除的陪聊服务项目主键 + * @return 结果 + */ + @Override + public int deletePlayClerkCommodityByIds(String[] ids) { + return playClerkCommodityMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除陪聊服务项目信息 + * + * @param id + * 陪聊服务项目主键 + * @return 结果 + */ + @Override + public int deletePlayClerkCommodityById(String id) { + return playClerkCommodityMapper.deleteById(id); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/service/impl/PlayClerkDataReviewInfoServiceImpl.java --- +package com.starry.admin.modules.clerk.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.github.yulichang.wrapper.MPJLambdaWrapper; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.clerk.mapper.PlayClerkDataReviewInfoMapper; +import com.starry.admin.modules.clerk.module.entity.PlayClerkDataReviewInfoEntity; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserReviewInfoEntity; +import com.starry.admin.modules.clerk.module.vo.PlayClerkDataReviewQueryVo; +import com.starry.admin.modules.clerk.module.vo.PlayClerkDataReviewReturnVo; +import com.starry.admin.modules.clerk.module.vo.PlayClerkDataReviewStateEditVo; +import com.starry.admin.modules.clerk.service.IPlayClerkDataReviewInfoService; +import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService; +import com.starry.common.utils.IdUtils; +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.List; +import javax.annotation.Resource; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +/** + * 店员资料审核Service业务层处理 + * + * @author admin + * @since 2024-05-19 + */ +@Service +public class PlayClerkDataReviewInfoServiceImpl + extends + ServiceImpl + implements + IPlayClerkDataReviewInfoService { + @Resource + private PlayClerkDataReviewInfoMapper playClerkDataReviewInfoMapper; + + @Resource + private IPlayClerkUserInfoService playClerkUserInfoService; + + /** + * 查询店员资料审核 + * + * @param id + * 店员资料审核主键 + * @return 店员资料审核 + */ + @Override + public PlayClerkDataReviewInfoEntity selectPlayClerkDataReviewInfoById(String id) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(PlayClerkDataReviewInfoEntity::getId, id); + PlayClerkDataReviewInfoEntity entity = this.baseMapper.selectOne(queryWrapper); + if (entity == null) { + throw new CustomException("对象不存在"); + } + return entity; + } + + @Override + public List queryByClerkId(String clerkId, String reviewState) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(PlayClerkDataReviewInfoEntity::getClerkId, clerkId); + queryWrapper.eq(PlayClerkDataReviewInfoEntity::getReviewState, reviewState); + return this.baseMapper.selectList(queryWrapper); + } + + @Override + public PlayClerkDataReviewInfoEntity queryByClerkId(String clerkId, String dataType, String reviewState) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(PlayClerkDataReviewInfoEntity::getClerkId, clerkId); + queryWrapper.eq(PlayClerkDataReviewInfoEntity::getReviewState, reviewState); + queryWrapper.eq(PlayClerkDataReviewInfoEntity::getDataType, dataType); + return this.baseMapper.selectOne(queryWrapper); + } + + /** + * 查询店员资料审核列表 + * + * @param vo + * 店员资料审核 + * @return 店员资料审核 + */ + @Override + public IPage selectByPage(PlayClerkDataReviewQueryVo vo) { + MPJLambdaWrapper lambdaQueryWrapper = new MPJLambdaWrapper<>(); + lambdaQueryWrapper.orderByDesc(PlayClerkDataReviewInfoEntity::getAddTime); + lambdaQueryWrapper.selectAll(PlayClerkDataReviewInfoEntity.class); + // 店员表 + lambdaQueryWrapper.selectAs(PlayClerkUserInfoEntity::getAvatar, "clerkAvatar") + .selectAs(PlayClerkUserInfoEntity::getNickname, "clerkNickname"); + lambdaQueryWrapper.leftJoin(PlayClerkUserInfoEntity.class, PlayClerkUserInfoEntity::getId, + PlayClerkUserReviewInfoEntity::getClerkId); + if (StrUtil.isNotBlank(vo.getClerkId())) { + lambdaQueryWrapper.eq(PlayClerkDataReviewInfoEntity::getClerkId, vo.getClerkId()); + } + if (StrUtil.isNotBlank(vo.getDataType())) { + lambdaQueryWrapper.eq(PlayClerkDataReviewInfoEntity::getDataType, vo.getDataType()); + } + if (StrUtil.isNotBlank(vo.getReviewState())) { + lambdaQueryWrapper.like(PlayClerkDataReviewInfoEntity::getReviewState, vo.getReviewState()); + } + if (vo.getAddTime() != null && vo.getAddTime().size() == 2) { + lambdaQueryWrapper.between(PlayClerkDataReviewInfoEntity::getAddTime, vo.getAddTime().get(0), + vo.getAddTime().get(1)); + } + return this.baseMapper.selectJoinPage(new Page<>(vo.getPageNum(), vo.getPageSize()), + PlayClerkDataReviewReturnVo.class, lambdaQueryWrapper); + } + + /** + * 新增店员资料审核 + * + * @param playClerkDataReviewInfo + * 店员资料审核 + * @return 结果 + */ + @Override + public boolean create(PlayClerkDataReviewInfoEntity playClerkDataReviewInfo) { + if (StrUtil.isBlankIfStr(playClerkDataReviewInfo.getId())) { + playClerkDataReviewInfo.setId(IdUtils.getUuid()); + } + if (StrUtil.isBlankIfStr(playClerkDataReviewInfo.getAddTime())) { + playClerkDataReviewInfo.setAddTime(LocalDateTime.now()); + } + return save(playClerkDataReviewInfo); + } + + @Override + public void updateDataReviewState(PlayClerkDataReviewStateEditVo vo) { + PlayClerkDataReviewInfoEntity entity = this.selectPlayClerkDataReviewInfoById(vo.getId()); + BeanUtils.copyProperties(vo, entity); + this.update(entity); + if ("1".equals(vo.getReviewState())) { + PlayClerkUserInfoEntity userInfo = new PlayClerkUserInfoEntity(); + userInfo.setId(entity.getClerkId()); + if ("1".equals(entity.getDataType())) { + userInfo.setAvatar(entity.getDataContent().get(0)); + } + if ("2".equals(entity.getDataType())) { + userInfo.setAlbum(entity.getDataContent()); + } + if ("3".equals(entity.getDataType())) { + userInfo.setAudio(entity.getDataContent().get(0)); + } + playClerkUserInfoService.update(userInfo); + } + } + + /** + * 修改店员资料审核 + * + * @param playClerkDataReviewInfo + * 店员资料审核 + * @return 结果 + */ + @Override + public boolean update(PlayClerkDataReviewInfoEntity playClerkDataReviewInfo) { + return updateById(playClerkDataReviewInfo); + } + + /** + * 批量删除店员资料审核 + * + * @param ids + * 需要删除的店员资料审核主键 + * @return 结果 + */ + @Override + public int deletePlayClerkDataReviewInfoByIds(String[] ids) { + return playClerkDataReviewInfoMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除店员资料审核信息 + * + * @param id + * 店员资料审核主键 + * @return 结果 + */ + @Override + public int deletePlayClerkDataReviewInfoById(String id) { + return playClerkDataReviewInfoMapper.deleteById(id); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/service/impl/PlayClerkLevelInfoServiceImpl.java --- +package com.starry.admin.modules.clerk.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.starry.admin.modules.clerk.mapper.PlayClerkLevelInfoMapper; +import com.starry.admin.modules.clerk.module.entity.PlayClerkLevelInfoEntity; +import com.starry.admin.modules.clerk.service.IPlayClerkLevelInfoService; +import com.starry.admin.modules.system.module.entity.SysTenantEntity; +import com.starry.common.utils.IdUtils; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 店员等级Service业务层处理 + * + * @author admin + * @since 2024-03-30 + */ +@Service +public class PlayClerkLevelInfoServiceImpl extends ServiceImpl + implements + IPlayClerkLevelInfoService { + @Resource + private PlayClerkLevelInfoMapper playClerkLevelInfoMapper; + + @Override + public void initDefaultLevel(SysTenantEntity sysTenantEntity) { + List list = this.selectAll(); + if (list == null || list.isEmpty()) { + PlayClerkLevelInfoEntity entity = new PlayClerkLevelInfoEntity(); + entity.setName("普通"); + entity.setFirstRandomRadio(45); + entity.setNotFirstRandomRadio(50); + entity.setFirstRewardRatio(45); + entity.setNotFirstRewardRatio(50); + entity.setFirstRegularRatio(45); + entity.setNotFirstRegularRatio(50); + entity.setLevel(1); + entity.setStyleType(entity.getLevel()); + entity.setTenantId(sysTenantEntity.getTenantId()); + this.baseMapper.insert(entity); + } + } + + @Override + public PlayClerkLevelInfoEntity getDefaultLevel() { + List list = this.selectAll(); + if (list != null && !list.isEmpty()) { + return list.get(0); + } else { + PlayClerkLevelInfoEntity entity = new PlayClerkLevelInfoEntity(); + entity.setName("普通"); + entity.setFirstRandomRadio(45); + entity.setNotFirstRandomRadio(50); + entity.setFirstRewardRatio(45); + entity.setNotFirstRewardRatio(50); + entity.setFirstRegularRatio(45); + entity.setNotFirstRegularRatio(50); + entity.setLevel(1); + entity.setStyleType(1); + this.baseMapper.insert(entity); + return entity; + } + } + + /** + * 查询店员等级 + * + * @param id + * 店员等级主键 + * @return 店员等级 + */ + @Override + public PlayClerkLevelInfoEntity selectPlayClerkLevelInfoById(String id) { + return this.baseMapper.selectById(id); + } + + @Override + public List selectAll() { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.orderByAsc(PlayClerkLevelInfoEntity::getLevel); + return this.baseMapper.selectList(lambdaQueryWrapper); + } + + /** + * 查询店员等级列表 + * + * @param playClerkLevelInfo + * 店员等级 + * @return 店员等级 + */ + @Override + public IPage selectPlayClerkLevelInfoByPage(PlayClerkLevelInfoEntity playClerkLevelInfo) { + Page page = new Page<>(1, 9999); + return this.baseMapper.selectPage(page, new LambdaQueryWrapper<>()); + } + + /** + * 新增店员等级 + * + * @param playClerkLevelInfo + * 店员等级 + * @return 结果 + */ + @Override + public boolean create(PlayClerkLevelInfoEntity playClerkLevelInfo) { + if (StrUtil.isBlankIfStr(playClerkLevelInfo.getId())) { + playClerkLevelInfo.setId(IdUtils.getUuid()); + } + playClerkLevelInfo.setCreatedTime(new Date()); + playClerkLevelInfo.setStyleType(playClerkLevelInfo.getLevel()); + return save(playClerkLevelInfo); + } + + /** + * 修改店员等级 + * + * @param playClerkLevelInfo + * 店员等级 + * @return 结果 + */ + @Override + public boolean update(PlayClerkLevelInfoEntity playClerkLevelInfo) { + return updateById(playClerkLevelInfo); + } + + /** + * 批量删除店员等级 + * + * @param ids + * 需要删除的店员等级主键 + * @return 结果 + */ + @Override + public int deletePlayClerkLevelInfoByIds(String[] ids) { + return playClerkLevelInfoMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除店员等级信息 + * + * @param id + * 店员等级主键 + * @return 结果 + */ + @Override + public int deletePlayClerkLevelInfoById(String id) { + return playClerkLevelInfoMapper.deleteById(id); + } + + @Override + public int selectMaxLevel() { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.select("max(level) as level "); + PlayClerkLevelInfoEntity entity = this.baseMapper.selectOne(queryWrapper); + return entity == null ? 0 : entity.getLevel(); + } + + @Override + public void delMaxLevelByLevel(Integer level) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(PlayClerkLevelInfoEntity::getLevel, level); + playClerkLevelInfoMapper.delete(queryWrapper); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/service/impl/PlayClerkPkServiceImpl.java --- +package com.starry.admin.modules.clerk.service.impl; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.starry.admin.modules.clerk.mapper.PlayClerkPkMapper; +import com.starry.admin.modules.clerk.module.entity.ClerkPkEnum; +import com.starry.admin.modules.clerk.module.entity.PlayClerkPkEntity; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity; +import com.starry.admin.modules.clerk.service.IPlayClerkPkService; +import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService; +import com.starry.common.utils.IdUtils; +import java.util.Arrays; +import java.util.Date; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 店员pkService业务层处理 + * + * @author admin + * @since 2024-08-02 + */ +@Service +public class PlayClerkPkServiceImpl extends ServiceImpl + implements + IPlayClerkPkService { + @Resource + private PlayClerkPkMapper playClerkPkMapper; + @Resource + private IPlayClerkUserInfoService clerkUserInfoService; + + /** + * 查询店员pk + * + * @param id + * 店员pk主键 + * @return 店员pk + */ + @Override + public PlayClerkPkEntity selectPlayClerkPkById(String id) { + return this.baseMapper.selectById(id); + } + + /** + * 查询店员pk列表 + * + * @param playClerkPk + * 店员pk + * @return 店员pk + */ + @Override + public IPage selectPlayClerkPkByPage(PlayClerkPkEntity playClerkPk) { + Page page = new Page<>(1, 10); + return this.baseMapper.selectPage(page, new LambdaQueryWrapper<>()); + } + + /** + * 新增店员pk + * + * @param playClerkPk + * 店员pk + * @return 结果 + */ + @Override + public boolean create(PlayClerkPkEntity playClerkPk) { + if (StrUtil.isBlankIfStr(playClerkPk.getId())) { + playClerkPk.setId(IdUtils.getUuid()); + } + if (DateUtil.compare(playClerkPk.getPkBeginTime(), new Date()) < 1) { + throw new RuntimeException("开始时间必须大于当前时间"); + } + if (DateUtil.compare(playClerkPk.getPkEndTime(), new Date()) < 1) { + throw new RuntimeException("结束时间必须大于当前时间"); + } + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(PlayClerkPkEntity.class) + .in(PlayClerkPkEntity::getClerkA, Arrays.asList(playClerkPk.getClerkA(), playClerkPk.getClerkB())) + .in(PlayClerkPkEntity::getStatus, + Arrays.asList(ClerkPkEnum.TO_BE_STARTED.name(), ClerkPkEnum.IN_PROGRESS.name())); + long count = this.count(wrapper); + if (count > 0) { + PlayClerkUserInfoEntity clerkUserInfo = clerkUserInfoService.selectById(playClerkPk.getClerkA()); + throw new RuntimeException("店员【" + clerkUserInfo.getNickname() + "】还有未完成的PK,无法继续添加"); + } + wrapper.clear(); + wrapper = Wrappers.lambdaQuery(PlayClerkPkEntity.class) + .in(PlayClerkPkEntity::getClerkB, Arrays.asList(playClerkPk.getClerkA(), playClerkPk.getClerkB())) + .in(PlayClerkPkEntity::getStatus, + Arrays.asList(ClerkPkEnum.TO_BE_STARTED.name(), ClerkPkEnum.IN_PROGRESS.name())); + count = this.count(wrapper); + if (count > 0) { + PlayClerkUserInfoEntity clerkUserInfo = clerkUserInfoService.selectById(playClerkPk.getClerkB()); + throw new RuntimeException("店员【" + clerkUserInfo.getNickname() + "】还有未完成的PK,无法继续添加"); + } + + playClerkPk.setStatus(ClerkPkEnum.TO_BE_STARTED.name()); + return save(playClerkPk); + } + + /** + * 修改店员pk + * + * @param playClerkPk + * 店员pk + * @return 结果 + */ + @Override + public boolean update(PlayClerkPkEntity playClerkPk) { + return updateById(playClerkPk); + } + + /** + * 批量删除店员pk + * + * @param ids + * 需要删除的店员pk主键 + * @return 结果 + */ + @Override + public int deletePlayClerkPkByIds(String[] ids) { + return playClerkPkMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除店员pk信息 + * + * @param id + * 店员pk主键 + * @return 结果 + */ + @Override + public int deletePlayClerkPkById(String id) { + return playClerkPkMapper.deleteById(id); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/service/impl/PlayClerkRankingInfoServiceImpl.java --- +package com.starry.admin.modules.clerk.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.github.yulichang.wrapper.MPJLambdaWrapper; +import com.starry.admin.modules.clerk.mapper.PlayClerkRankingInfoMapper; +import com.starry.admin.modules.clerk.module.entity.*; +import com.starry.admin.modules.clerk.service.IPlayClerkRankingInfoService; +import com.starry.admin.modules.personnel.service.IPlayPersonnelGroupInfoService; +import com.starry.admin.modules.weichat.entity.order.PlayOrderHistoryRankingReturnVo; +import com.starry.admin.modules.weichat.entity.order.PlayOrderRankingListVo; +import com.starry.admin.modules.weichat.entity.order.PlayOrderRankingReturnVo; +import com.starry.admin.utils.SecurityUtils; +import com.starry.common.utils.IdUtils; +import java.time.LocalDate; +import java.util.Arrays; +import java.util.List; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 店员排行Service业务层处理 + * + * @author admin + * @since 2024-05-25 + */ +@Service +public class PlayClerkRankingInfoServiceImpl extends ServiceImpl + implements + IPlayClerkRankingInfoService { + @Resource + private PlayClerkRankingInfoMapper playClerkRankingInfoMapper; + + @Resource + private IPlayPersonnelGroupInfoService playClerkGroupInfoService; + + @Override + public IPage selectByPage(IPlayClerkRankingInfoQueryVo vo) { + MPJLambdaWrapper lambdaQueryWrapper = new MPJLambdaWrapper<>(); + lambdaQueryWrapper.selectAll(PlayClerkRankingInfoEntity.class); + // 拼接店员表 + lambdaQueryWrapper.selectAs(PlayClerkUserInfoEntity::getNickname, "clerkNickname") + .selectAs(PlayClerkUserInfoEntity::getSex, "clerkSex"); + lambdaQueryWrapper.leftJoin(PlayClerkUserInfoEntity.class, PlayClerkUserInfoEntity::getId, + PlayClerkRankingInfoEntity::getClerkId); + if (StrUtil.isNotBlank(vo.getClerkId())) { + lambdaQueryWrapper.eq(PlayClerkRankingInfoEntity::getClerkId, vo.getClerkId()); + } + if (StrUtil.isNotBlank(vo.getWeeklyRanking())) { + lambdaQueryWrapper.eq(PlayClerkRankingInfoEntity::getWeeklyRanking, vo.getWeeklyRanking()); + } + if (StrUtil.isNotBlank(vo.getHistoricalStatistics())) { + lambdaQueryWrapper.eq(PlayClerkRankingInfoEntity::getHistoricalStatistics, vo.getHistoricalStatistics()); + } + if (StrUtil.isNotBlank(vo.getSex())) { + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getSex, vo.getSex()); + } + if (vo.getSettlementDate() != null) { + lambdaQueryWrapper.eq(PlayClerkRankingInfoEntity::getSettlementDate, vo.getSettlementDate()); + } + // 加入组员的筛选 + List clerkIdList = playClerkGroupInfoService.getValidClerkIdList(SecurityUtils.getLoginUser(), null); + lambdaQueryWrapper.in(PlayClerkUserInfoEntity::getId, clerkIdList); + + lambdaQueryWrapper.orderByAsc(PlayClerkRankingInfoEntity::getRankingIndex); + return this.baseMapper.selectJoinPage(new Page<>(vo.getPageNum(), vo.getPageSize()), + IPlayClerkRankingInfoReturnVo.class, lambdaQueryWrapper); + } + + /** + * 查询店员排行 + * + * @param id + * 店员排行主键 + * @return 店员排行 + */ + @Override + public PlayClerkRankingInfoEntity selectPlayClerkRankingInfoById(String id) { + return this.baseMapper.selectById(id); + } + + @Override + public List selectHistoryRanking(String clerkId) { + long serialNumber = selectSerialNumber("1"); + MPJLambdaWrapper lambdaQueryWrapper = new MPJLambdaWrapper<>(); + // 根据排行序号和用户ID查询 + lambdaQueryWrapper.ne(PlayClerkRankingInfoEntity::getSerialNumber, serialNumber); + lambdaQueryWrapper.eq(PlayClerkRankingInfoEntity::getClerkId, clerkId); + return this.baseMapper.selectJoinList(PlayOrderHistoryRankingReturnVo.class, lambdaQueryWrapper); + } + + @Override + public PlayOrderRankingReturnVo selectCurrentRanking(String clerkId) { + long serialNumber = selectSerialNumber("1"); + MPJLambdaWrapper lambdaQueryWrapper = new MPJLambdaWrapper<>(); + lambdaQueryWrapper.selectAll(PlayClerkRankingInfoEntity.class); + // 店员信息 + lambdaQueryWrapper.selectAs(PlayClerkUserInfoEntity::getId, "clerkId") + .selectAs(PlayClerkUserInfoEntity::getNickname, "clerkNickname") + .selectAs(PlayClerkUserInfoEntity::getAvatar, "clerkAvatar") + .selectAs(PlayClerkUserInfoEntity::getSex, "clerkSex"); + lambdaQueryWrapper.leftJoin(PlayClerkUserInfoEntity.class, PlayClerkUserInfoEntity::getId, + PlayClerkRankingInfoEntity::getClerkId); + // 店员等级 + lambdaQueryWrapper.selectAs(PlayClerkLevelInfoEntity::getId, "levelId") + .selectAs(PlayClerkLevelInfoEntity::getName, "levelName"); + lambdaQueryWrapper.leftJoin(PlayClerkLevelInfoEntity.class, PlayClerkLevelInfoEntity::getId, + PlayClerkUserInfoEntity::getLevelId); + // 根据排行序号和用户ID查询 + lambdaQueryWrapper.eq(PlayClerkRankingInfoEntity::getSerialNumber, serialNumber); + lambdaQueryWrapper.eq(PlayClerkRankingInfoEntity::getClerkId, clerkId); + lambdaQueryWrapper.eq(PlayClerkRankingInfoEntity::getHistoricalStatistics, "0"); + PlayOrderRankingReturnVo returnVo = this.baseMapper.selectJoinOne(PlayOrderRankingReturnVo.class, + lambdaQueryWrapper); + if (returnVo == null) { + returnVo = new PlayOrderRankingReturnVo(); + } + returnVo.setRankings(this.selectBySerialNumber(serialNumber)); + return returnVo; + } + + @Override + public List selectMaxSerialNumber(String weeklyRanking) { + MPJLambdaWrapper lambdaQueryWrapper = new MPJLambdaWrapper<>(); + lambdaQueryWrapper.eq(PlayClerkRankingInfoEntity::getSerialNumber, this.selectSerialNumber(weeklyRanking)); + return this.baseMapper.selectList(lambdaQueryWrapper); + } + + @Override + public void updateClerkRankingInfo(String weeklyRanking, Integer serialNumber) { + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper<>(); + lambdaUpdateWrapper.eq(PlayClerkRankingInfoEntity::getWeeklyRanking, weeklyRanking); + lambdaUpdateWrapper.eq(PlayClerkRankingInfoEntity::getSerialNumber, serialNumber); + lambdaUpdateWrapper.set(PlayClerkRankingInfoEntity::getHistoricalStatistics, "1"); + this.baseMapper.update(null, lambdaUpdateWrapper); + } + + /** + * 获取当前期排名序号 + * + * @return PlayClerkRankingInfoEntity + */ + @Override + public Integer selectSerialNumber(String weeklyRanking) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayClerkRankingInfoEntity::getWeeklyRanking, weeklyRanking); + lambdaQueryWrapper.orderByDesc(PlayClerkRankingInfoEntity::getSerialNumber).last("limit 1"); + PlayClerkRankingInfoEntity entity = this.baseMapper.selectOne(lambdaQueryWrapper); + if (entity == null || entity.getSerialNumber() == null) { + return 0; + } + return entity.getSerialNumber(); + } + + List selectBySerialNumber(long serialNumber) { + MPJLambdaWrapper lambdaQueryWrapper = new MPJLambdaWrapper<>(); + lambdaQueryWrapper.eq(PlayClerkRankingInfoEntity::getSerialNumber, serialNumber); + lambdaQueryWrapper.orderByDesc(PlayClerkRankingInfoEntity::getRankingIndex); + lambdaQueryWrapper.selectAll(PlayClerkRankingInfoEntity.class); + // 店员信息 + lambdaQueryWrapper.selectAs(PlayClerkUserInfoEntity::getId, "clerkId") + .selectAs(PlayClerkUserInfoEntity::getNickname, "clerkNickname") + .selectAs(PlayClerkUserInfoEntity::getAvatar, "clerkAvatar") + .selectAs(PlayClerkUserInfoEntity::getSex, "clerkSex"); + lambdaQueryWrapper.leftJoin(PlayClerkUserInfoEntity.class, PlayClerkUserInfoEntity::getId, + PlayClerkRankingInfoEntity::getClerkId); + // 店员等级 + lambdaQueryWrapper.selectAs(PlayClerkLevelInfoEntity::getId, "levelId") + .selectAs(PlayClerkLevelInfoEntity::getName, "levelName"); + lambdaQueryWrapper.leftJoin(PlayClerkLevelInfoEntity.class, PlayClerkLevelInfoEntity::getId, + PlayClerkUserInfoEntity::getLevelId); + return this.baseMapper.selectJoinList(PlayOrderRankingListVo.class, lambdaQueryWrapper); + } + + @Override + public PlayClerkRankingInfoEntity selectByTime(String clerkId, LocalDate startTime, LocalDate endTime) { + MPJLambdaWrapper lambdaQueryWrapper = new MPJLambdaWrapper<>(); + lambdaQueryWrapper.eq(PlayClerkRankingInfoEntity::getStartCountDate, startTime); + lambdaQueryWrapper.eq(PlayClerkRankingInfoEntity::getEndCountDate, endTime); + lambdaQueryWrapper.eq(PlayClerkRankingInfoEntity::getClerkId, clerkId); + return this.baseMapper.selectOne(lambdaQueryWrapper); + } + + /** + * 查询店员排行列表 + * + * @param playClerkRankingInfo + * 店员排行 + * @return 店员排行 + */ + @Override + public IPage selectPlayClerkRankingInfoByPage( + PlayClerkRankingInfoEntity playClerkRankingInfo) { + Page page = new Page<>(1, 10); + return this.baseMapper.selectPage(page, new LambdaQueryWrapper<>()); + } + + /** + * 新增店员排行 + * + * @param playClerkRankingInfo + * 店员排行 + * @return 结果 + */ + @Override + public boolean create(PlayClerkRankingInfoEntity playClerkRankingInfo) { + if (StrUtil.isBlankIfStr(playClerkRankingInfo.getId())) { + playClerkRankingInfo.setId(IdUtils.getUuid()); + } + return save(playClerkRankingInfo); + } + + /** + * 修改店员排行 + * + * @param playClerkRankingInfo + * 店员排行 + * @return 结果 + */ + @Override + public boolean update(PlayClerkRankingInfoEntity playClerkRankingInfo) { + return updateById(playClerkRankingInfo); + } + + /** + * 批量删除店员排行 + * + * @param ids + * 需要删除的店员排行主键 + * @return 结果 + */ + @Override + public int deletePlayClerkRankingInfoByIds(String[] ids) { + return playClerkRankingInfoMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除店员排行信息 + * + * @param id + * 店员排行主键 + * @return 结果 + */ + @Override + public int deletePlayClerkRankingInfoById(String id) { + return playClerkRankingInfoMapper.deleteById(id); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/service/impl/PlayClerkTypeInfoServiceImpl.java --- +package com.starry.admin.modules.clerk.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.github.yulichang.wrapper.MPJLambdaWrapper; +import com.starry.admin.modules.clerk.mapper.PlayClerkTypeInfoMapper; +import com.starry.admin.modules.clerk.module.entity.PlayClerkTypeInfoEntity; +import com.starry.admin.modules.clerk.module.vo.PlayClerkTypeInfoQueryVo; +import com.starry.admin.modules.clerk.module.vo.PlayClerkTypeInfoReturnVo; +import com.starry.admin.modules.clerk.service.IPlayClerkTypeInfoService; +import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService; +import com.starry.common.utils.IdUtils; +import java.util.Arrays; +import java.util.List; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 店员分类信息Service业务层处理 + * + * @author admin + * @since 2024-05-31 + */ +@Service +public class PlayClerkTypeInfoServiceImpl extends ServiceImpl + implements + IPlayClerkTypeInfoService { + + @Resource + private PlayClerkTypeInfoMapper playClerkTypeInfoMapper; + + @Resource + private IPlayClerkUserInfoService playClerkUserInfoService; + + /** + * 查询店员分类信息 + * + * @param id + * 店员分类信息主键 + * @return 店员分类信息 + */ + @Override + public PlayClerkTypeInfoEntity selectPlayClerkTypeInfoById(String id) { + return this.baseMapper.selectById(id); + } + + @Override + public List selectByAll() { + return this.baseMapper.selectList(new LambdaQueryWrapper<>()); + } + + /** + * 查询店员分类信息列表 + * + * @param vo + * 店员分类信息 + * @return 店员分类信息 + */ + @Override + public IPage selectByPage(PlayClerkTypeInfoQueryVo vo) { + MPJLambdaWrapper lambdaWrapper = new MPJLambdaWrapper<>(); + lambdaWrapper.orderByAsc(PlayClerkTypeInfoEntity::getSort); + IPage page = this.baseMapper.selectJoinPage( + new Page<>(vo.getPageNum(), vo.getPageSize()), PlayClerkTypeInfoReturnVo.class, lambdaWrapper); + for (PlayClerkTypeInfoReturnVo record : page.getRecords()) { + record.setClerkNumber(playClerkUserInfoService.listAllByTypeId(record.getId()).size()); + } + return page; + } + + /** + * 新增店员分类信息 + * + * @param playClerkTypeInfo + * 店员分类信息 + * @return 结果 + */ + @Override + public boolean create(PlayClerkTypeInfoEntity playClerkTypeInfo) { + if (StrUtil.isBlankIfStr(playClerkTypeInfo.getId())) { + playClerkTypeInfo.setId(IdUtils.getUuid()); + } + return save(playClerkTypeInfo); + } + + /** + * 修改店员分类信息 + * + * @param playClerkTypeInfo + * 店员分类信息 + * @return 结果 + */ + @Override + public boolean update(PlayClerkTypeInfoEntity playClerkTypeInfo) { + return updateById(playClerkTypeInfo); + } + + /** + * 批量删除店员分类信息 + * + * @param ids + * 需要删除的店员分类信息主键 + * @return 结果 + */ + @Override + public int deletePlayClerkTypeInfoByIds(String[] ids) { + return playClerkTypeInfoMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除店员分类信息信息 + * + * @param id + * 店员分类信息主键 + * @return 结果 + */ + @Override + public int deletePlayClerkTypeInfoById(String id) { + return playClerkTypeInfoMapper.deleteById(id); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/service/impl/PlayClerkTypeUserInfoServiceImpl.java --- +package com.starry.admin.modules.clerk.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.starry.admin.modules.clerk.mapper.PlayClerkTypeUserInfoMapper; +import com.starry.admin.modules.clerk.module.entity.PlayClerkTypeUserInfoEntity; +import com.starry.admin.modules.clerk.service.IPlayClerkTypeUserInfoService; +import com.starry.common.utils.IdUtils; +import java.util.Arrays; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 店员和分类关系Service业务层处理 + * + * @author admin + * @since 2024-05-31 + */ +@Service +public class PlayClerkTypeUserInfoServiceImpl + extends + ServiceImpl + implements + IPlayClerkTypeUserInfoService { + @Resource + private PlayClerkTypeUserInfoMapper playClerkTypeUserInfoMapper; + + /** + * 查询店员和分类关系 + * + * @param id + * 店员和分类关系主键 + * @return 店员和分类关系 + */ + @Override + public PlayClerkTypeUserInfoEntity selectPlayClerkTypeUserInfoById(String id) { + return this.baseMapper.selectById(id); + } + + /** + * 查询店员和分类关系列表 + * + * @param playClerkTypeUserInfo + * 店员和分类关系 + * @return 店员和分类关系 + */ + @Override + public IPage selectPlayClerkTypeUserInfoByPage( + PlayClerkTypeUserInfoEntity playClerkTypeUserInfo) { + Page page = new Page<>(1, 10); + return this.baseMapper.selectPage(page, new LambdaQueryWrapper()); + } + + /** + * 新增店员和分类关系 + * + * @param playClerkTypeUserInfo + * 店员和分类关系 + * @return 结果 + */ + @Override + public boolean create(PlayClerkTypeUserInfoEntity playClerkTypeUserInfo) { + if (StrUtil.isBlankIfStr(playClerkTypeUserInfo.getId())) { + playClerkTypeUserInfo.setId(IdUtils.getUuid()); + } + return save(playClerkTypeUserInfo); + } + + /** + * 修改店员和分类关系 + * + * @param playClerkTypeUserInfo + * 店员和分类关系 + * @return 结果 + */ + @Override + public boolean update(PlayClerkTypeUserInfoEntity playClerkTypeUserInfo) { + return updateById(playClerkTypeUserInfo); + } + + /** + * 批量删除店员和分类关系 + * + * @param ids + * 需要删除的店员和分类关系主键 + * @return 结果 + */ + @Override + public int deletePlayClerkTypeUserInfoByIds(String[] ids) { + return playClerkTypeUserInfoMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除店员和分类关系信息 + * + * @param id + * 店员和分类关系主键 + * @return 结果 + */ + @Override + public int deletePlayClerkTypeUserInfoById(String id) { + return playClerkTypeUserInfoMapper.deleteById(id); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/service/impl/PlayClerkUserInfoServiceImpl.java --- +package com.starry.admin.modules.clerk.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson2.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.github.yulichang.wrapper.MPJLambdaWrapper; +import com.starry.admin.common.component.JwtToken; +import com.starry.admin.common.domain.LoginUser; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.clerk.mapper.PlayClerkUserInfoMapper; +import com.starry.admin.modules.clerk.module.entity.*; +import com.starry.admin.modules.clerk.module.vo.PlayClerkCommodityQueryVo; +import com.starry.admin.modules.clerk.module.vo.PlayClerkUnsettledWagesInfoQueryVo; +import com.starry.admin.modules.clerk.module.vo.PlayClerkUnsettledWagesInfoReturnVo; +import com.starry.admin.modules.clerk.service.IPlayClerkCommodityService; +import com.starry.admin.modules.clerk.service.IPlayClerkLevelInfoService; +import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService; +import com.starry.admin.modules.custom.entity.PlayCustomFollowInfoEntity; +import com.starry.admin.modules.custom.service.IPlayCustomFollowInfoService; +import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity; +import com.starry.admin.modules.order.service.IPlayOrderInfoService; +import com.starry.admin.modules.personnel.module.entity.PlayPersonnelAdminInfoEntity; +import com.starry.admin.modules.personnel.module.entity.PlayPersonnelGroupInfoEntity; +import com.starry.admin.modules.personnel.module.entity.PlayPersonnelWaiterInfoEntity; +import com.starry.admin.modules.personnel.service.IPlayBalanceDetailsInfoService; +import com.starry.admin.modules.personnel.service.IPlayPersonnelAdminInfoService; +import com.starry.admin.modules.personnel.service.IPlayPersonnelGroupInfoService; +import com.starry.admin.modules.personnel.service.IPlayPersonnelWaiterInfoService; +import com.starry.admin.modules.statistics.module.vo.PlayClerkPerformanceInfoQueryVo; +import com.starry.admin.modules.system.service.LoginService; +import com.starry.admin.modules.weichat.entity.PlayClerkUserLoginResponseVo; +import com.starry.admin.modules.weichat.entity.clerk.PlayClerkUserInfoQueryVo; +import com.starry.admin.modules.weichat.entity.clerk.PlayClerkUserInfoResultVo; +import com.starry.admin.utils.SecurityUtils; +import com.starry.common.utils.ConvertUtil; +import com.starry.common.utils.IdUtils; +import com.starry.common.utils.StringUtils; +import java.math.BigDecimal; +import java.util.*; +import java.util.stream.Collectors; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 店员Service业务层处理 + * + * @author admin + * @since 2024-03-30 + */ +@Service +public class PlayClerkUserInfoServiceImpl extends ServiceImpl + implements + IPlayClerkUserInfoService { + @Resource + private PlayClerkUserInfoMapper playClerkUserInfoMapper; + @Resource + private PlayClerkUserReviewInfoServiceImpl playClerkUserReviewInfoService; + @Resource + private IPlayClerkCommodityService playClerkCommodityService; + @Resource + private IPlayCustomFollowInfoService customFollowInfoService; + @Resource + private IPlayBalanceDetailsInfoService playBalanceDetailsInfoService; + @Resource + private IPlayOrderInfoService playOrderInfoService; + @Resource + private IPlayPersonnelGroupInfoService playClerkGroupInfoService; + @Resource + private IPlayPersonnelAdminInfoService playPersonnelAdminInfoService; + @Resource + private IPlayPersonnelWaiterInfoService playClerkWaiterInfoService; + @Resource + private LoginService loginService; + @Resource + private JwtToken jwtToken; + @Resource + private IPlayClerkLevelInfoService playClerkLevelInfoService; + + @Override + public List listAllByTypeId(String typeId) { + MPJLambdaWrapper lambdaWrapper = new MPJLambdaWrapper<>(); + lambdaWrapper.select(PlayClerkUserInfoEntity::getId); + lambdaWrapper.eq(PlayClerkUserInfoEntity::getTypeId, typeId); + return this.baseMapper.selectList(lambdaWrapper); + } + + @Override + public List listAllByGroupId(String groupId) { + MPJLambdaWrapper lambdaWrapper = new MPJLambdaWrapper<>(); + lambdaWrapper.select(PlayClerkUserInfoEntity::getId, PlayClerkUserInfoEntity::getListingState); + lambdaWrapper.eq(PlayClerkUserInfoEntity::getGroupId, groupId); + return this.baseMapper.selectList(lambdaWrapper); + } + + @Override + public Long getTotalClerkUser(String tenantId) { + MPJLambdaWrapper lambdaWrapper = new MPJLambdaWrapper<>(); + lambdaWrapper.eq(PlayClerkUserInfoEntity::getTenantId, tenantId); + return this.baseMapper.selectCount(lambdaWrapper); + } + + @Override + public PlayClerkLevelInfoEntity queryLevelCommission(String clerkId) { + MPJLambdaWrapper lambdaWrapper = new MPJLambdaWrapper<>(); + lambdaWrapper.selectAll(PlayClerkLevelInfoEntity.class); + lambdaWrapper.selectAs(PlayClerkUserInfoEntity::getLevelId, "levelId"); + lambdaWrapper.leftJoin(PlayClerkLevelInfoEntity.class, PlayClerkLevelInfoEntity::getId, + PlayClerkUserInfoEntity::getLevelId); + lambdaWrapper.eq(PlayClerkUserInfoEntity::getId, clerkId); + return this.baseMapper.selectJoinOne(PlayClerkLevelInfoEntity.class, lambdaWrapper); + + } + + @Override + public PlayClerkUserInfoEntity selectByOpenid(String openId) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getOpenid, openId); + return this.baseMapper.selectOne(lambdaQueryWrapper); + } + + /** + * 查询店员 + * + * @param id + * 店员主键 + * @return 店员 + */ + @Override + public PlayClerkUserInfoEntity selectById(String id) { + PlayClerkUserInfoEntity entity = this.baseMapper.selectById(id); + if (entity == null) { + throw new CustomException("店员不存在"); + } + return entity; + } + + @Override + public PlayClerkUserLoginResponseVo getVo(PlayClerkUserInfoEntity userInfo) { + PlayClerkUserLoginResponseVo result = ConvertUtil.entityToVo(userInfo, PlayClerkUserLoginResponseVo.class); + // List list = + // playClerkDataReviewInfoService.queryByClerkId(userInfo.getId(),"0"); + // // 判断头像、音频、相册是否可以编辑,如果存在未审核的数据,则不允许编辑 + // Map map = + // list.stream().collect(Collectors.toMap(PlayClerkDataReviewInfoEntity::getDataType, + // account -> account, (entity1, entity2) -> entity1)); + // if (map.containsKey("1")) { + // result.setAvatarAllowEdit(false); + // } + // if (map.containsKey("2")) { + // result.setAlbumAllowEdit(false); + // } + // if (map.containsKey("3")) { + // result.setAudioAllowEdit(false); + // } + // 是店员之后,判断是否可以登录 + if ("1".equals(result.getClerkState())) { + // 设置店员是否运行登录 + if ("0".equals(userInfo.getOnboardingState())) { + result.setAllowLogin("1"); + result.setDisableLoginReason("你已离职,需要复职请联系店铺管理员"); + } + if ("0".equals(userInfo.getListingState())) { + result.setAllowLogin("1"); + result.setDisableLoginReason("你已被下架,没有权限访问"); + } + + } + + // 如果存在未审批的申请,或者当前已经是店员-可以申请陪聊 + PlayClerkUserReviewInfoEntity entity = playClerkUserReviewInfoService.queryByClerkId(userInfo.getId(), "0"); + if (entity != null || "1".equals(result.getClerkState())) { + result.setClerkAllowEdit(false); + } + + // 查询店员服务项目 + List clerkCommodityEntities = playClerkCommodityService + .selectCommodityTypeByUser(userInfo.getId(), ""); + List playClerkCommodityQueryVos = new ArrayList<>(); + for (PlayClerkCommodityEntity clerkCommodityEntity : clerkCommodityEntities) { + playClerkCommodityQueryVos.add(new PlayClerkCommodityQueryVo(clerkCommodityEntity.getCommodityName(), + clerkCommodityEntity.getEnablingState())); + } + result.setCommodity(playClerkCommodityQueryVos); + result.setArea(userInfo.getProvince() + "-" + userInfo.getCity()); + + result.setPcData(this.getPcData(userInfo)); + result.setLevelInfo(playClerkLevelInfoService.selectPlayClerkLevelInfoById(userInfo.getLevelId())); + return result; + } + + @Override + public void updateTokenById(String id, String token) { + PlayClerkUserInfoEntity entity = new PlayClerkUserInfoEntity(); + entity.setToken(token); + entity.setId(id); + entity.setOnlineState("1"); + this.baseMapper.updateById(entity); + } + + @Override + public void updateAccountBalanceById(String id, BigDecimal accountBalance) { + + } + + @Override + public void updateAccountBalanceById(String userId, BigDecimal balanceBeforeOperation, + BigDecimal balanceAfterOperation, String operationType, String operationAction, BigDecimal balanceMoney, + String orderId) { + // 修改用户余额 + this.baseMapper.updateById(new PlayClerkUserInfoEntity(userId, balanceAfterOperation)); + // 记录余额变更记录 + playBalanceDetailsInfoService.insertBalanceDetailsInfo("0", userId, balanceBeforeOperation, + balanceAfterOperation, operationType, operationAction, balanceMoney, BigDecimal.ZERO, orderId); + } + + /** + * 查询店员列表 + * + * @param vo + * 店员查询对象 + * @return 店员 + */ + @Override + public IPage selectPlayClerkUserInfoByPage(PlayClerkUserInfoQueryVo vo) { + Page page = new Page<>(vo.getPageNum(), vo.getPageSize()); + + MPJLambdaWrapper lambdaQueryWrapper = new MPJLambdaWrapper<>(); + // 查询不隐藏的 + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getDisplayState, "1"); + // 查询主表全部字段 + lambdaQueryWrapper.selectAll(PlayClerkUserInfoEntity.class).selectAs(PlayClerkUserInfoEntity::getCity, + "address"); + // 等级表 + lambdaQueryWrapper.selectAs(PlayClerkLevelInfoEntity::getName, "levelName"); + lambdaQueryWrapper.leftJoin(PlayClerkLevelInfoEntity.class, PlayClerkLevelInfoEntity::getId, + PlayClerkUserInfoEntity::getLevelId); + + // 服务项目表 + if (StrUtil.isNotBlank(vo.getNickname())) { + lambdaQueryWrapper.like(PlayClerkUserInfoEntity::getNickname, vo.getNickname()); + } + if (StrUtil.isNotBlank(vo.getTypeId())) { + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getTypeId, vo.getTypeId()); + } + if (StrUtil.isNotBlank(vo.getLevelId())) { + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getLevelId, vo.getLevelId()); + } + if (StrUtil.isNotBlank(vo.getSex())) { + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getSex, vo.getSex()); + } + if (StrUtil.isNotBlank(vo.getProvince())) { + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getProvince, vo.getProvince()); + } + if (StrUtil.isNotBlank(vo.getClerkState())) { + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getClerkState, vo.getClerkState()); + } + if (StrUtil.isNotBlank(vo.getRecommendationState())) { + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getRecommendationState, vo.getRecommendationState()); + } + if (StrUtil.isNotBlank(vo.getOnboardingState())) { + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getOnboardingState, vo.getOnboardingState()); + } + return this.baseMapper.selectJoinPage(page, PlayClerkUserInfoResultVo.class, lambdaQueryWrapper); + } + + @Override + public List listAll() { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getClerkState, "1"); + return this.baseMapper.selectList(lambdaQueryWrapper); + + } + + @Override + public IPage listUnsettledWagesByPage(PlayClerkUnsettledWagesInfoQueryVo vo) { + MPJLambdaWrapper lambdaQueryWrapper = new MPJLambdaWrapper<>(); + // 查询所有店员 + lambdaQueryWrapper.selectAs(PlayClerkUserInfoEntity::getNickname, "clerkNickname") + .selectAs(PlayClerkUserInfoEntity::getId, "clerkId"); + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getClerkState, "1"); + // 加入组员的筛选 + List clerkIdList = playClerkGroupInfoService.getValidClerkIdList(SecurityUtils.getLoginUser(), null); + lambdaQueryWrapper.in(PlayClerkUserInfoEntity::getId, clerkIdList); + if (StrUtil.isNotBlank(vo.getClerkId())) { + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getId, vo.getClerkId()); + } + if (StrUtil.isNotBlank(vo.getListingState())) { + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getListingState, vo.getListingState()); + } + // 查询店员订单信息 + lambdaQueryWrapper.selectCollection(PlayOrderInfoEntity.class, + PlayClerkUnsettledWagesInfoReturnVo::getOrderInfoEntities); + lambdaQueryWrapper.leftJoin(PlayOrderInfoEntity.class, PlayOrderInfoEntity::getAcceptBy, + PlayClerkUserInfoEntity::getId); + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getOrderSettlementState, "0"); + + return this.baseMapper.selectJoinPage(new Page<>(vo.getPageNum(), vo.getPageSize()), + PlayClerkUnsettledWagesInfoReturnVo.class, lambdaQueryWrapper); + } + + @Override + public IPage selectByPage(PlayClerkPerformanceInfoQueryVo vo) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + if (StrUtil.isNotBlank(vo.getClerkId())) { + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getId, vo.getClerkId()); + } + // if (StrUtil.isNotBlank(vo.getGroupId())) { + // lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getGroupId, vo.getGroupId()); + // } + if (StrUtil.isNotBlank(vo.getSex())) { + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getSex, vo.getSex()); + } + if (StrUtil.isNotBlank(vo.getListingState())) { + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getListingState, vo.getListingState()); + } + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getClerkState, "1"); + // 加入组员的筛选 + List clerkIdList = playClerkGroupInfoService.getValidClerkIdList(SecurityUtils.getLoginUser(), null); + lambdaQueryWrapper.in(PlayClerkUserInfoEntity::getId, clerkIdList); + return this.baseMapper.selectPage(new Page<>(vo.getPageNum(), vo.getPageSize()), lambdaQueryWrapper); + } + + @Override + public IPage selectByPage(PlayClerkUserQueryVo vo) { + MPJLambdaWrapper lambdaQueryWrapper = new MPJLambdaWrapper<>(); + + LoginUser loginUser = SecurityUtils.getLoginUser(); + // 主表(店员表全部字段) + lambdaQueryWrapper.selectAll(PlayClerkUserInfoEntity.class); + + if (StrUtil.isNotBlank(vo.getId())) { + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getId, vo.getId()); + } + if (StrUtil.isNotBlank(vo.getNickname())) { + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getNickname, vo.getNickname()); + } + if (StrUtil.isNotBlank(vo.getPhone())) { + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getPhone, vo.getPhone()); + } + if (StrUtil.isNotBlank(vo.getGroupId())) { + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getGroupId, vo.getGroupId()); + } + if (StrUtil.isNotBlank(vo.getSex())) { + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getSex, vo.getSex()); + } + if (StrUtil.isNotBlank(vo.getFixingLevel())) { + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getFixingLevel, vo.getFixingLevel()); + } + if (StrUtil.isNotBlank(vo.getLevelId())) { + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getLevelId, vo.getLevelId()); + } + if (StrUtil.isNotBlank(vo.getProvince())) { + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getProvince, vo.getProvince()); + } + if (StrUtil.isNotBlank(vo.getCity())) { + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getCity, vo.getCity()); + } + if (StrUtil.isNotBlank(vo.getOnboardingState())) { + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getOnboardingState, vo.getOnboardingState()); + } + if (StrUtil.isNotBlank(vo.getRecommendationState())) { + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getRecommendationState, vo.getRecommendationState()); + } + if (StrUtil.isNotBlank(vo.getPinToTopState())) { + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getPinToTopState, vo.getPinToTopState()); + } + if (StrUtil.isNotBlank(vo.getOnlineState())) { + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getOnlineState, vo.getOnlineState()); + } + if (StrUtil.isNotBlank(vo.getDisplayState())) { + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getDisplayState, vo.getDisplayState()); + } + if (StrUtil.isNotBlank(vo.getRealState())) { + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getRealState, vo.getRealState()); + } + if (StrUtil.isNotBlank(vo.getMandatoryRealState())) { + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getMandatoryRealState, vo.getMandatoryRealState()); + } + if (StrUtil.isNotBlank(vo.getClerkState())) { + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getClerkState, vo.getClerkState()); + } + if (StrUtil.isNotBlank(vo.getCode())) { + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getCode, vo.getCode()); + } + + // 加入组员的筛选 + List clerkIdList = playClerkGroupInfoService.getValidClerkIdList(SecurityUtils.getLoginUser(), null); + lambdaQueryWrapper.in(PlayClerkUserInfoEntity::getId, clerkIdList); + lambdaQueryWrapper.orderByDesc(PlayClerkUserInfoEntity::getCreatedTime); + IPage page = this.baseMapper.selectJoinPage( + new Page<>(vo.getPageNum(), vo.getPageSize()), PlayClerkUserReturnVo.class, lambdaQueryWrapper); + + for (PlayClerkUserReturnVo record : page.getRecords()) { + BigDecimal orderTotalAmount = new BigDecimal("0"); + int orderContinueNumber = 0; + int orderNumber = 0; + for (PlayOrderInfoEntity orderInfo : playOrderInfoService.queryBySettlementOrder(record.getId(), "")) { + if ("0".equals(orderInfo.getFirstOrder())) { + orderContinueNumber++; + } + orderNumber++; + if (!"4".equals(orderInfo.getOrderStatus())) { + orderTotalAmount = orderTotalAmount.add(orderInfo.getFinalAmount()); + } + } + record.setOrderTotalAmount(orderTotalAmount); + record.setOrderNumber(String.valueOf(orderNumber)); + record.setOrderContinueNumber(String.valueOf(orderContinueNumber)); + } + + return page; + } + + @Override + public IPage selectByPage(PlayClerkUserInfoQueryVo vo, String customUserId) { + IPage voPage = this.selectPlayClerkUserInfoByPage(vo); + Map customFollows = new HashMap<>(16); + // 如果当前顾客已登录,查询用户关注状态 + if (StrUtil.isNotBlank(customUserId)) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayCustomFollowInfoEntity::getCustomId, customUserId); + List customFollowInfoEntities = customFollowInfoService + .list(lambdaQueryWrapper); + customFollows = customFollowInfoEntities.stream().collect(Collectors + .toMap(PlayCustomFollowInfoEntity::getClerkId, PlayCustomFollowInfoEntity::getFollowState)); + } + for (PlayClerkUserInfoResultVo record : voPage.getRecords()) { + record.setFollowState(customFollows.containsKey(record.getId()) ? "1" : "0"); + record.setCommodity(playClerkCommodityService.getClerkCommodityList(record.getId(), "1")); + } + voPage.getRecords().parallelStream().forEach(ca -> { + ca.setLevelInfo(playClerkLevelInfoService.selectPlayClerkLevelInfoById(ca.getLevelId())); + }); + return voPage; + } + + /** + * 新增店员 + * + * @param playClerkUserInfo + * 店员 + * @return 结果 + */ + @Override + public boolean create(PlayClerkUserInfoEntity playClerkUserInfo) { + if (StrUtil.isBlankIfStr(playClerkUserInfo.getId())) { + playClerkUserInfo.setId(IdUtils.getUuid()); + } + return save(playClerkUserInfo); + } + + /** + * 修改店员 + * + * @param playClerkUserInfo + * 店员 + * @return 结果 + */ + @Override + public boolean update(PlayClerkUserInfoEntity playClerkUserInfo) { + return updateById(playClerkUserInfo); + } + + /** + * 批量删除店员 + * + * @param ids + * 需要删除的店员主键 + * @return 结果 + */ + @Override + public int deletePlayClerkUserInfoByIds(String[] ids) { + return playClerkUserInfoMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除店员信息 + * + * @param id + * 店员主键 + * @return 结果 + */ + @Override + public int deletePlayClerkUserInfoById(String id) { + return playClerkUserInfoMapper.deleteById(id); + } + + @Override + public List simpleList() { + List clerkIdList = playClerkGroupInfoService.getValidClerkIdList(SecurityUtils.getLoginUser(), null); + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayClerkUserInfoEntity::getDeleted, 0); + lambdaQueryWrapper.in(PlayClerkUserInfoEntity::getId, clerkIdList); + lambdaQueryWrapper.select(PlayClerkUserInfoEntity::getId, PlayClerkUserInfoEntity::getNickname, + PlayClerkUserInfoEntity::getAvatar, PlayClerkUserInfoEntity::getTypeId, + PlayClerkUserInfoEntity::getGroupId, PlayClerkUserInfoEntity::getPhone); + lambdaQueryWrapper.orderByDesc(PlayClerkUserInfoEntity::getId); + return this.baseMapper.selectList(lambdaQueryWrapper); + } + + @Override + public JSONObject getPcData(PlayClerkUserInfoEntity entity) { + JSONObject data = new JSONObject(); + data.fluentPut("token", ""); + data.fluentPut("role", ""); + if (StringUtils.isEmpty(entity.getSysUserId())) { + return data; + } + LoginUser loginUserInfo = loginService.getLoginUserInfo(entity.getSysUserId()); + Map tokenMap = jwtToken.createToken(loginUserInfo); + data.fluentPut("token", tokenMap.get("token")); + PlayPersonnelAdminInfoEntity adminInfoEntity = playPersonnelAdminInfoService + .selectByUserId(entity.getSysUserId()); + if (Objects.nonNull(adminInfoEntity)) { + data.fluentPut("role", "operator"); + return data; + } + PlayPersonnelGroupInfoEntity groupInfoEntity = playClerkGroupInfoService.selectByUserId(entity.getSysUserId()); + if (Objects.nonNull(groupInfoEntity)) { + data.fluentPut("role", "leader"); + return data; + } + PlayPersonnelWaiterInfoEntity waiterInfoEntity = playClerkWaiterInfoService + .selectByUserId(entity.getSysUserId()); + if (Objects.nonNull(waiterInfoEntity)) { + data.fluentPut("role", "waiter"); + return data; + } + return data; + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/service/impl/PlayClerkUserReviewInfoServiceImpl.java --- +package com.starry.admin.modules.clerk.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.github.yulichang.wrapper.MPJLambdaWrapper; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.clerk.mapper.PlayClerkUserReviewInfoMapper; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserReviewInfoEntity; +import com.starry.admin.modules.clerk.module.vo.PlayClerkUserReviewQueryVo; +import com.starry.admin.modules.clerk.module.vo.PlayClerkUserReviewReturnVo; +import com.starry.admin.modules.clerk.module.vo.PlayClerkUserReviewStateEditVo; +import com.starry.admin.modules.clerk.service.IPlayClerkCommodityService; +import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService; +import com.starry.admin.modules.clerk.service.IPlayClerkUserReviewInfoService; +import com.starry.admin.modules.weichat.service.WxCustomMpService; +import com.starry.common.utils.IdUtils; +import java.util.Arrays; +import javax.annotation.Resource; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +/** + * 店员资料审核Service业务层处理 + * + * @author admin + * @since 2024-05-19 + */ +@Service +public class PlayClerkUserReviewInfoServiceImpl + extends + ServiceImpl + implements + IPlayClerkUserReviewInfoService { + + @Resource + private PlayClerkUserReviewInfoMapper playClerkUserReviewInfoMapper; + @Resource + private IPlayClerkUserInfoService playClerkUserInfoService; + @Resource + private IPlayClerkCommodityService clerkCommodityService; + @Resource + private WxCustomMpService wxCustomMpService; + + @Override + public PlayClerkUserReviewInfoEntity queryByClerkId(String clerkId, String reviewState) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(PlayClerkUserReviewInfoEntity::getClerkId, clerkId); + queryWrapper.eq(PlayClerkUserReviewInfoEntity::getReviewState, reviewState); + return this.baseMapper.selectOne(queryWrapper); + } + + /** + * 查询店员资料审核 + * + * @param id + * 店员资料审核主键 + * @return 店员资料审核 + */ + @Override + public PlayClerkUserReviewInfoEntity selectPlayClerkUserReviewInfoById(String id) { + PlayClerkUserReviewInfoEntity entity = this.baseMapper.selectById(id); + if (entity == null) { + throw new CustomException("对象不存在"); + } + return entity; + } + + @Override + public IPage selectByPage(PlayClerkUserReviewQueryVo vo) { + MPJLambdaWrapper lambdaQueryWrapper = new MPJLambdaWrapper<>(); + lambdaQueryWrapper.selectAll(PlayClerkUserReviewInfoEntity.class); + // 店员表 + lambdaQueryWrapper.selectAs(PlayClerkUserInfoEntity::getAvatar, "clerkAvatar") + .selectAs(PlayClerkUserInfoEntity::getSignature, "signature"); + lambdaQueryWrapper.leftJoin(PlayClerkUserInfoEntity.class, PlayClerkUserInfoEntity::getId, + PlayClerkUserReviewInfoEntity::getClerkId); + if (StrUtil.isNotBlank(vo.getClerkId())) { + lambdaQueryWrapper.eq(PlayClerkUserReviewInfoEntity::getClerkId, vo.getClerkId()); + } + if (StrUtil.isNotBlank(vo.getSex())) { + lambdaQueryWrapper.eq(PlayClerkUserReviewInfoEntity::getSex, vo.getSex()); + } + if (StrUtil.isNotBlank(vo.getNickname())) { + lambdaQueryWrapper.like(PlayClerkUserReviewInfoEntity::getNickname, vo.getNickname()); + } + if (StrUtil.isNotBlank(vo.getPhone())) { + lambdaQueryWrapper.like(PlayClerkUserReviewInfoEntity::getPhone, vo.getPhone()); + } + if (StrUtil.isNotBlank(vo.getReviewState())) { + lambdaQueryWrapper.like(PlayClerkUserReviewInfoEntity::getReviewState, vo.getReviewState()); + } + if (StrUtil.isNotBlank(vo.getWeiChatCode())) { + lambdaQueryWrapper.like(PlayClerkUserReviewInfoEntity::getWeiChatCode, vo.getWeiChatCode()); + } + // 加入组员的筛选 + // List clerkIdList = + // playClerkGroupInfoService.getValidClerkIdList(SecurityUtils.getLoginUser(), + // null); + // lambdaQueryWrapper.in(PlayClerkUserInfoEntity::getId, clerkIdList); + lambdaQueryWrapper.orderByDesc(PlayClerkUserReviewInfoEntity::getAddTime); + lambdaQueryWrapper.orderByDesc(PlayClerkUserReviewInfoEntity::getClerkId); + return this.baseMapper.selectJoinPage(new Page<>(vo.getPageNum(), vo.getPageSize()), + PlayClerkUserReviewReturnVo.class, lambdaQueryWrapper); + } + + /** + * 查询店员资料审核列表 + * + * @param playClerkUserReviewInfo + * 店员资料审核 + * @return 店员资料审核 + */ + @Override + public IPage selectPlayClerkUserReviewInfoByPage( + PlayClerkUserReviewInfoEntity playClerkUserReviewInfo) { + Page page = new Page<>(1, 10); + return this.baseMapper.selectPage(page, new LambdaQueryWrapper<>()); + } + + /** + * 新增店员资料审核 + * + * @param playClerkUserReviewInfo + * 店员资料审核 + * @return 结果 + */ + @Override + public boolean create(PlayClerkUserReviewInfoEntity playClerkUserReviewInfo) { + if (StrUtil.isBlankIfStr(playClerkUserReviewInfo.getId())) { + playClerkUserReviewInfo.setId(IdUtils.getUuid()); + } + return save(playClerkUserReviewInfo); + } + + /** + * 修改店员资料审核 + * + * @param entity + * 店员资料审核 + * @return 结果 + */ + @Override + public boolean update(PlayClerkUserReviewInfoEntity entity) { + return updateById(entity); + } + + /** + * 修改店员资料审核 + * + * @param vo + * 店员资料审核对象 + */ + @Override + public void updateDataReviewState(PlayClerkUserReviewStateEditVo vo) { + PlayClerkUserReviewInfoEntity entity = this.selectPlayClerkUserReviewInfoById(vo.getId()); + PlayClerkUserInfoEntity userInfo = playClerkUserInfoService.selectById(entity.getClerkId()); + if ("1".equals(vo.getReviewState())) { + BeanUtils.copyProperties(entity, userInfo); + userInfo.setClerkState("1"); + userInfo.setId(entity.getClerkId()); + userInfo.setAlbum(entity.getAlbum()); + playClerkUserInfoService.update(userInfo); + clerkCommodityService.initClerkCommodity(userInfo.getId()); + } + BeanUtils.copyProperties(vo, entity); + this.update(entity); + + // 发送消息 + wxCustomMpService.sendCheckMessage(entity, userInfo, vo.getReviewState()); + } + + /** + * 批量删除店员资料审核 + * + * @param ids + * 需要删除的店员资料审核主键 + * @return 结果 + */ + @Override + public int deletePlayClerkUserReviewInfoByIds(String[] ids) { + return playClerkUserReviewInfoMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除店员资料审核信息 + * + * @param id + * 店员资料审核主键 + * @return 结果 + */ + @Override + public int deletePlayClerkUserReviewInfoById(String id) { + return playClerkUserReviewInfoMapper.deleteById(id); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/service/impl/PlayClerkWagesDetailsInfoServiceImpl.java --- +package com.starry.admin.modules.clerk.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.starry.admin.modules.clerk.mapper.PlayClerkWagesDetailsInfoMapper; +import com.starry.admin.modules.clerk.module.entity.PlayClerkWagesDetailsInfoEntity; +import com.starry.admin.modules.clerk.service.IPlayClerkWagesDetailsInfoService; +import com.starry.common.utils.IdUtils; +import java.util.Arrays; +import java.util.List; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 店员工资明细信息Service业务层处理 + * + * @author admin + * @since 2024-05-31 + */ +@Service +public class PlayClerkWagesDetailsInfoServiceImpl + extends + ServiceImpl + implements + IPlayClerkWagesDetailsInfoService { + @Resource + private PlayClerkWagesDetailsInfoMapper playClerkWagesDetailsInfoMapper; + + @Override + public PlayClerkWagesDetailsInfoEntity selectByClerkIdAndWagesId(String wagesId, String clerkId) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayClerkWagesDetailsInfoEntity::getWagesId, wagesId); + lambdaQueryWrapper.eq(PlayClerkWagesDetailsInfoEntity::getClerkId, clerkId); + return this.baseMapper.selectOne(lambdaQueryWrapper); + } + + @Override + public PlayClerkWagesDetailsInfoEntity selectByOrderId(String orderId) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayClerkWagesDetailsInfoEntity::getOrderId, orderId); + return this.baseMapper.selectOne(lambdaQueryWrapper); + } + + /** + * 查询店员工资明细信息 + * + * @param id + * 店员工资明细信息主键 + * @return 店员工资明细信息 + */ + @Override + public PlayClerkWagesDetailsInfoEntity selectPlayClerkWagesDetailsInfoById(String id) { + return this.baseMapper.selectById(id); + } + + @Override + public List selectByWagesId(String wagesId) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayClerkWagesDetailsInfoEntity::getWagesId, wagesId); + return this.baseMapper.selectList(lambdaQueryWrapper); + } + + /** + * 查询店员工资明细信息列表 + * + * @param playClerkWagesDetailsInfo + * 店员工资明细信息 + * @return 店员工资明细信息 + */ + @Override + public IPage selectPlayClerkWagesDetailsInfoByPage( + PlayClerkWagesDetailsInfoEntity playClerkWagesDetailsInfo) { + Page page = new Page<>(1, 10); + return this.baseMapper.selectPage(page, new LambdaQueryWrapper<>()); + } + + /** + * 新增店员工资明细信息 + * + * @param playClerkWagesDetailsInfo + * 店员工资明细信息 + * @return 结果 + */ + @Override + public boolean create(PlayClerkWagesDetailsInfoEntity playClerkWagesDetailsInfo) { + if (StrUtil.isBlankIfStr(playClerkWagesDetailsInfo.getId())) { + playClerkWagesDetailsInfo.setId(IdUtils.getUuid()); + } + return save(playClerkWagesDetailsInfo); + } + + /** + * 修改店员工资明细信息 + * + * @param playClerkWagesDetailsInfo + * 店员工资明细信息 + * @return 结果 + */ + @Override + public boolean update(PlayClerkWagesDetailsInfoEntity playClerkWagesDetailsInfo) { + return updateById(playClerkWagesDetailsInfo); + } + + /** + * 批量删除店员工资明细信息 + * + * @param ids + * 需要删除的店员工资明细信息主键 + * @return 结果 + */ + @Override + public int deletePlayClerkWagesDetailsInfoByIds(String[] ids) { + return playClerkWagesDetailsInfoMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除店员工资明细信息信息 + * + * @param id + * 店员工资明细信息主键 + * @return 结果 + */ + @Override + public int deletePlayClerkWagesDetailsInfoById(String id) { + return playClerkWagesDetailsInfoMapper.deleteById(id); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/service/impl/PlayClerkWagesInfoServiceImpl.java --- +package com.starry.admin.modules.clerk.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.github.yulichang.wrapper.MPJLambdaWrapper; +import com.starry.admin.modules.clerk.mapper.PlayClerkWagesInfoMapper; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity; +import com.starry.admin.modules.clerk.module.entity.PlayClerkWagesInfoEntity; +import com.starry.admin.modules.clerk.module.vo.PlayClerkWagesInfoQueryVo; +import com.starry.admin.modules.clerk.module.vo.PlayClerkWagesInfoReturnVo; +import com.starry.admin.modules.clerk.service.IPlayClerkWagesInfoService; +import com.starry.admin.modules.personnel.service.IPlayPersonnelGroupInfoService; +import com.starry.admin.utils.SecurityUtils; +import com.starry.common.utils.IdUtils; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.Arrays; +import java.util.List; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 店员工资结算信息Service业务层处理 + * + * @author admin + * @since 2024-05-31 + */ +@Service +public class PlayClerkWagesInfoServiceImpl extends ServiceImpl + implements + IPlayClerkWagesInfoService { + @Resource + private PlayClerkWagesInfoMapper playClerkWagesInfoMapper; + + @Resource + private IPlayPersonnelGroupInfoService playClerkGroupInfoService; + + @Override + public PlayClerkWagesInfoEntity selectCurrentPeriodWagesByClerkId(String clerkId) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayClerkWagesInfoEntity::getClerkId, clerkId); + lambdaQueryWrapper.eq(PlayClerkWagesInfoEntity::getHistoricalStatistics, "0"); + return this.baseMapper.selectOne(lambdaQueryWrapper); + } + + @Override + public List selectHistoricalWagesByClerkId(String clerkId) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayClerkWagesInfoEntity::getClerkId, clerkId); + lambdaQueryWrapper.eq(PlayClerkWagesInfoEntity::getHistoricalStatistics, "1"); + return this.baseMapper.selectList(lambdaQueryWrapper); + } + + @Override + public PlayClerkWagesInfoEntity getLastSettlement(String clerkId) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayClerkWagesInfoEntity::getClerkId, clerkId); + lambdaQueryWrapper.eq(PlayClerkWagesInfoEntity::getHistoricalStatistics, "0"); + lambdaQueryWrapper.orderByDesc(PlayClerkWagesInfoEntity::getEndCountDate); + return this.baseMapper.selectOne(lambdaQueryWrapper); + } + + @Override + public LocalDate getLastSettlementTime(String clerkId) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayClerkWagesInfoEntity::getClerkId, clerkId); + lambdaQueryWrapper.eq(PlayClerkWagesInfoEntity::getHistoricalStatistics, "1"); + lambdaQueryWrapper.orderByDesc(PlayClerkWagesInfoEntity::getEndCountDate); + PlayClerkWagesInfoEntity entity = this.baseMapper.selectOne(lambdaQueryWrapper); + if (entity == null) { + return LocalDate.of(2000, 1, 1); + } + return entity.getEndCountDate(); + } + + @Override + public IPage selectHistoricalByPage(PlayClerkWagesInfoQueryVo vo) { + MPJLambdaWrapper lambdaWrapper = new MPJLambdaWrapper<>(); + lambdaWrapper.selectAll(PlayClerkWagesInfoEntity.class); + // 拼接店员表 + lambdaWrapper.selectAs(PlayClerkUserInfoEntity::getNickname, "clerkNickname"); + lambdaWrapper.leftJoin(PlayClerkUserInfoEntity.class, PlayClerkUserInfoEntity::getId, + PlayClerkWagesInfoEntity::getClerkId); + if (StrUtil.isNotBlank(vo.getGroupId())) { + lambdaWrapper.eq(PlayClerkUserInfoEntity::getGroupId, vo.getGroupId()); + } + if (StrUtil.isNotBlank(vo.getListingState())) { + lambdaWrapper.eq(PlayClerkUserInfoEntity::getListingState, vo.getListingState()); + } + if (StrUtil.isNotBlank(vo.getClerkId())) { + lambdaWrapper.eq(PlayClerkUserInfoEntity::getId, vo.getClerkId()); + } + if (StrUtil.isNotEmpty(vo.getSettlementDate())) { + if (vo.getSettlementDate().contains("T")) { + vo.setSettlementDate(vo.getSettlementDate().substring(0, vo.getSettlementDate().indexOf("T"))); + } + lambdaWrapper.eq(PlayClerkWagesInfoEntity::getSettlementDate, + LocalDate.parse(vo.getSettlementDate(), DateTimeFormatter.ofPattern("yyyy-MM-dd"))); + } + lambdaWrapper.eq(PlayClerkWagesInfoEntity::getHistoricalStatistics, "1"); + // 加入组员的筛选 + List clerkIdList = playClerkGroupInfoService.getValidClerkIdList(SecurityUtils.getLoginUser(), null); + lambdaWrapper.in(PlayClerkUserInfoEntity::getId, clerkIdList); + return this.baseMapper.selectJoinPage(new Page<>(vo.getPageNum(), vo.getPageSize()), + PlayClerkWagesInfoReturnVo.class, lambdaWrapper); + } + + /** + * 查询店员工资结算信息 + * + * @param id + * 店员工资结算信息主键 + * @return 店员工资结算信息 + */ + @Override + public PlayClerkWagesInfoEntity selectPlayClerkWagesInfoById(String id) { + return this.baseMapper.selectById(id); + } + + /** + * 查询店员工资结算信息列表 + * + * @param playClerkWagesInfo + * 店员工资结算信息 + * @return 店员工资结算信息 + */ + @Override + public IPage selectPlayClerkWagesInfoByPage(PlayClerkWagesInfoEntity playClerkWagesInfo) { + Page page = new Page<>(1, 10); + return this.baseMapper.selectPage(page, new LambdaQueryWrapper<>()); + } + + /** + * 新增店员工资结算信息 + * + * @param playClerkWagesInfo + * 店员工资结算信息 + * @return 结果 + */ + @Override + public boolean create(PlayClerkWagesInfoEntity playClerkWagesInfo) { + if (StrUtil.isBlankIfStr(playClerkWagesInfo.getId())) { + playClerkWagesInfo.setId(IdUtils.getUuid()); + } + return save(playClerkWagesInfo); + } + + /** + * 修改店员工资结算信息 + * + * @param playClerkWagesInfo + * 店员工资结算信息 + * @return 结果 + */ + @Override + public boolean update(PlayClerkWagesInfoEntity playClerkWagesInfo) { + return updateById(playClerkWagesInfo); + } + + /** + * 批量删除店员工资结算信息 + * + * @param ids + * 需要删除的店员工资结算信息主键 + * @return 结果 + */ + @Override + public int deletePlayClerkWagesInfoByIds(String[] ids) { + return playClerkWagesInfoMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除店员工资结算信息信息 + * + * @param id + * 店员工资结算信息主键 + * @return 结果 + */ + @Override + public int deletePlayClerkWagesInfoById(String id) { + return playClerkWagesInfoMapper.deleteById(id); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/clerk/service/impl/PlayCustomArticleInfoServiceImpl.java --- +package com.starry.admin.modules.clerk.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.starry.admin.modules.clerk.mapper.PlayCustomArticleInfoMapper; +import com.starry.admin.modules.clerk.module.entity.PlayCustomArticleInfoEntity; +import com.starry.admin.modules.clerk.service.IPlayCustomArticleInfoService; +import com.starry.common.utils.IdUtils; +import java.util.Arrays; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 陪聊点赞动态信息Service业务层处理 + * + * @author admin + * @since 2024-05-04 + */ +@Service +public class PlayCustomArticleInfoServiceImpl + extends + ServiceImpl + implements + IPlayCustomArticleInfoService { + @Resource + private PlayCustomArticleInfoMapper playCustomArticleInfoMapper; + + @Override + public PlayCustomArticleInfoEntity selectByArticleId(String articleId, String customId, String endorseType) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayCustomArticleInfoEntity::getArticleId, articleId); + lambdaQueryWrapper.eq(PlayCustomArticleInfoEntity::getCustomId, customId); + lambdaQueryWrapper.eq(PlayCustomArticleInfoEntity::getEndorseType, endorseType); + return this.baseMapper.selectOne(lambdaQueryWrapper); + } + + /** + * 查询陪聊点赞动态信息 + * + * @param id + * 陪聊点赞动态信息主键 + * @return 陪聊点赞动态信息 + */ + @Override + public PlayCustomArticleInfoEntity selectPlayCustomArticleInfoById(String id) { + return this.baseMapper.selectById(id); + } + + /** + * 查询陪聊点赞动态信息列表 + * + * @param playCustomArticleInfo + * 陪聊点赞动态信息 + * @return 陪聊点赞动态信息 + */ + @Override + public IPage selectPlayCustomArticleInfoByPage( + PlayCustomArticleInfoEntity playCustomArticleInfo) { + Page page = new Page<>(1, 10); + return this.baseMapper.selectPage(page, new LambdaQueryWrapper<>()); + } + + /** + * 新增陪聊点赞动态信息 + * + * @param playCustomArticleInfo + * 陪聊点赞动态信息 + * @return 结果 + */ + @Override + public boolean create(PlayCustomArticleInfoEntity playCustomArticleInfo) { + if (StrUtil.isBlankIfStr(playCustomArticleInfo.getId())) { + playCustomArticleInfo.setId(IdUtils.getUuid()); + } + return save(playCustomArticleInfo); + } + + /** + * 修改陪聊点赞动态信息 + * + * @param playCustomArticleInfo + * 陪聊点赞动态信息 + * @return 结果 + */ + @Override + public boolean update(PlayCustomArticleInfoEntity playCustomArticleInfo) { + return updateById(playCustomArticleInfo); + } + + /** + * 批量删除陪聊点赞动态信息 + * + * @param ids + * 需要删除的陪聊点赞动态信息主键 + * @return 结果 + */ + @Override + public int deletePlayCustomArticleInfoByIds(String[] ids) { + return playCustomArticleInfoMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除陪聊点赞动态信息信息 + * + * @param id + * 陪聊点赞动态信息主键 + * @return 结果 + */ + @Override + public int deletePlayCustomArticleInfoById(String id) { + return playCustomArticleInfoMapper.deleteById(id); + } + + @Override + public void deleteByArticleId(String articleId) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayCustomArticleInfoEntity::getArticleId, articleId); + this.baseMapper.delete(lambdaQueryWrapper); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/custom/controller/PlayCustomFollowInfoController.java --- +package com.starry.admin.modules.custom.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.modules.custom.entity.PlayCustomFollowInfoEntity; +import com.starry.admin.modules.custom.service.IPlayCustomFollowInfoService; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import javax.annotation.Resource; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +/** + * 顾客关注陪聊信息Controller + * + * @author admin + * @since 2024-04-30 + */ +@Api(tags = "顾客关注管理", description = "顾客关注店员信息管理相关接口,包括查询、新增、修改和删除等操作") +@RestController +@RequestMapping("/play/follow") +public class PlayCustomFollowInfoController { + @Resource + private IPlayCustomFollowInfoService playCustomFollowInfoService; + + /** + * 查询顾客关注陪聊信息列表 + */ + @ApiOperation(value = "分页查询关注列表", notes = "分页查询顾客关注店员信息列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayCustomFollowInfoEntity.class, responseContainer = "Page")}) + @PreAuthorize("@customSs.hasPermission('play:info:list')") + @GetMapping("/list") + public R list(@ApiParam(value = "查询条件") PlayCustomFollowInfoEntity playCustomFollowInfo) { + IPage list = playCustomFollowInfoService + .selectPlayCustomFollowInfoByPage(playCustomFollowInfo); + return R.ok(list); + } + + /** + * 获取顾客关注陪聊信息详细信息 + */ + @ApiOperation(value = "获取关注详情", notes = "根据ID获取顾客关注店员详细信息") + @ApiImplicitParam(name = "id", value = "关注记录ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = PlayCustomFollowInfoEntity.class)}) + @PreAuthorize("@customSs.hasPermission('play:info:query')") + @GetMapping(value = "/{id}") + public R getInfo(@PathVariable("id") String id) { + return R.ok(playCustomFollowInfoService.selectPlayCustomFollowInfoById(id)); + } + + /** + * 新增顾客关注陪聊信息 + */ + @ApiOperation(value = "新增关注记录", notes = "创建新的顾客关注店员信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "添加失败")}) + @PreAuthorize("@customSs.hasPermission('play:info:create')") + @Log(title = "顾客关注陪聊信息", businessType = BusinessType.INSERT) + @PostMapping("/create") + public R create( + @ApiParam(value = "关注信息", required = true) @RequestBody PlayCustomFollowInfoEntity playCustomFollowInfo) { + boolean success = playCustomFollowInfoService.create(playCustomFollowInfo); + if (success) { + return R.ok(); + } + return R.error("添加失败"); + } + + /** + * 修改顾客关注陪聊信息 + */ + @ApiOperation(value = "修改关注记录", notes = "根据ID修改顾客关注店员信息") + @ApiImplicitParam(name = "id", value = "关注记录ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败")}) + @PreAuthorize("@customSs.hasPermission('play:info:edit')") + @Log(title = "顾客关注陪聊信息", businessType = BusinessType.UPDATE) + @PostMapping(value = "/update/{id}") + public R update(@PathVariable String id, + @ApiParam(value = "关注信息", required = true) @RequestBody PlayCustomFollowInfoEntity playCustomFollowInfo) { + playCustomFollowInfo.setId(id); + boolean success = playCustomFollowInfoService.update(playCustomFollowInfo); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + /** + * 删除顾客关注陪聊信息 + */ + @ApiOperation(value = "删除关注记录", notes = "根据ID批量删除顾客关注店员信息") + @ApiImplicitParam(name = "ids", value = "关注记录ID数组", required = true, paramType = "path", dataType = "String[]", example = "1,2,3") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Integer.class)}) + @PreAuthorize("@customSs.hasPermission('play:info:remove')") + @Log(title = "顾客关注陪聊信息", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@PathVariable String[] ids) { + return R.ok(playCustomFollowInfoService.deletePlayCustomFollowInfoByIds(ids)); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/custom/controller/PlayCustomGiftInfoController.java --- +package com.starry.admin.modules.custom.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.modules.custom.module.entity.PlayCustomGiftInfoEntity; +import com.starry.admin.modules.custom.service.IPlayCustomGiftInfoService; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import javax.annotation.Resource; +import org.springframework.web.bind.annotation.*; + +/** + * 顾客和礼物关系Controller + * + * @author admin + * @since 2024-06-05 + */ +@Api(tags = "顾客礼物管理", description = "顾客与礼物关系管理相关接口,包括查询、新增、修改和删除等操作") +@RestController +@RequestMapping("/custom/giff") +public class PlayCustomGiftInfoController { + @Resource + private IPlayCustomGiftInfoService playCustomGiftInfoService; + + /** + * 查询顾客和礼物关系列表 + */ + @ApiOperation(value = "分页查询礼物列表", notes = "分页查询顾客与礼物关系列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayCustomGiftInfoEntity.class, responseContainer = "Page")}) + @GetMapping("/list") + public R list(@ApiParam(value = "查询条件") PlayCustomGiftInfoEntity playCustomGiftInfo) { + IPage list = playCustomGiftInfoService + .selectPlayCustomGiftInfoByPage(playCustomGiftInfo); + return R.ok(list); + } + + /** + * 获取顾客和礼物关系详细信息 + */ + @ApiOperation(value = "获取礼物详情", notes = "根据ID获取顾客与礼物关系详细信息") + @ApiImplicitParam(name = "id", value = "礼物关系ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = PlayCustomGiftInfoEntity.class)}) + @GetMapping(value = "/{id}") + public R getInfo(@PathVariable("id") String id) { + return R.ok(playCustomGiftInfoService.selectPlayCustomGiftInfoById(id)); + } + + /** + * 新增顾客和礼物关系 + */ + @ApiOperation(value = "新增礼物关系", notes = "创建新的顾客与礼物关系信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "添加失败")}) + @Log(title = "顾客和礼物关系", businessType = BusinessType.INSERT) + @PostMapping("/create") + public R create( + @ApiParam(value = "礼物关系信息", required = true) @RequestBody PlayCustomGiftInfoEntity playCustomGiftInfo) { + boolean success = playCustomGiftInfoService.create(playCustomGiftInfo); + if (success) { + return R.ok(); + } + return R.error("添加失败"); + } + + /** + * 修改顾客和礼物关系 + */ + @ApiOperation(value = "修改礼物关系", notes = "根据ID修改顾客与礼物关系信息") + @ApiImplicitParam(name = "id", value = "礼物关系ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败")}) + @Log(title = "顾客和礼物关系", businessType = BusinessType.UPDATE) + @PostMapping(value = "/update/{id}") + public R update(@PathVariable String id, + @ApiParam(value = "礼物关系信息", required = true) @RequestBody PlayCustomGiftInfoEntity playCustomGiftInfo) { + playCustomGiftInfo.setId(id); + boolean success = playCustomGiftInfoService.update(playCustomGiftInfo); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + /** + * 删除顾客和礼物关系 + */ + @ApiOperation(value = "删除礼物关系", notes = "根据ID批量删除顾客与礼物关系信息") + @ApiImplicitParam(name = "ids", value = "礼物关系ID数组", required = true, paramType = "path", dataType = "String[]", example = "1,2,3") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Integer.class)}) + @Log(title = "顾客和礼物关系", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@PathVariable String[] ids) { + return R.ok(playCustomGiftInfoService.deletePlayCustomGiftInfoByIds(ids)); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/custom/controller/PlayCustomLeaveMsgController.java --- +package com.starry.admin.modules.custom.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.modules.custom.module.entity.PlayCustomLeaveMsgEntity; +import com.starry.admin.modules.custom.module.vo.PlayCustomLeaveMsgQueryVo; +import com.starry.admin.modules.custom.module.vo.PlayCustomLeaveMsgReturnVo; +import com.starry.admin.modules.custom.service.IPlayCustomLeaveMsgService; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 顾客留言Controller + * + * @author admin + * @since 2024-05-07 + */ +@Api(tags = "顾客留言管理", description = "顾客留言信息管理相关接口,包括查询、新增、修改和删除等操作") +@RestController +@RequestMapping("/custom/leave") +public class PlayCustomLeaveMsgController { + @Resource + private IPlayCustomLeaveMsgService playCustomLeaveMsgService; + + /** + * 分页查询顾客留言列表 + */ + @ApiOperation(value = "分页查询留言列表", notes = "分页查询顾客留言信息列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayCustomLeaveMsgReturnVo.class, responseContainer = "Page")}) + @PostMapping("/listByPage") + public R list(@ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayCustomLeaveMsgQueryVo vo) { + IPage list = playCustomLeaveMsgService.selectByPage(vo); + return R.ok(list); + } + + /** + * 获取顾客留言详细信息 + */ + @ApiOperation(value = "获取留言详情", notes = "根据ID获取顾客留言详细信息") + @ApiImplicitParam(name = "id", value = "留言ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = PlayCustomLeaveMsgEntity.class)}) + @GetMapping(value = "/{id}") + public R getInfo(@PathVariable("id") String id) { + return R.ok(playCustomLeaveMsgService.selectPlayCustomLeaveMsgById(id)); + } + + /** + * 新增顾客留言 + */ + @ApiOperation(value = "新增留言", notes = "创建新的顾客留言信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "添加失败")}) + // @PreAuthorize("@customSs.hasPermission('custom:leave:add')") + @Log(title = "顾客留言", businessType = BusinessType.INSERT) + @PostMapping("/create") + public R create( + @ApiParam(value = "留言信息", required = true) @RequestBody PlayCustomLeaveMsgEntity playCustomLeaveMsg) { + boolean success = playCustomLeaveMsgService.create(playCustomLeaveMsg); + if (success) { + return R.ok(); + } + return R.error("添加失败"); + } + + /** + * 修改顾客留言 + */ + @ApiOperation(value = "修改留言", notes = "根据ID修改顾客留言信息") + @ApiImplicitParam(name = "id", value = "留言ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败")}) + // @PreAuthorize("@customSs.hasPermission('custom:leave:update')") + @Log(title = "顾客留言", businessType = BusinessType.UPDATE) + @PostMapping(value = "/update/{id}") + public R update(@PathVariable String id, + @ApiParam(value = "留言信息", required = true) @RequestBody PlayCustomLeaveMsgEntity playCustomLeaveMsg) { + playCustomLeaveMsg.setId(id); + boolean success = playCustomLeaveMsgService.update(playCustomLeaveMsg); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + /** + * 删除顾客留言 + */ + @ApiOperation(value = "删除留言", notes = "根据ID批量删除顾客留言信息") + @ApiImplicitParam(name = "ids", value = "留言ID数组", required = true, paramType = "path", dataType = "String[]", example = "1,2,3") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Integer.class)}) + // @PreAuthorize("@customSs.hasPermission('custom:leave:delete')") + @Log(title = "顾客留言", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@PathVariable String[] ids) { + return R.ok(playCustomLeaveMsgService.deletePlayCustomLeaveMsgByIds(ids)); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/custom/controller/PlayCustomLevelInfoController.java --- +package com.starry.admin.modules.custom.controller; + +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.custom.module.entity.PlayCustomLevelInfoEntity; +import com.starry.admin.modules.custom.module.vo.PlayCustomLevelAddVo; +import com.starry.admin.modules.custom.module.vo.PlayCustomLevelEditVo; +import com.starry.admin.modules.custom.module.vo.PlayCustomLevelReturnVo; +import com.starry.admin.modules.custom.service.IPlayCustomLevelInfoService; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import com.starry.common.utils.ConvertUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.util.List; +import javax.annotation.Resource; +import org.springframework.web.bind.annotation.*; + +/** + * 顾客等级Controller + * + * @author admin + * @since 2024-05-04 + */ +@RestController +@RequestMapping("/custom/level") +@Api(tags = "顾客等级管理", description = "顾客等级信息管理相关接口,包括查询、新增、修改和删除等操作") +public class PlayCustomLevelInfoController { + @Resource + private IPlayCustomLevelInfoService playCustomLevelInfoService; + + /** + * 查询顾客等级列表 + */ + @PostMapping("/listAll") + @ApiOperation(value = "查询等级列表", notes = "获取所有顾客等级信息列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayCustomLevelReturnVo.class, responseContainer = "List")}) + public R listAll() { + List list = playCustomLevelInfoService.selectPlayCustomLevelInfoByPage(); + return R.ok(ConvertUtil.entityToVoList(list, PlayCustomLevelReturnVo.class)); + } + + /** + * 获取顾客等级详细信息 + */ + @GetMapping(value = "/{id}") + @ApiOperation(value = "获取等级详情", notes = "根据ID获取顾客等级详细信息") + @ApiImplicitParam(name = "id", value = "等级ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = PlayCustomLevelInfoEntity.class)}) + public R getInfo(@PathVariable("id") String id) { + return R.ok(playCustomLevelInfoService.selectPlayCustomLevelInfoById(id)); + } + + /** + * 新增顾客等级 + */ + // @PreAuthorize("@customSs.hasPermission('custom:level:add')") + @Log(title = "店员等级", businessType = BusinessType.INSERT) + @PostMapping("/create") + @ApiOperation(value = "新增等级", notes = "创建新的顾客等级信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "添加失败")}) + public R create(@ApiParam(value = "等级信息", required = true) @RequestBody PlayCustomLevelAddVo vo) { + PlayCustomLevelInfoEntity entity = ConvertUtil.entityToVo(vo, PlayCustomLevelInfoEntity.class); + int level = playCustomLevelInfoService.selectMaxLevel(); + entity.setLevel(level + 1); + boolean success = playCustomLevelInfoService.create(entity); + if (success) { + return R.ok(); + } + return R.error("添加失败"); + } + + /** + * 修改顾客等级 + */ + // @PreAuthorize("@customSs.hasPermission('custom:level:update')") + @Log(title = "顾客等级", businessType = BusinessType.UPDATE) + @PostMapping(value = "/update") + @ApiOperation(value = "修改等级", notes = "修改顾客等级信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败"), + @ApiResponse(code = 400, message = "对象不存在")}) + public R update(@ApiParam(value = "等级信息", required = true) @RequestBody PlayCustomLevelEditVo vo) { + if (playCustomLevelInfoService.selectPlayCustomLevelInfoById(vo.getId()) == null) { + throw new CustomException("对象不存在"); + } + PlayCustomLevelInfoEntity entity = ConvertUtil.entityToVo(vo, PlayCustomLevelInfoEntity.class); + boolean success = playCustomLevelInfoService.update(entity); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + /** + * 删除店员等级 + */ + @Log(title = "店员等级", businessType = BusinessType.DELETE) + @DeleteMapping("delMaxLevel") + @ApiOperation(value = "删除最高等级", notes = "删除系统中的最高等级") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 400, message = "最后一级,不允许删除")}) + public R remove() { + int level = playCustomLevelInfoService.selectMaxLevel(); + if (level <= 1) { + throw new CustomException("最后一级,不允许删除"); + } + playCustomLevelInfoService.delMaxLevelByLevel(level); + return R.ok(); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/custom/controller/PlayCustomRankingController.java --- +package com.starry.admin.modules.custom.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.modules.custom.module.vo.PlayCustomRankingQueryVo; +import com.starry.admin.modules.custom.module.vo.PlayCustomRankingReturnVo; +import com.starry.admin.modules.custom.service.IPlayCustomUserInfoService; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 顾客Controller + * + * @author admin + * @since 2024-04-08 + */ +@Api(tags = "顾客排名管理", description = "顾客消费排名相关接口,包括查询排名列表等操作") +@RestController +@RequestMapping("/custom/ranking") +public class PlayCustomRankingController { + @Resource + private IPlayCustomUserInfoService playCustomUserInfoService; + + /** + * 查询顾客排名列表 + */ + @ApiOperation(value = "分页查询排名列表", notes = "分页查询顾客消费排名信息列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayCustomRankingReturnVo.class, responseContainer = "Page")}) + @PostMapping("/listByPage") + public R list(@ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayCustomRankingQueryVo vo) { + IPage list = playCustomUserInfoService.selectRankingByPage(vo); + return R.ok(list); + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/custom/controller/PlayCustomUserInfoController.java --- +package com.starry.admin.modules.custom.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.modules.custom.module.entity.PlayCustomUserInfoEntity; +import com.starry.admin.modules.custom.module.vo.PlayCustomUserQueryVo; +import com.starry.admin.modules.custom.module.vo.PlayCustomUserReturnVo; +import com.starry.admin.modules.custom.module.vo.PlayCustomUserStateEditVo; +import com.starry.admin.modules.custom.service.IPlayCustomUserInfoService; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import com.starry.common.utils.ConvertUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 顾客Controller + * + * @author admin + * @since 2024-04-08 + */ +@Api(tags = "顾客管理", description = "顾客信息管理相关接口,包括查询、新增、修改和删除等操作") +@RestController +@RequestMapping("/custom/user") +public class PlayCustomUserInfoController { + @Resource + private IPlayCustomUserInfoService playCustomUserInfoService; + + /** + * 查询顾客列表 + */ + @ApiOperation(value = "分页查询顾客列表", notes = "分页查询顾客信息列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayCustomUserReturnVo.class, responseContainer = "Page")}) + @PostMapping("/listByPage") + public R list(@ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayCustomUserQueryVo vo) { + IPage list = playCustomUserInfoService.selectByPage(vo); + return R.ok(list); + } + + /** + * 获取顾客详细信息 + */ + @ApiOperation(value = "获取顾客详情", notes = "根据ID获取顾客详细信息") + @ApiImplicitParam(name = "id", value = "顾客ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = PlayCustomUserInfoEntity.class)}) + @GetMapping(value = "/{id}") + public R getInfo(@PathVariable("id") String id) { + return R.ok(playCustomUserInfoService.selectById(id)); + } + + /** + * 新增顾客 + */ + @ApiOperation(value = "新增顾客", notes = "创建新的顾客信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "添加失败")}) + @Log(title = "顾客", businessType = BusinessType.INSERT) + @PostMapping("/create") + public R create( + @ApiParam(value = "顾客信息", required = true) @RequestBody PlayCustomUserInfoEntity playCustomUserInfo) { + boolean success = playCustomUserInfoService.create(playCustomUserInfo); + if (success) { + return R.ok(); + } + return R.error("添加失败"); + } + + /** + * 修改顾客状态 + */ + @ApiOperation(value = "修改顾客状态", notes = "修改顾客的状态信息,如黑名单状态、关注状态等") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败")}) + @Log(title = "顾客", businessType = BusinessType.UPDATE) + @PostMapping(value = "/updateState") + public R updateState( + @ApiParam(value = "顾客状态信息", required = true) @Validated @RequestBody PlayCustomUserStateEditVo vo) { + PlayCustomUserInfoEntity entity = ConvertUtil.entityToVo(vo, PlayCustomUserInfoEntity.class); + boolean success = playCustomUserInfoService.update(entity); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + /** + * 修改顾客 + */ + @ApiOperation(value = "修改顾客信息", notes = "根据ID修改顾客基本信息") + @ApiImplicitParam(name = "id", value = "顾客ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败")}) + @Log(title = "顾客", businessType = BusinessType.UPDATE) + @PostMapping(value = "/update/{id}") + public R update(@PathVariable String id, + @ApiParam(value = "顾客信息", required = true) @RequestBody PlayCustomUserInfoEntity playCustomUserInfo) { + playCustomUserInfo.setId(id); + boolean success = playCustomUserInfoService.update(playCustomUserInfo); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + /** + * 删除顾客 + */ + @ApiOperation(value = "删除顾客", notes = "根据ID批量删除顾客信息") + @ApiImplicitParam(name = "ids", value = "顾客ID数组", required = true, paramType = "path", dataType = "String[]", example = "1,2,3") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Integer.class)}) + @Log(title = "顾客", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@PathVariable String[] ids) { + return R.ok(playCustomUserInfoService.deletePlayCustomUserInfoByIds(ids)); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/custom/entity/PlayCustomFollowInfoEntity.java --- +package com.starry.admin.modules.custom.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.common.domain.BaseEntity; +import java.util.Date; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 顾客关注陪聊信息对象 play_custom_follow_info + * + * @author admin + * @since 2024-04-30 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("play_custom_follow_info") +public class PlayCustomFollowInfoEntity extends BaseEntity { + + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 顾客ID + */ + private String customId; + + /** + * 陪聊ID + */ + private String clerkId; + + /** + * 关注时间 + */ + private Date followTime; + + /** + * 取消关注时间 + */ + private Date unfollowTime; + + /** + * 关注状态[0:未关注,1:已关注] + */ + private String followState; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/custom/mapper/PlayCustomFollowInfoMapper.java --- +package com.starry.admin.modules.custom.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.starry.admin.modules.custom.entity.PlayCustomFollowInfoEntity; + +/** + * 顾客关注陪聊信息Mapper接口 + * + * @author admin + * @since 2024-04-30 + */ +public interface PlayCustomFollowInfoMapper extends MPJBaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/custom/mapper/PlayCustomGiftInfoMapper.java --- +package com.starry.admin.modules.custom.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.starry.admin.modules.custom.module.entity.PlayCustomGiftInfoEntity; + +/** + * 顾客和礼物关系Mapper接口 + * + * @author admin + * @since 2024-06-05 + */ +public interface PlayCustomGiftInfoMapper extends MPJBaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/custom/mapper/PlayCustomLeaveMsgMapper.java --- +package com.starry.admin.modules.custom.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.starry.admin.modules.custom.module.entity.PlayCustomLeaveMsgEntity; + +/** + * 顾客留言Mapper接口 + * + * @author admin + * @since 2024-05-07 + */ +public interface PlayCustomLeaveMsgMapper extends MPJBaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/custom/mapper/PlayCustomLevelInfoMapper.java --- +package com.starry.admin.modules.custom.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.starry.admin.modules.custom.module.entity.PlayCustomLevelInfoEntity; + +/** + * 顾客等级Mapper接口 + * + * @author admin + * @since 2024-05-04 + */ +public interface PlayCustomLevelInfoMapper extends BaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/custom/mapper/PlayCustomUserInfoMapper.java --- +package com.starry.admin.modules.custom.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.starry.admin.modules.custom.module.entity.PlayCustomUserInfoEntity; + +/** + * 顾客Mapper接口 + * + * @author admin + * @since 2024-04-08 + */ +public interface PlayCustomUserInfoMapper extends MPJBaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/custom/module/entity/PlayCustomGiftInfoEntity.java --- +package com.starry.admin.modules.custom.module.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.common.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 顾客和礼物关系对象 play_custom_gift_info + * + * @author admin + * @since 2024-06-05 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("play_custom_gift_info") +public class PlayCustomGiftInfoEntity extends BaseEntity { + + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 顾客ID + */ + private String customId; + + /** + * 礼物ID + */ + private String giffId; + + /** + * 礼物数量 + */ + private Long giffNumber; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/custom/module/entity/PlayCustomLeaveMsgEntity.java --- +package com.starry.admin.modules.custom.module.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.admin.common.conf.StringTypeHandler; +import com.starry.common.domain.BaseEntity; +import java.util.Date; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 顾客留言对象 play_custom_leave_msg + * + * @author admin + * @since 2024-05-07 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName(value = "play_custom_leave_msg", autoResultMap = true) +public class PlayCustomLeaveMsgEntity extends BaseEntity { + + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 顾客ID + */ + private String customId; + + /** + * 留言内容 + */ + private String content; + + /** + * 图片 + */ + @TableField(typeHandler = StringTypeHandler.class) + private List images; + + /** + * 留言时间 + */ + private Date msgTime; + + /** + * 备注 + */ + private String remark; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/custom/module/entity/PlayCustomLevelInfoEntity.java --- +package com.starry.admin.modules.custom.module.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.common.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 顾客等级对象 play_custom_level_info + * + * @author admin + * @since 2024-05-04 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("play_custom_level_info") +public class PlayCustomLevelInfoEntity extends BaseEntity { + + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 等级名称 + */ + private String name; + + /** + * 等级数字(排序字段) + */ + private Integer level; + + /** + * 上一级消费金额 + */ + private String consumptionAmount; + + /** + * 满减比例 + */ + private Integer discount; + + /** + * 头像框地址 + */ + private String avatarFrameAddress; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/custom/module/entity/PlayCustomUserInfoEntity.java --- +package com.starry.admin.modules.custom.module.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.starry.common.domain.BaseEntity; +import java.math.BigDecimal; +import java.util.Date; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 顾客对象 play_custom_user_info + * + * @author admin + * @since 2024-04-08 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("play_custom_user_info") +public class PlayCustomUserInfoEntity extends BaseEntity { + + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 用户的标识,对当前公众号唯一 + */ + private String openid; + + /** + * 用户的标识,对当前公众号唯一 + */ + private String unionid; + + /** + * 顾客昵称 + */ + private String nickname; + + /** + * 顾客性别(0:未知;1:男,2:女) + */ + private Integer sex; + + /** + * 头像 + */ + private String avatar; + + /** + * 手机号码 + */ + private String phone; + + /** + * 微信号码 + */ + private String weiChatCode; + + /** + * 等级ID + */ + private String levelId; + + /** + * 所在国家 + */ + private String country; + + /** + * 所在省份 + */ + private String province; + + /** + * 所在城市 + */ + private String city; + + /** + * 账户余额 + */ + private BigDecimal accountBalance; + + /** + * 累计充值金额 + */ + private BigDecimal accumulatedRechargeAmount; + + /** + * 累计消费金额 + */ + private BigDecimal accumulatedConsumptionAmount; + + /** + * 余额状态[0:不存在余额,1:存在余额] + */ + private String accountState; + + /** + * 关注状态[0:未关注,1:已关注] + */ + private String subscribeState; + + /** + * 黑名单状态[0:非黑名单,1:黑名单] + */ + private String blacklistState; + + /** + * 违规状态[0:未违规,1:违规] + */ + private String violationState; + + /** + * 是否下单状态[0:未下单过,1:下单过] + */ + private String purchaseState; + + /** + * 绑定手机状态[0:未绑定,1:绑定] + */ + private String mobilePhoneState; + + /** + * 实名状态【1:已实名,0:未实名】 + */ + private String realState; + + /** + * 是否必须实名【2:跟随店铺设置,1:必须实名,0:非必须实名】 + */ + private String mandatoryRealState; + + /** + * 注册时间 + */ + private Date registrationTime; + + /** + * 上次登录时间 + */ + private Date lastLoginTime; + + /** + * 首次下单时间 + */ + private Date firstPurchaseTime; + + /** + * 最后一次下单时间 + */ + private Date lastPurchaseTime; + + /** + * 隐藏等级[0:不隐藏;1:隐藏] + */ + private String hideLevelState; + + /** + * 隐藏排名[0:不隐藏;1:隐藏] + */ + private String hideRankingState; + + /** + * 备注 + */ + private String remark; + + /** + * 最近一次登录token + */ + @JsonIgnore + private String token; + + public PlayCustomUserInfoEntity() { + } + + public PlayCustomUserInfoEntity(String id, BigDecimal accountBalance) { + this.id = id; + this.accountBalance = accountBalance; + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/custom/module/vo/PlayCustomLeaveMsgQueryVo.java --- +package com.starry.admin.modules.custom.module.vo; + +import com.starry.common.domain.BasePageEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 顾客留言查询对象 + * + * @author admin + * @since 2024/5/7 16:29 + **/ +@Data +@EqualsAndHashCode(callSuper = true) +@ApiModel(value = "顾客留言查询参数", description = "查询顾客留言信息的条件参数") +public class PlayCustomLeaveMsgQueryVo extends BasePageEntity { + + @ApiModelProperty(value = "顾客ID", example = "1", notes = "特定顾客的ID") + private String customId; + + @ApiModelProperty(value = "留言内容", example = "服务很好", notes = "留言的内容,支持模糊查询") + private String content; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/custom/module/vo/PlayCustomLeaveMsgReturnVo.java --- +package com.starry.admin.modules.custom.module.vo; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.starry.admin.common.conf.StringTypeHandler; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.Date; +import java.util.List; +import lombok.Data; + +/** + * 顾客留言查询返回对象 + * + * @author admin + * @since 2024/5/7 16:29 + **/ +@Data +@ApiModel(value = "顾客留言返回数据", description = "顾客留言信息的返回数据") +public class PlayCustomLeaveMsgReturnVo { + + /** + * UUID + */ + @ApiModelProperty(value = "留言ID", example = "1") + private String id; + + /** + * 留言内容 + */ + @ApiModelProperty(value = "留言内容", example = "服务很好,希望以后再次合作") + private String content; + + /** + * 图片 + */ + @ApiModelProperty(value = "留言图片", example = "[\"https://example.com/image1.jpg\",\"https://example.com/image2.jpg\"]") + @TableField(typeHandler = StringTypeHandler.class) + private List images; + + /** + * 留言时间 + */ + @ApiModelProperty(value = "留言时间", example = "2024-01-01 12:00:00") + private Date msgTime; + + /** + * 备注 + */ + @ApiModelProperty(value = "备注", example = "重要留言") + private String remark; + + /** + * 顾客Id + */ + @ApiModelProperty(value = "顾客ID", example = "1") + private String customId; + + /** + * 顾客昵称 + */ + @ApiModelProperty(value = "顾客头像", example = "https://example.com/avatar.jpg") + private String customAvatar; + + /** + * 头像 + */ + @ApiModelProperty(value = "顾客昵称", example = "张三") + private String customNickname; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/custom/module/vo/PlayCustomLevelAddVo.java --- +package com.starry.admin.modules.custom.module.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +@ApiModel(value = "顾客等级添加参数", description = "新增顾客等级信息的请求参数") +public class PlayCustomLevelAddVo { + + /** + * 等级名称 + */ + @NotBlank(message = "等级名称不能为空") + @ApiModelProperty(value = "等级名称", required = true, example = "钻石会员", notes = "顾客等级的名称") + private String name; + + /** + * 上一级消费金额 + */ + @NotBlank(message = "消费金额不能为空") + @ApiModelProperty(value = "消费金额", required = true, example = "1000", notes = "达到该等级需要的消费金额") + private String consumptionAmount; + + /** + * 满减比例 + */ + @NotBlank(message = "满减比例不能为空") + @ApiModelProperty(value = "满减比例", required = true, example = "95", notes = "该等级享受的满减折扣比例,如95表示95折") + private Integer discount; + + /** + * 头像框地址 + */ + @ApiModelProperty(value = "头像框地址", example = "https://example.com/frame.png", notes = "该等级专属的头像框图片地址") + private String avatarFrameAddress; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/custom/module/vo/PlayCustomLevelEditVo.java --- +package com.starry.admin.modules.custom.module.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +@ApiModel(value = "顾客等级修改参数", description = "修改顾客等级信息的请求参数") +public class PlayCustomLevelEditVo { + + /** + * UUID + */ + @NotBlank(message = "ID不能为空") + @ApiModelProperty(value = "等级ID", required = true, example = "1", notes = "顾客等级的ID") + private String id; + + /** + * 等级名称 + */ + @NotBlank(message = "等级名称不能为空") + @ApiModelProperty(value = "等级名称", required = true, example = "钻石会员", notes = "顾客等级的名称") + private String name; + + /** + * 上一级消费金额 + */ + @NotBlank(message = "消费金额不能为空") + @ApiModelProperty(value = "消费金额", required = true, example = "1000", notes = "达到该等级需要的消费金额") + private String consumptionAmount; + + /** + * 满减比例 + */ + @NotBlank(message = "满减比例不能为空") + @ApiModelProperty(value = "满减比例", required = true, example = "95", notes = "该等级享受的满减折扣比例,如95表示95折") + private Integer discount; + + /** + * 头像框地址 + */ + @ApiModelProperty(value = "头像框地址", example = "https://example.com/frame.png", notes = "该等级专属的头像框图片地址") + private String avatarFrameAddress; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/custom/module/vo/PlayCustomLevelReturnVo.java --- +package com.starry.admin.modules.custom.module.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 顾客等级查询对象 + * + * @author admin + */ +@Data +@ApiModel(value = "顾客等级返回数据", description = "顾客等级信息的返回数据") +public class PlayCustomLevelReturnVo { + + /** + * UUID + */ + @ApiModelProperty(value = "等级ID", example = "1") + private String id; + /** + * 等级名称 + */ + @ApiModelProperty(value = "等级名称", example = "钻石会员") + private String name; + + /** + * 等级数字(排序字段) + */ + @ApiModelProperty(value = "等级数值", example = "3", notes = "等级数字,用于排序") + private Integer level; + + /** + * 上一级消费金额 + */ + @ApiModelProperty(value = "消费金额", example = "1000", notes = "达到该等级需要的消费金额") + private String consumptionAmount; + + /** + * 满减比例 + */ + @ApiModelProperty(value = "满减比例", example = "95", notes = "该等级享受的满减折扣比例,如95表示95折") + private Integer discount; + + /** + * 头像框地址 + */ + @ApiModelProperty(value = "头像框地址", example = "https://example.com/frame.png") + private String avatarFrameAddress; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/custom/module/vo/PlayCustomRankingQueryVo.java --- +package com.starry.admin.modules.custom.module.vo; + +import com.starry.common.domain.BasePageEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 顾客排名分页查询对象 + * + * @author admin + * @since 2024/5/14 下午7:47 + **/ +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel(value = "顾客排名查询参数", description = "查询顾客消费排名信息的条件参数") +public class PlayCustomRankingQueryVo extends BasePageEntity { + /** + * userId + */ + @ApiModelProperty(value = "顾客ID", example = "1", notes = "特定顾客的ID") + private String id; + + /** + * 下单时间 + */ + @ApiModelProperty(value = "下单时间范围", example = "['2024-01-01 00:00:00','2024-12-31 23:59:59']", notes = "下单时间范围,包含开始和结束时间") + private List purchaserTime; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/custom/module/vo/PlayCustomRankingReturnVo.java --- +package com.starry.admin.modules.custom.module.vo; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.List; +import lombok.Data; + +/** + * 顾客分页查询返回对象 + * + * @author admin + * @since 2024/5/14 下午7:47 + **/ +@Data +@ApiModel(value = "顾客排名返回数据", description = "顾客消费排名信息的返回数据") +public class PlayCustomRankingReturnVo { + /** + * UUID + */ + @ApiModelProperty(value = "顾客ID", example = "1") + private String id; + + /** + * 顾客昵称 + */ + @ApiModelProperty(value = "顾客昵称", example = "张三") + private String nickname; + + /** + * 头像 + */ + @ApiModelProperty(value = "头像", example = "https://example.com/avatar.jpg") + private String avatar; + + /** + * 排名 + */ + @ApiModelProperty(value = "排名", example = "1", notes = "顾客消费排名索引") + private Integer rankingIndex; + + /** + * 订单列表 + */ + @JsonIgnore + @ApiModelProperty(value = "订单列表", hidden = true) + private List orderInfos; + + /** + * 下单时间-起始时间 + */ + @ApiModelProperty(value = "下单起始时间", example = "2024-01-01 00:00:00") + private String beginPurchaserTime; + + /** + * 下单时间-终止时间 + */ + @ApiModelProperty(value = "下单终止时间", example = "2024-12-31 23:59:59") + private String endPurchaserTime; + + /** + * 订单总数 + */ + @ApiModelProperty(value = "订单总数", example = "10") + private String orderNumber; + + /** + * 续单总数 + */ + @ApiModelProperty(value = "续单总数", example = "5", notes = "顾客续费订单的总数量") + private String orderContinueNumber; + + /** + * 订单单价 + */ + @ApiModelProperty(value = "订单单价", example = "100.00") + private String orderPrice; + + /** + * 订单总金额 + */ + @ApiModelProperty(value = "订单总金额", example = "1000.00") + private BigDecimal orderTotalAmount; + + /** + * 统计时间 + */ + @ApiModelProperty(value = "统计时间", example = "2024-01-01") + private String statisticalTime = LocalDate.now().toString(); + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/custom/module/vo/PlayCustomUserQueryVo.java --- +package com.starry.admin.modules.custom.module.vo; + +import com.starry.common.domain.BasePageEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 顾客分页查询对象 + * + * @author admin + * @since 2024/5/14 下午7:47 + **/ +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel(value = "顾客查询参数", description = "查询顾客信息的条件参数") +public class PlayCustomUserQueryVo extends BasePageEntity { + + @ApiModelProperty(value = "顾客ID", example = "1", notes = "特定顾客的ID") + private String id; + + /** + * 用户的标识,对当前公众号唯一 + */ + @ApiModelProperty(value = "OpenID", example = "o6_bmjrPTlm6_2sgVt7hMZOPfL2M", notes = "微信用户的唯一标识") + private String openid; + + /** + * 顾客昵称 + */ + @ApiModelProperty(value = "昵称", example = "张三", notes = "顾客的昵称,支持模糊查询") + private String nickname; + + /** + * 顾客性别(0:未知;1:男,2:女) + */ + @ApiModelProperty(value = "性别", example = "1", notes = "0:未知;1:男;2:女") + private String sex; + + /** + * 微信号 + */ + @ApiModelProperty(value = "微信号", example = "zhangsan123", notes = "顾客的微信号") + private String weiChatCode; + + /** + * 绑定手机状态[0:未绑定,1:绑定] + */ + @ApiModelProperty(value = "绑定手机状态", example = "1", notes = "0:未绑定,1:绑定") + private String mobilePhoneState; + + /** + * 手机号码 + */ + @ApiModelProperty(value = "手机号码", example = "13800138000", notes = "顾客的手机号码") + private String phone; + + /** + * 等级ID + */ + @ApiModelProperty(value = "等级ID", example = "1", notes = "顾客等级的ID") + private String levelId; + + /** + * 余额状态[0:不存在余额,1:存在余额] + */ + @ApiModelProperty(value = "余额状态", example = "1", notes = "0:不存在余额,1:存在余额") + private String accountState; + + /** + * 关注状态[0:未关注,1:已关注] + */ + @ApiModelProperty(value = "关注状态", example = "1", notes = "0:未关注,1:已关注") + private String subscribeState; + + /** + * 违规状态[0:未违规,1:违规] + */ + @ApiModelProperty(value = "违规状态", example = "0", notes = "0:未违规,1:违规") + private String violationState; + + /** + * 是否下单状态[0:未下单过,1:下单过] + */ + @ApiModelProperty(value = "下单状态", example = "1", notes = "0:未下单过,1:下单过") + private String purchaseState; + + /** + * 黑名单状态[0:非黑名单,1:黑名单] + */ + @ApiModelProperty(value = "黑名单状态", example = "0", notes = "0:非黑名单,1:黑名单") + private String blacklistState; + + /** + * 注册时间 + */ + @ApiModelProperty(value = "注册时间范围", example = "['2024-01-01 00:00:00','2024-12-31 23:59:59']", notes = "注册时间范围,包含开始和结束时间") + private List registrationTime; + + /** + * 首次下单时间 + */ + @ApiModelProperty(value = "首次下单时间范围", example = "['2024-01-01 00:00:00','2024-12-31 23:59:59']", notes = "首次下单时间范围,包含开始和结束时间") + private List firstPurchaseTime; + + /** + * 最后一次下单时间 + */ + @ApiModelProperty(value = "最后下单时间范围", example = "['2024-01-01 00:00:00','2024-12-31 23:59:59']", notes = "最后一次下单时间范围,包含开始和结束时间") + private List lastPurchaseTime; + /** + * 备注 + */ + @ApiModelProperty(value = "备注", example = "重要客户", notes = "顾客相关备注信息") + private String remark; + + /** + * 排序字段 + */ + @ApiModelProperty(value = "排序字段", example = "registrationTime", notes = "排序的字段名称") + private String sort; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/custom/module/vo/PlayCustomUserReturnVo.java --- +package com.starry.admin.modules.custom.module.vo; + +import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; +import lombok.Data; + +/** + * 顾客分页查询返回对象 + * + * @author admin + * @since 2024/5/14 下午7:47 + **/ +@Data +@ApiModel(value = "顾客返回数据", description = "顾客信息的返回数据") +public class PlayCustomUserReturnVo { + /** + * UUID + */ + @ApiModelProperty(value = "顾客ID", example = "1") + private String id; + + /** + * 租户ID + */ + @ApiModelProperty(value = "租户ID", example = "tenant123", notes = "系统租户标识") + private String tenantId; + + /** + * 用户的标识,对当前公众号唯一 + */ + @ApiModelProperty(value = "OpenID", example = "o6_bmjrPTlm6_2sgVt7hMZOPfL2M", notes = "微信用户的唯一标识") + private String openid; + + /** + * 顾客昵称 + */ + @ApiModelProperty(value = "昵称", example = "张三") + private String nickname; + + /** + * 顾客性别(0:未知;1:男,2:女) + */ + @ApiModelProperty(value = "性别", example = "1", notes = "0:未知;1:男;2:女") + private Integer sex; + + /** + * 头像 + */ + @ApiModelProperty(value = "头像", example = "https://example.com/avatar.jpg") + private String avatar; + + /** + * 手机号码 + */ + @ApiModelProperty(value = "手机号码", example = "13800138000") + private String phone; + + /** + * 微信号码 + */ + @ApiModelProperty(value = "微信号", example = "zhangsan123") + private String weiChatCode; + + /** + * 所在国家 + */ + @ApiModelProperty(value = "国家", example = "中国") + private String country; + + /** + * 所在省份 + */ + @ApiModelProperty(value = "省份", example = "广东省") + private String province; + + /** + * 所在城市 + */ + @ApiModelProperty(value = "城市", example = "深圳市") + private String city; + + /** + * 账户余额 + */ + @ApiModelProperty(value = "账户余额", example = "1000.50") + private BigDecimal accountBalance; + + /** + * 余额状态[0:不存在余额,1:存在余额] + */ + @ApiModelProperty(value = "余额状态", example = "1", notes = "0:不存在余额,1:存在余额") + private String accountState; + + /** + * 关注状态[0:未关注,1:已关注] + */ + @ApiModelProperty(value = "关注状态", example = "1", notes = "0:未关注,1:已关注") + private String subscribeState; + + /** + * 黑名单状态[0:非黑名单,1:黑名单] + */ + @ApiModelProperty(value = "黑名单状态", example = "0", notes = "0:非黑名单,1:黑名单") + private String blacklistState; + + /** + * 违规状态[0:未违规,1:违规] + */ + @ApiModelProperty(value = "违规状态", example = "0", notes = "0:未违规,1:违规") + private String violationState; + + /** + * 是否下单状态[0:未下单过,1:下单过] + */ + @ApiModelProperty(value = "下单状态", example = "1", notes = "0:未下单过,1:下单过") + private String purchaseState; + + /** + * 绑定手机状态[0:未绑定,1:绑定] + */ + @ApiModelProperty(value = "绑定手机状态", example = "1", notes = "0:未绑定,1:绑定") + private String mobilePhoneState; + + /** + * 实名状态【1:已实名,0:未实名】 + */ + @ApiModelProperty(value = "实名状态", example = "1", notes = "1:已实名,0:未实名") + private String realState; + + /** + * 是否必须实名【2:跟随店铺设置,1:必须实名,0:非必须实名】 + */ + @ApiModelProperty(value = "必须实名状态", example = "1", notes = "2:跟随店铺设置,1:必须实名,0:非必须实名") + private String mandatoryRealState; + + /** + * 注册时间 + */ + @ApiModelProperty(value = "注册时间", example = "2024-01-01 12:00:00") + private Date registrationTime; + + /** + * 上次登录时间 + */ + @ApiModelProperty(value = "上次登录时间", example = "2024-01-15 12:00:00") + private Date lastLoginTime; + + /** + * 首次下单时间 + */ + @ApiModelProperty(value = "首次下单时间", example = "2024-01-05 12:00:00") + private Date firstPurchaseTime; + + /** + * 最后一次下单时间 + */ + @ApiModelProperty(value = "最后下单时间", example = "2024-01-20 12:00:00") + private Date lastPurchaseTime; + + /** + * 备注 + */ + @ApiModelProperty(value = "备注", example = "重要客户") + private String remark; + + /** + * 等级ID + */ + @ApiModelProperty(value = "等级ID", example = "1") + private String levelId; + + /** + * 等级名称 + */ + @ApiModelProperty(value = "等级名称", example = "钻石会员") + private String levelName; + + /** + * 订单列表 + */ + @ApiModelProperty(value = "订单列表", notes = "顾客的订单列表") + private List orderInfos; + /** + * 订单总数 + */ + @ApiModelProperty(value = "订单总数", example = "10") + private String orderNumber; + + /** + * 订单单价 + */ + @ApiModelProperty(value = "订单单价", example = "100.00") + private String orderPrice; + + /** + * 订单总金额 + */ + @ApiModelProperty(value = "订单总金额", example = "1000.00") + private BigDecimal orderTotalAmount; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/custom/module/vo/PlayCustomUserStateEditVo.java --- +package com.starry.admin.modules.custom.module.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +/** + * @author admin + */ +@Data +@ApiModel(value = "顾客状态修改参数", description = "修改顾客状态信息的请求参数") +public class PlayCustomUserStateEditVo { + + /** + * id + */ + @NotBlank(message = "id不能为空") + @ApiModelProperty(value = "顾客ID", required = true, example = "1", notes = "顾客的ID") + private String id; + + /** + * 余额状态[0:不存在余额,1:存在余额] + */ + @ApiModelProperty(value = "余额状态", example = "1", notes = "0:不存在余额,1:存在余额") + private String accountState; + + /** + * 关注状态[0:未关注,1:已关注] + */ + @ApiModelProperty(value = "关注状态", example = "1", notes = "0:未关注,1:已关注") + private String subscribeState; + + /** + * 黑名单状态[0:非黑名单,1:黑名单] + */ + @ApiModelProperty(value = "黑名单状态", example = "0", notes = "0:非黑名单,1:黑名单") + private String blacklistState; + + /** + * 违规状态[0:未违规,1:违规] + */ + @ApiModelProperty(value = "违规状态", example = "0", notes = "0:未违规,1:违规") + private String violationState; + + /** + * 是否下单状态[0:未未下单,1:下单过] + */ + @ApiModelProperty(value = "下单状态", example = "1", notes = "0:未下单过,1:下单过") + private String purchaseState; + + /** + * 绑定手机状态[0:未绑定,1:绑定] + */ + @ApiModelProperty(value = "绑定手机状态", example = "1", notes = "0:未绑定,1:绑定") + private String mobilePhoneState; + + /** + * 实名状态【1:已实名,0:未实名】 + */ + @ApiModelProperty(value = "实名状态", example = "1", notes = "1:已实名,0:未实名") + private String realState; + + /** + * 是否必须实名【0:非必须实名;1:必须实名;2:跟随店铺设置】 + */ + @ApiModelProperty(value = "必须实名状态", example = "1", notes = "2:跟随店铺设置,1:必须实名,0:非必须实名") + private String mandatoryRealState; + + @ApiModelProperty(value = "备注", example = "重要客户", notes = "顾客相关备注信息") + private String remark; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/custom/service/IPlayCustomFollowInfoService.java --- +package com.starry.admin.modules.custom.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.custom.entity.PlayCustomFollowInfoEntity; +import com.starry.admin.modules.weichat.entity.PlayClerkFollowQueryVo; +import com.starry.admin.modules.weichat.entity.PlayClerkFollowReturnVo; + +/** + * 顾客关注陪聊信息Service接口 + * + * @author admin + * @since 2024-04-30 + */ +public interface IPlayCustomFollowInfoService extends IService { + /** + * 查询顾客关注陪聊信息 + * + * @param id + * 顾客关注陪聊信息主键 + * @return 顾客关注陪聊信息 + */ + PlayCustomFollowInfoEntity selectPlayCustomFollowInfoById(String id); + + /** + * 修改关注状态 + * + * @param customUserId + * 顾客ID + * @param clerkUserId + * 陪聊ID + * @return 关注状态[0:未关注,1:已关注] + */ + String queryFollowState(String customUserId, String clerkUserId); + + /** + * 修改关注状态 + * + * @param customUserId + * 顾客ID + * @param clerkUserId + * 陪聊ID + * @param followState + * 关注状态[0:未关注,1:已关注] + */ + void updateFollowState(String customUserId, String clerkUserId, String followState); + + /** + * 分页查询陪聊关注状态 + * + * @param vo + * 店员关注状态 查询对象 + * @return 顾客关注陪聊信息集合 + * @author admin + * @since 2024/5/10 10:28 + **/ + IPage selectByPage(PlayClerkFollowQueryVo vo); + + /** + * 查询顾客关注陪聊信息列表 + * + * @param playCustomFollowInfo + * 顾客关注陪聊信息 + * @return 顾客关注陪聊信息集合 + */ + IPage selectPlayCustomFollowInfoByPage(PlayCustomFollowInfoEntity playCustomFollowInfo); + + /** + * 新增顾客关注陪聊信息 + * + * @param playCustomFollowInfo + * 顾客关注陪聊信息 + * @return 结果 + */ + boolean create(PlayCustomFollowInfoEntity playCustomFollowInfo); + + /** + * 修改顾客关注陪聊信息 + * + * @param playCustomFollowInfo + * 顾客关注陪聊信息 + * @return 结果 + */ + boolean update(PlayCustomFollowInfoEntity playCustomFollowInfo); + + /** + * 批量删除顾客关注陪聊信息 + * + * @param ids + * 需要删除的顾客关注陪聊信息主键集合 + * @return 结果 + */ + int deletePlayCustomFollowInfoByIds(String[] ids); + + /** + * 删除顾客关注陪聊信息信息 + * + * @param id + * 顾客关注陪聊信息主键 + * @return 结果 + */ + int deletePlayCustomFollowInfoById(String id); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/custom/service/IPlayCustomGiftInfoService.java --- +package com.starry.admin.modules.custom.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.custom.module.entity.PlayCustomGiftInfoEntity; +import java.util.List; + +/** + * 顾客和礼物关系Service接口 + * + * @author admin + * @since 2024-06-05 + */ +public interface IPlayCustomGiftInfoService extends IService { + + /** + * 根据顾客ID和礼物ID,查询当前礼物活点亮情况 + * + * @param giftId + * 礼物ID + * @param customId + * 顾客ID + * @return 物活点亮情况 + */ + PlayCustomGiftInfoEntity selectByGiftIdAndCustomId(String giftId, String customId); + + /** + * 查询顾客已点亮礼物 + * + * @param customId + * 顾客IF + * @return 顾客已点亮礼物列表 + */ + List selectBtyCustomId(String customId); + + /** + * 查询顾客和礼物关系 + * + * @param id + * 顾客和礼物关系主键 + * @return 顾客和礼物关系 + */ + PlayCustomGiftInfoEntity selectPlayCustomGiftInfoById(String id); + + /** + * 查询顾客和礼物关系列表 + * + * @param playCustomGiftInfo + * 顾客和礼物关系 + * @return 顾客和礼物关系集合 + */ + IPage selectPlayCustomGiftInfoByPage(PlayCustomGiftInfoEntity playCustomGiftInfo); + + /** + * 新增顾客和礼物关系 + * + * @param playCustomGiftInfo + * 顾客和礼物关系 + * @return 结果 + */ + boolean create(PlayCustomGiftInfoEntity playCustomGiftInfo); + + /** + * 修改顾客和礼物关系 + * + * @param playCustomGiftInfo + * 顾客和礼物关系 + * @return 结果 + */ + boolean update(PlayCustomGiftInfoEntity playCustomGiftInfo); + + /** + * 批量删除顾客和礼物关系 + * + * @param ids + * 需要删除的顾客和礼物关系主键集合 + * @return 结果 + */ + int deletePlayCustomGiftInfoByIds(String[] ids); + + /** + * 删除顾客和礼物关系信息 + * + * @param id + * 顾客和礼物关系主键 + * @return 结果 + */ + int deletePlayCustomGiftInfoById(String id); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/custom/service/IPlayCustomLeaveMsgService.java --- +package com.starry.admin.modules.custom.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.custom.module.entity.PlayCustomLeaveMsgEntity; +import com.starry.admin.modules.custom.module.vo.PlayCustomLeaveMsgQueryVo; +import com.starry.admin.modules.custom.module.vo.PlayCustomLeaveMsgReturnVo; + +/** + * 顾客留言Service接口 + * + * @author admin + * @since 2024-05-07 + */ +public interface IPlayCustomLeaveMsgService extends IService { + /** + * 查询顾客留言 + * + * @param id + * 顾客留言主键 + * @return 顾客留言 + */ + PlayCustomLeaveMsgEntity selectPlayCustomLeaveMsgById(String id); + + /** + * 查询当前用户不允许留言的原因 + * + * @param customId + * 顾客ID + * @return 没有权限原因 + */ + String queryNoMessagesAllowedReason(String customId); + + /** + * 分页查询顾客留言列表 + * + * @param vo + * 顾客留言分页查询对象 + * @return 顾客留言集合 + */ + IPage selectByPage(PlayCustomLeaveMsgQueryVo vo); + + /** + * 查询顾客留言列表 + * + * @param playCustomLeaveMsg + * 顾客留言 + * @return 顾客留言集合 + */ + IPage selectPlayCustomLeaveMsgByPage(PlayCustomLeaveMsgEntity playCustomLeaveMsg); + + /** + * 新增顾客留言 + * + * @param playCustomLeaveMsg + * 顾客留言 + * @return 结果 + */ + boolean create(PlayCustomLeaveMsgEntity playCustomLeaveMsg); + + /** + * 修改顾客留言 + * + * @param playCustomLeaveMsg + * 顾客留言 + * @return 结果 + */ + boolean update(PlayCustomLeaveMsgEntity playCustomLeaveMsg); + + /** + * 批量删除顾客留言 + * + * @param ids + * 需要删除的顾客留言主键集合 + * @return 结果 + */ + int deletePlayCustomLeaveMsgByIds(String[] ids); + + /** + * 删除顾客留言信息 + * + * @param id + * 顾客留言主键 + * @return 结果 + */ + int deletePlayCustomLeaveMsgById(String id); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/custom/service/IPlayCustomLevelInfoService.java --- +package com.starry.admin.modules.custom.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.custom.module.entity.PlayCustomLevelInfoEntity; +import com.starry.admin.modules.system.module.entity.SysTenantEntity; +import java.util.List; + +/** + * 顾客等级Service接口 + * + * @author admin + * @since 2024-05-04 + */ +public interface IPlayCustomLevelInfoService extends IService { + + /** + * 初始化顾客等级 + * + * @param sysTenantEntity + * 租户细信息 + * @author admin + * @since 2024/7/19 15:13 + **/ + void initDefaultLevel(SysTenantEntity sysTenantEntity); + + /** + * 获取新增顾客时,默认最低等级ID + * + * @return PlayCustomLevelInfoEntity + */ + PlayCustomLevelInfoEntity getDefaultLevel(); + + /** + * 查询顾客等级列表 + * + * @return 顾客等级集合 + */ + List selectAll(); + + /** + * 查询顾客等级 + * + * @param id + * 顾客等级主键 + * @return 顾客等级 + */ + PlayCustomLevelInfoEntity selectPlayCustomLevelInfoById(String id); + + /** + * 查询顾客等级列表 + * + * @return 顾客等级集合 + */ + List selectPlayCustomLevelInfoByPage(); + + /** + * 新增顾客等级 + * + * @param playCustomLevelInfo + * 顾客等级 + * @return 结果 + */ + boolean create(PlayCustomLevelInfoEntity playCustomLevelInfo); + + /** + * 修改顾客等级 + * + * @param playCustomLevelInfo + * 顾客等级 + * @return 结果 + */ + boolean update(PlayCustomLevelInfoEntity playCustomLevelInfo); + + /** + * 批量删除顾客等级 + * + * @param ids + * 需要删除的顾客等级主键集合 + * @return 结果 + */ + int deletePlayCustomLevelInfoByIds(String[] ids); + + /** + * 删除顾客等级信息 + * + * @param id + * 顾客等级主键 + * @return 结果 + */ + int deletePlayCustomLevelInfoById(String id); + + /** + * 查询最大等级 + * + * @return 最大等级 + */ + int selectMaxLevel(); + + /** + * 删除最大等级 + */ + void delMaxLevelByLevel(Integer level); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/custom/service/IPlayCustomUserInfoService.java --- +package com.starry.admin.modules.custom.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.custom.module.entity.PlayCustomUserInfoEntity; +import com.starry.admin.modules.custom.module.vo.PlayCustomRankingQueryVo; +import com.starry.admin.modules.custom.module.vo.PlayCustomRankingReturnVo; +import com.starry.admin.modules.custom.module.vo.PlayCustomUserQueryVo; +import com.starry.admin.modules.custom.module.vo.PlayCustomUserReturnVo; +import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity; +import java.math.BigDecimal; +import java.util.List; + +/** + * 顾客Service接口 + * + * @author admin + * @since 2024-04-08 + */ +public interface IPlayCustomUserInfoService extends IService { + + /** + * 查询顾客 + * + * @param openId + * 顾客主键 + * @return 顾客 + */ + PlayCustomUserInfoEntity selectByOpenid(String openId); + + /** + * 根据顾客等级,查询顾客充值余额时,实际支付金额 + * + * @param rechargeAmount + * 重置金额,单位分 + * @param customId + * 顾客ID + * @return 实际支付金额 + */ + BigDecimal getCustomPaymentAmount(BigDecimal rechargeAmount, String customId); + + /** + * 顾客账户余额充值 + * + * @param rechargeAmount + * 充值金额,单位分 + * @param customId + * 顾客ID + * @param orderId + * 订单ID + */ + void customAccountBalanceRecharge(BigDecimal rechargeAmount, String customId, String orderId); + + /** + * 查询顾客 + * + * @param id + * 顾客主键 + * @return 顾客 + */ + PlayCustomUserInfoEntity selectById(String id); + + /** + * 分页查询顾客列表 + * + * @param vo + * 顾客查询对象 + * @return 顾客集合 + */ + IPage selectByPage(PlayCustomUserQueryVo vo); + + /** + * 分页查询顾客排名列表 + * + * @param vo + * 顾客查询对象 + * @return 顾客集合 + */ + IPage selectRankingByPage(PlayCustomRankingQueryVo vo); + + /** + * 新增顾客 + * + * @param playCustomUserInfo + * 顾客 + * @return 结果 + */ + boolean create(PlayCustomUserInfoEntity playCustomUserInfo); + + /** + * 更新token + * + * @param id + * 账户余额 + * @param token + * TOKEN + * @author admin + * @since 2024/4/9 14:33 + **/ + void updateTokenById(String id, String token); + + /** + * 更新账号余额 + * + * @param id + * 用户ID + * @param accountBalance + * 账户余额 + * @author admin + * @since 2024/4/9 14:33 + **/ + void updateAccountBalanceById(String id, BigDecimal accountBalance); + + /** + * 更新顾客账户余额信息 + * + * @param userId + * 用户ID + * @param balanceBeforeOperation + * 操作前余额 + * @param balanceAfterOperation + * 操作后余额 + * @param operationType + * 操作类型(0:充值;1:消费;2:服务;3:退款) + * @param operationAction + * 操作动作 + * @param balanceMoney + * 操作金额 + * @param giftAmount + * 赠送金额 + * @param orderId + * 订单ID + */ + void updateAccountBalanceById(String userId, BigDecimal balanceBeforeOperation, BigDecimal balanceAfterOperation, + String operationType, String operationAction, BigDecimal balanceMoney, BigDecimal giftAmount, + String orderId); + + /** + * 修改顾客 + * + * @param playCustomUserInfo + * 顾客 + * @return 结果 + */ + boolean update(PlayCustomUserInfoEntity playCustomUserInfo); + + /** + * 批量删除顾客 + * + * @param ids + * 需要删除的顾客主键集合 + * @return 结果 + */ + int deletePlayCustomUserInfoByIds(String[] ids); + + /** + * 删除顾客信息 + * + * @param id + * 顾客主键 + * @return 结果 + */ + int deletePlayCustomUserInfoById(String id); + + List simpleList(); + + /** + * 保存订单信息 + * + * @param entity + * 订单实体 * @since 2024/7/18 17:13 + * @author admin + **/ + void saveOrderInfo(PlayOrderInfoEntity entity); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/custom/service/impl/PlayCustomFollowInfoServiceImpl.java --- +package com.starry.admin.modules.custom.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.github.yulichang.wrapper.MPJLambdaWrapper; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity; +import com.starry.admin.modules.custom.entity.PlayCustomFollowInfoEntity; +import com.starry.admin.modules.custom.mapper.PlayCustomFollowInfoMapper; +import com.starry.admin.modules.custom.service.IPlayCustomFollowInfoService; +import com.starry.admin.modules.weichat.entity.PlayClerkFollowQueryVo; +import com.starry.admin.modules.weichat.entity.PlayClerkFollowReturnVo; +import com.starry.common.utils.IdUtils; +import java.util.Arrays; +import java.util.Date; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 顾客关注陪聊信息Service业务层处理 + * + * @author admin + * @since 2024-04-30 + */ +@Service +public class PlayCustomFollowInfoServiceImpl extends ServiceImpl + implements + IPlayCustomFollowInfoService { + @Resource + private PlayCustomFollowInfoMapper playCustomFollowInfoMapper; + + /** + * 查询顾客关注陪聊信息 + * + * @param id + * 顾客关注陪聊信息主键 + * @return 顾客关注陪聊信息 + */ + @Override + public PlayCustomFollowInfoEntity selectPlayCustomFollowInfoById(String id) { + return this.baseMapper.selectById(id); + } + + @Override + public String queryFollowState(String customUserId, String clerkUserId) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayCustomFollowInfoEntity::getClerkId, clerkUserId); + lambdaQueryWrapper.eq(PlayCustomFollowInfoEntity::getCustomId, customUserId); + PlayCustomFollowInfoEntity entity = this.baseMapper.selectOne(lambdaQueryWrapper); + return entity == null ? "0" : entity.getFollowState(); + } + + @Override + public void updateFollowState(String customUserId, String clerkUserId, String followState) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayCustomFollowInfoEntity::getClerkId, clerkUserId); + lambdaQueryWrapper.eq(PlayCustomFollowInfoEntity::getCustomId, customUserId); + PlayCustomFollowInfoEntity entity = this.baseMapper.selectOne(lambdaQueryWrapper); + if (entity == null) { + entity = new PlayCustomFollowInfoEntity(); + entity.setCustomId(customUserId); + entity.setFollowState(followState); + entity.setClerkId(clerkUserId); + entity.setFollowTime(new Date()); + this.baseMapper.insert(entity); + } else { + entity.setFollowState(followState); + this.baseMapper.updateById(entity); + } + } + + @Override + public IPage selectByPage(PlayClerkFollowQueryVo vo) { + MPJLambdaWrapper lambdaQueryWrapper = new MPJLambdaWrapper() + // 查询主表全部字段 + .selectAll(PlayCustomFollowInfoEntity.class) + // 陪聊用户表全部字段 + .selectAll(PlayClerkUserInfoEntity.class) + // 陪聊用户表 + .leftJoin(PlayClerkUserInfoEntity.class, PlayClerkUserInfoEntity::getId, + PlayCustomFollowInfoEntity::getClerkId); + if (StrUtil.isNotBlank(vo.getCustomId())) { + lambdaQueryWrapper.eq(PlayCustomFollowInfoEntity::getCustomId, vo.getCustomId()); + } + if (StrUtil.isNotBlank(vo.getFollowState())) { + lambdaQueryWrapper.eq(PlayCustomFollowInfoEntity::getFollowState, vo.getFollowState()); + } + IPage iPage = this.baseMapper.selectJoinPage( + new Page<>(vo.getPageNum(), vo.getPageSize()), PlayClerkFollowReturnVo.class, lambdaQueryWrapper); + for (PlayClerkFollowReturnVo record : iPage.getRecords()) { + LambdaQueryWrapper lambdaQueryWrapper1 = new LambdaQueryWrapper<>(); + lambdaQueryWrapper1.eq(PlayCustomFollowInfoEntity::getClerkId, record.getClerkId()); + record.setFollowNumber(this.baseMapper.selectList(lambdaQueryWrapper1).size()); + } + return iPage; + } + + /** + * 查询顾客关注陪聊信息列表 + * + * @param playCustomFollowInfo + * 顾客关注陪聊信息 + * @return 顾客关注陪聊信息 + */ + @Override + public IPage selectPlayCustomFollowInfoByPage( + PlayCustomFollowInfoEntity playCustomFollowInfo) { + Page page = new Page<>(1, 10); + return this.baseMapper.selectPage(page, new LambdaQueryWrapper<>()); + } + + /** + * 新增顾客关注陪聊信息 + * + * @param playCustomFollowInfo + * 顾客关注陪聊信息 + * @return 结果 + */ + @Override + public boolean create(PlayCustomFollowInfoEntity playCustomFollowInfo) { + if (StrUtil.isBlankIfStr(playCustomFollowInfo.getId())) { + playCustomFollowInfo.setId(IdUtils.getUuid()); + } + return save(playCustomFollowInfo); + } + + /** + * 修改顾客关注陪聊信息 + * + * @param playCustomFollowInfo + * 顾客关注陪聊信息 + * @return 结果 + */ + @Override + public boolean update(PlayCustomFollowInfoEntity playCustomFollowInfo) { + return updateById(playCustomFollowInfo); + } + + /** + * 批量删除顾客关注陪聊信息 + * + * @param ids + * 需要删除的顾客关注陪聊信息主键 + * @return 结果 + */ + @Override + public int deletePlayCustomFollowInfoByIds(String[] ids) { + return playCustomFollowInfoMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除顾客关注陪聊信息信息 + * + * @param id + * 顾客关注陪聊信息主键 + * @return 结果 + */ + @Override + public int deletePlayCustomFollowInfoById(String id) { + return playCustomFollowInfoMapper.deleteById(id); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/custom/service/impl/PlayCustomGiftInfoServiceImpl.java --- +package com.starry.admin.modules.custom.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.starry.admin.modules.custom.mapper.PlayCustomGiftInfoMapper; +import com.starry.admin.modules.custom.module.entity.PlayCustomGiftInfoEntity; +import com.starry.admin.modules.custom.service.IPlayCustomGiftInfoService; +import com.starry.common.utils.IdUtils; +import java.util.Arrays; +import java.util.List; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 顾客和礼物关系Service业务层处理 + * + * @author admin + * @since 2024-06-05 + */ +@Service +public class PlayCustomGiftInfoServiceImpl extends ServiceImpl + implements + IPlayCustomGiftInfoService { + @Resource + private PlayCustomGiftInfoMapper playCustomGiftInfoMapper; + + @Override + public PlayCustomGiftInfoEntity selectByGiftIdAndCustomId(String giftId, String customId) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayCustomGiftInfoEntity::getCustomId, customId); + lambdaQueryWrapper.eq(PlayCustomGiftInfoEntity::getGiffId, giftId); + return this.baseMapper.selectOne(lambdaQueryWrapper); + } + + /** + * 根据店员ID查询店员活动礼物列表 + * + * @param customId + * 店员ID + * @return 店员活动礼物列表 + */ + @Override + public List selectBtyCustomId(String customId) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayCustomGiftInfoEntity::getCustomId, customId); + return this.baseMapper.selectList(lambdaQueryWrapper); + } + + /** + * 查询顾客和礼物关系 + * + * @param id + * 顾客和礼物关系主键 + * @return 顾客和礼物关系 + */ + @Override + public PlayCustomGiftInfoEntity selectPlayCustomGiftInfoById(String id) { + return this.baseMapper.selectById(id); + } + + /** + * 查询顾客和礼物关系列表 + * + * @param playCustomGiftInfo + * 顾客和礼物关系 + * @return 顾客和礼物关系 + */ + @Override + public IPage selectPlayCustomGiftInfoByPage(PlayCustomGiftInfoEntity playCustomGiftInfo) { + Page page = new Page<>(1, 10); + return this.baseMapper.selectPage(page, new LambdaQueryWrapper()); + } + + /** + * 新增顾客和礼物关系 + * + * @param playCustomGiftInfo + * 顾客和礼物关系 + * @return 结果 + */ + @Override + public boolean create(PlayCustomGiftInfoEntity playCustomGiftInfo) { + if (StrUtil.isBlankIfStr(playCustomGiftInfo.getId())) { + playCustomGiftInfo.setId(IdUtils.getUuid()); + } + return save(playCustomGiftInfo); + } + + /** + * 修改顾客和礼物关系 + * + * @param playCustomGiftInfo + * 顾客和礼物关系 + * @return 结果 + */ + @Override + public boolean update(PlayCustomGiftInfoEntity playCustomGiftInfo) { + return updateById(playCustomGiftInfo); + } + + /** + * 批量删除顾客和礼物关系 + * + * @param ids + * 需要删除的顾客和礼物关系主键 + * @return 结果 + */ + @Override + public int deletePlayCustomGiftInfoByIds(String[] ids) { + return playCustomGiftInfoMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除顾客和礼物关系信息 + * + * @param id + * 顾客和礼物关系主键 + * @return 结果 + */ + @Override + public int deletePlayCustomGiftInfoById(String id) { + return playCustomGiftInfoMapper.deleteById(id); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/custom/service/impl/PlayCustomLeaveMsgServiceImpl.java --- +package com.starry.admin.modules.custom.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.github.yulichang.wrapper.MPJLambdaWrapper; +import com.starry.admin.common.conf.ThreadLocalRequestDetail; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.custom.mapper.PlayCustomLeaveMsgMapper; +import com.starry.admin.modules.custom.module.entity.PlayCustomLeaveMsgEntity; +import com.starry.admin.modules.custom.module.entity.PlayCustomUserInfoEntity; +import com.starry.admin.modules.custom.module.vo.PlayCustomLeaveMsgQueryVo; +import com.starry.admin.modules.custom.module.vo.PlayCustomLeaveMsgReturnVo; +import com.starry.admin.modules.custom.service.IPlayCustomLeaveMsgService; +import com.starry.common.utils.IdUtils; +import com.starry.common.utils.StringUtils; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.Arrays; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 顾客留言Service业务层处理 + * + * @author admin + * @since 2024-05-07 + */ +@Service +public class PlayCustomLeaveMsgServiceImpl extends ServiceImpl + implements + IPlayCustomLeaveMsgService { + @Resource + private PlayCustomLeaveMsgMapper playCustomLeaveMsgMapper; + + @Override + public IPage selectByPage(PlayCustomLeaveMsgQueryVo vo) { + MPJLambdaWrapper lambdaQueryWrapper = new MPJLambdaWrapper() + // 查询主表全部字段 + .selectAll(PlayCustomLeaveMsgEntity.class) + // 查询顾客表 + .selectAs(PlayCustomUserInfoEntity::getId, "customId") + .selectAs(PlayCustomUserInfoEntity::getAvatar, "customAvatar") + .selectAs(PlayCustomUserInfoEntity::getNickname, "customNickname") + // 子表 + .leftJoin(PlayCustomUserInfoEntity.class, PlayCustomUserInfoEntity::getId, + PlayCustomLeaveMsgEntity::getCustomId); + return this.baseMapper.selectJoinPage(new Page<>(vo.getPageNum(), vo.getPageSize()), + PlayCustomLeaveMsgReturnVo.class, lambdaQueryWrapper); + } + + /** + * 查询顾客留言 + * + * @param id + * 顾客留言主键 + * @return 顾客留言 + */ + @Override + public PlayCustomLeaveMsgEntity selectPlayCustomLeaveMsgById(String id) { + return this.baseMapper.selectById(id); + } + + /** + * 查询顾客留言列表 + * + * @param playCustomLeaveMsg + * 顾客留言 + * @return 顾客留言 + */ + @Override + public IPage selectPlayCustomLeaveMsgByPage(PlayCustomLeaveMsgEntity playCustomLeaveMsg) { + Page page = new Page<>(1, 10); + return this.baseMapper.selectPage(page, new LambdaQueryWrapper<>()); + } + + /** + * 查询当前用户不允许留言的原因 1、一个人在同一天只能留言一次 + * + * @param customId + * 顾客ID + * @return 当前用户不允许留言的原因 + */ + @Override + public String queryNoMessagesAllowedReason(String customId) { + // 1、一个人在同一天只能留言一次 + LocalDateTime now = LocalDateTime.now(); + LocalDateTime start = LocalDateTime.of(now.toLocalDate(), LocalTime.MIN); + LocalDateTime end = LocalDateTime.of(now.toLocalDate(), LocalTime.MAX); + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayCustomLeaveMsgEntity::getCustomId, customId); + lambdaQueryWrapper.between(PlayCustomLeaveMsgEntity::getMsgTime, start, end); + if (this.baseMapper.selectOne(lambdaQueryWrapper) != null) { + return "一天只能留言一次"; + } + // 2、 + // 3、 + return ""; + } + + /** + * 新增顾客留言 + * + * @param playCustomLeaveMsg + * 顾客留言 + * @return 结果 + */ + @Override + public boolean create(PlayCustomLeaveMsgEntity playCustomLeaveMsg) { + String noMessagesAllowedReason = this + .queryNoMessagesAllowedReason(ThreadLocalRequestDetail.getCustomUserInfo().getId()); + if (StringUtils.isNotEmpty(noMessagesAllowedReason)) { + throw new CustomException(noMessagesAllowedReason); + } + if (StrUtil.isBlankIfStr(playCustomLeaveMsg.getId())) { + playCustomLeaveMsg.setId(IdUtils.getUuid()); + } + return save(playCustomLeaveMsg); + } + + /** + * 修改顾客留言 + * + * @param playCustomLeaveMsg + * 顾客留言 + * @return 结果 + */ + @Override + public boolean update(PlayCustomLeaveMsgEntity playCustomLeaveMsg) { + return updateById(playCustomLeaveMsg); + } + + /** + * 批量删除顾客留言 + * + * @param ids + * 需要删除的顾客留言主键 + * @return 结果 + */ + @Override + public int deletePlayCustomLeaveMsgByIds(String[] ids) { + return playCustomLeaveMsgMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除顾客留言信息 + * + * @param id + * 顾客留言主键 + * @return 结果 + */ + @Override + public int deletePlayCustomLeaveMsgById(String id) { + return playCustomLeaveMsgMapper.deleteById(id); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/custom/service/impl/PlayCustomLevelInfoServiceImpl.java --- +package com.starry.admin.modules.custom.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.starry.admin.modules.custom.mapper.PlayCustomLevelInfoMapper; +import com.starry.admin.modules.custom.module.entity.PlayCustomLevelInfoEntity; +import com.starry.admin.modules.custom.service.IPlayCustomLevelInfoService; +import com.starry.admin.modules.system.module.entity.SysTenantEntity; +import com.starry.common.utils.IdUtils; +import java.util.Arrays; +import java.util.List; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 顾客等级Service业务层处理 + * + * @author admin + * @since 2024-05-04 + */ +@Service +public class PlayCustomLevelInfoServiceImpl extends ServiceImpl + implements + IPlayCustomLevelInfoService { + @Resource + private PlayCustomLevelInfoMapper playCustomLevelInfoMapper; + + @Override + public void initDefaultLevel(SysTenantEntity sysTenantEntity) { + List list = this.selectAll(); + if (list == null || list.isEmpty()) { + PlayCustomLevelInfoEntity entity = new PlayCustomLevelInfoEntity(); + entity.setLevel(1); + entity.setName("V1"); + entity.setConsumptionAmount("1"); + entity.setDiscount(100); + entity.setTenantId(sysTenantEntity.getTenantId()); + this.baseMapper.insert(entity); + } + } + + @Override + public PlayCustomLevelInfoEntity getDefaultLevel() { + List list = this.selectAll(); + if (list != null && !list.isEmpty()) { + return list.get(0); + } else { + PlayCustomLevelInfoEntity entity = new PlayCustomLevelInfoEntity(); + entity.setLevel(1); + entity.setName("V1"); + entity.setConsumptionAmount("1"); + entity.setDiscount(100); + this.baseMapper.insert(entity); + return entity; + } + } + + @Override + public List selectAll() { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.orderByAsc(PlayCustomLevelInfoEntity::getLevel); + return this.baseMapper.selectList(lambdaQueryWrapper); + } + + /** + * 查询顾客等级 + * + * @param id + * 顾客等级主键 + * @return 顾客等级 + */ + @Override + public PlayCustomLevelInfoEntity selectPlayCustomLevelInfoById(String id) { + return this.baseMapper.selectById(id); + } + + /** + * 查询顾客等级列表 + * + * @return 顾客等级 + */ + @Override + public List selectPlayCustomLevelInfoByPage() { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.orderByAsc(PlayCustomLevelInfoEntity::getLevel); + return this.baseMapper.selectList(lambdaQueryWrapper); + } + + /** + * 新增顾客等级 + * + * @param playCustomLevelInfo + * 顾客等级 + * @return 结果 + */ + @Override + public boolean create(PlayCustomLevelInfoEntity playCustomLevelInfo) { + if (StrUtil.isBlankIfStr(playCustomLevelInfo.getId())) { + playCustomLevelInfo.setId(IdUtils.getUuid()); + } + return save(playCustomLevelInfo); + } + + /** + * 修改顾客等级 + * + * @param playCustomLevelInfo + * 顾客等级 + * @return 结果 + */ + @Override + public boolean update(PlayCustomLevelInfoEntity playCustomLevelInfo) { + return updateById(playCustomLevelInfo); + } + + /** + * 批量删除顾客等级 + * + * @param ids + * 需要删除的顾客等级主键 + * @return 结果 + */ + @Override + public int deletePlayCustomLevelInfoByIds(String[] ids) { + return playCustomLevelInfoMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除顾客等级信息 + * + * @param id + * 顾客等级主键 + * @return 结果 + */ + @Override + public int deletePlayCustomLevelInfoById(String id) { + return playCustomLevelInfoMapper.deleteById(id); + } + + @Override + public int selectMaxLevel() { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.select("max(level) as level "); + PlayCustomLevelInfoEntity entity = this.baseMapper.selectOne(queryWrapper); + return entity == null ? 0 : entity.getLevel(); + } + + @Override + public void delMaxLevelByLevel(Integer level) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(PlayCustomLevelInfoEntity::getLevel, level); + this.baseMapper.delete(queryWrapper); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/custom/service/impl/PlayCustomUserInfoServiceImpl.java --- +package com.starry.admin.modules.custom.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.github.yulichang.wrapper.MPJLambdaWrapper; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.custom.mapper.PlayCustomUserInfoMapper; +import com.starry.admin.modules.custom.module.entity.PlayCustomLevelInfoEntity; +import com.starry.admin.modules.custom.module.entity.PlayCustomUserInfoEntity; +import com.starry.admin.modules.custom.module.vo.PlayCustomRankingQueryVo; +import com.starry.admin.modules.custom.module.vo.PlayCustomRankingReturnVo; +import com.starry.admin.modules.custom.module.vo.PlayCustomUserQueryVo; +import com.starry.admin.modules.custom.module.vo.PlayCustomUserReturnVo; +import com.starry.admin.modules.custom.service.IPlayCustomUserInfoService; +import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity; +import com.starry.admin.modules.order.service.impl.PlayOrderInfoServiceImpl; +import com.starry.admin.modules.personnel.service.IPlayBalanceDetailsInfoService; +import com.starry.common.utils.IdUtils; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.*; +import java.util.stream.Collectors; +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * 顾客Service业务层处理 + * + * @author admin + * @since 2024-04-08 + */ +@Slf4j +@Service +public class PlayCustomUserInfoServiceImpl extends ServiceImpl + implements + IPlayCustomUserInfoService { + @Resource + private PlayCustomUserInfoMapper playCustomUserInfoMapper; + + @Resource + private PlayOrderInfoServiceImpl playOrderInfoService; + + @Resource + private IPlayBalanceDetailsInfoService playBalanceDetailsInfoService; + + @Override + public PlayCustomUserInfoEntity selectByOpenid(String openId) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayCustomUserInfoEntity::getOpenid, openId); + return this.baseMapper.selectOne(lambdaQueryWrapper); + } + + @Override + public BigDecimal getCustomPaymentAmount(BigDecimal rechargeAmount, String customId) { + // 根据顾客ID,查询顾客对应等级 + MPJLambdaWrapper lambdaQueryWrapper = new MPJLambdaWrapper<>(); + lambdaQueryWrapper.selectAll(PlayCustomLevelInfoEntity.class); + lambdaQueryWrapper.leftJoin(PlayCustomLevelInfoEntity.class, PlayCustomLevelInfoEntity::getId, + PlayCustomUserInfoEntity::getLevelId); + lambdaQueryWrapper.eq(PlayCustomUserInfoEntity::getId, customId); + PlayCustomLevelInfoEntity entity = this.baseMapper.selectJoinOne(PlayCustomLevelInfoEntity.class, + lambdaQueryWrapper); + if (entity == null) { + log.error("未查询当前顾客的充值优惠金额,支付金额等于充值金额,rechargeAmount={},customId={}", rechargeAmount, customId); + return rechargeAmount; + } + try { + BigDecimal paymentAmount = BigDecimal.valueOf(entity.getDiscount()) + .divide(new BigDecimal(100), 2, RoundingMode.HALF_UP).multiply(rechargeAmount); + log.info("等级为{}的顾客{},充值{}元,实际应该支付{}元", entity.getName(), customId, rechargeAmount, paymentAmount); + return paymentAmount; + } catch (Exception e) { + log.error("计算顾客充值优惠金额发生异常,支付金额等于充值金额,rechargeAmount={},customId={}", rechargeAmount, customId); + return rechargeAmount; + } + } + + @Override + public void customAccountBalanceRecharge(BigDecimal rechargeAmount, String customId, String orderId) { + PlayCustomUserInfoEntity userInfo = this.selectById(customId); + // 查询充值赠送金额(暂是设置为0) + // 此处我想实现:超过50送5,超过100送10,200送20,300送30,400送40,500送50 + BigDecimal giftAmount = calculateGiftMoney(rechargeAmount); + // 修改用户账户余额 + this.updateAccountBalanceById(customId, userInfo.getAccountBalance(), + userInfo.getAccountBalance().add(rechargeAmount).add(giftAmount), "0", "充值", + rechargeAmount.add(giftAmount), giftAmount, orderId); + } + + private static BigDecimal calculateGiftMoney(BigDecimal rechargeAmount) { + // 此处我想实现:超过50送5,超过100送10,200送20,300送30,400送40,500送50 + BigDecimal giftAmount = BigDecimal.ZERO; + if (rechargeAmount.compareTo(new BigDecimal(50)) >= 0) { + giftAmount = new BigDecimal(5); + } + if (rechargeAmount.compareTo(new BigDecimal(100)) >= 0) { + giftAmount = new BigDecimal(10); + } + if (rechargeAmount.compareTo(new BigDecimal(200)) >= 0) { + giftAmount = new BigDecimal(20); + } + if (rechargeAmount.compareTo(new BigDecimal(300)) >= 0) { + giftAmount = new BigDecimal(30); + } + if (rechargeAmount.compareTo(new BigDecimal(400)) >= 0) { + giftAmount = new BigDecimal(40); + } + if (rechargeAmount.compareTo(new BigDecimal(500)) >= 0) { + giftAmount = new BigDecimal(50); + } + return giftAmount; + } + + /** + * 查询顾客 + * + * @param id + * 顾客主键 + * @return 顾客 + */ + @Override + public PlayCustomUserInfoEntity selectById(String id) { + PlayCustomUserInfoEntity entity = this.baseMapper.selectById(id); + if (entity == null) { + throw new CustomException("顾客不存在"); + } + return entity; + } + + @Override + public IPage selectRankingByPage(PlayCustomRankingQueryVo vo) { + MPJLambdaWrapper lambdaQueryWrapper = new MPJLambdaWrapper<>(); + lambdaQueryWrapper.selectCollection(PlayOrderInfoEntity.class, PlayCustomRankingReturnVo::getOrderInfos) + .leftJoin(PlayOrderInfoEntity.class, PlayOrderInfoEntity::getPurchaserBy, + PlayCustomUserInfoEntity::getId); + if (StrUtil.isNotBlank(vo.getId())) { + lambdaQueryWrapper.eq(PlayCustomUserInfoEntity::getId, vo.getId()); + } + if (vo.getPurchaserTime() != null && vo.getPurchaserTime().size() == 2) { + lambdaQueryWrapper.between(PlayOrderInfoEntity::getPurchaserTime, vo.getPurchaserTime().get(0), + vo.getPurchaserTime().get(1)); + } + + IPage page = this.baseMapper.selectJoinPage( + new Page<>(vo.getPageNum(), vo.getPageSize()), PlayCustomRankingReturnVo.class, lambdaQueryWrapper); + int index = 1; + for (PlayCustomRankingReturnVo record : page.getRecords()) { + record.setRankingIndex((vo.getPageNum() - 1) * vo.getPageSize() + index); + if (vo.getPurchaserTime() != null && vo.getPurchaserTime().size() == 2) { + record.setBeginPurchaserTime(vo.getPurchaserTime().get(0)); + record.setEndPurchaserTime(vo.getPurchaserTime().get(1)); + } + BigDecimal orderTotalAmount = new BigDecimal("0"); + int orderContinueNumber = 0; + int orderNumber = 0; + for (PlayOrderInfoEntity orderInfo : record.getOrderInfos()) { + if (orderInfo.getId() == null) { + continue; + } + if ("0".equals(orderInfo.getFirstOrder())) { + orderContinueNumber++; + } + orderNumber++; + if (!"4".equals(orderInfo.getOrderStatus())) { + orderTotalAmount = orderTotalAmount.add(orderInfo.getFinalAmount()); + } + } + record.setOrderTotalAmount(orderTotalAmount); + record.setOrderNumber(String.valueOf(orderNumber)); + record.setOrderContinueNumber(String.valueOf(orderContinueNumber)); + if (orderNumber != 0) { + record.setOrderPrice( + String.valueOf(orderTotalAmount.divide(new BigDecimal(orderNumber), 2, RoundingMode.HALF_UP))); + } else { + record.setOrderPrice("0"); + } + index++; + } + // 按照订单顺序进行排序 + page.setRecords(page.getRecords().stream() + .sorted(Comparator.comparing(PlayCustomRankingReturnVo::getOrderNumber).reversed()) + .collect(Collectors.toList())); + return page; + } + + @Override + public IPage selectByPage(PlayCustomUserQueryVo vo) { + MPJLambdaWrapper lambdaQueryWrapper = new MPJLambdaWrapper<>(); + lambdaQueryWrapper.selectAll(PlayCustomUserInfoEntity.class); + lambdaQueryWrapper.selectAs(PlayCustomLevelInfoEntity::getName, "levelName"); + lambdaQueryWrapper.leftJoin(PlayCustomLevelInfoEntity.class, PlayCustomLevelInfoEntity::getId, + PlayCustomUserInfoEntity::getLevelId); + if (StrUtil.isNotBlank(vo.getId())) { + lambdaQueryWrapper.eq(PlayCustomUserInfoEntity::getId, vo.getId()); + } + if (StrUtil.isNotBlank(vo.getNickname())) { + lambdaQueryWrapper.like(PlayCustomUserInfoEntity::getNickname, vo.getNickname()); + } + if (StrUtil.isNotBlank(vo.getRemark())) { + lambdaQueryWrapper.like(PlayCustomUserInfoEntity::getRemark, vo.getRemark()); + } + if (StrUtil.isNotBlank(vo.getWeiChatCode())) { + lambdaQueryWrapper.like(PlayCustomUserInfoEntity::getWeiChatCode, vo.getWeiChatCode()); + } + if (StrUtil.isNotBlank(vo.getPhone())) { + lambdaQueryWrapper.eq(PlayCustomUserInfoEntity::getPhone, vo.getPhone()); + } + if (StrUtil.isNotBlank(vo.getSex())) { + lambdaQueryWrapper.eq(PlayCustomUserInfoEntity::getSex, vo.getSex()); + } + if (StrUtil.isNotBlank(vo.getLevelId())) { + lambdaQueryWrapper.eq(PlayCustomUserInfoEntity::getLevelId, vo.getLevelId()); + } + if (StrUtil.isNotBlank(vo.getSubscribeState())) { + lambdaQueryWrapper.eq(PlayCustomUserInfoEntity::getSubscribeState, vo.getSubscribeState()); + } + if (StrUtil.isNotBlank(vo.getBlacklistState())) { + lambdaQueryWrapper.eq(PlayCustomUserInfoEntity::getBlacklistState, vo.getBlacklistState()); + } + if (StrUtil.isNotBlank(vo.getViolationState())) { + lambdaQueryWrapper.eq(PlayCustomUserInfoEntity::getViolationState, vo.getViolationState()); + } + if (StrUtil.isNotBlank(vo.getPurchaseState())) { + lambdaQueryWrapper.eq(PlayCustomUserInfoEntity::getPurchaseState, vo.getPurchaseState()); + } + if (StrUtil.isNotBlank(vo.getMobilePhoneState())) { + lambdaQueryWrapper.eq(PlayCustomUserInfoEntity::getMobilePhoneState, vo.getMobilePhoneState()); + } + if (vo.getRegistrationTime() != null && vo.getRegistrationTime().size() == 2) { + lambdaQueryWrapper.between(PlayCustomUserInfoEntity::getRegistrationTime, vo.getRegistrationTime().get(0), + vo.getRegistrationTime().get(1)); + } + if (vo.getFirstPurchaseTime() != null && vo.getFirstPurchaseTime().size() == 2) { + lambdaQueryWrapper.between(PlayCustomUserInfoEntity::getFirstPurchaseTime, vo.getFirstPurchaseTime().get(0), + vo.getFirstPurchaseTime().get(1)); + } + if (vo.getLastPurchaseTime() != null && vo.getLastPurchaseTime().size() == 2) { + lambdaQueryWrapper.between(PlayCustomUserInfoEntity::getLastPurchaseTime, vo.getLastPurchaseTime().get(0), + vo.getLastPurchaseTime().get(1)); + } + if (StrUtil.isNotBlank(vo.getSort())) { + if ("levelId".equals(vo.getSort())) { + lambdaQueryWrapper.orderByDesc(PlayCustomUserInfoEntity::getLevelId); + } + if ("accountBalance".equals(vo.getSort())) { + lambdaQueryWrapper.orderByDesc(PlayCustomUserInfoEntity::getAccountBalance); + } + if ("lastPurchaseTime".equals(vo.getSort())) { + lambdaQueryWrapper.orderByDesc(PlayCustomUserInfoEntity::getLastPurchaseTime); + } + } + + IPage page = this.baseMapper.selectJoinPage( + new Page<>(vo.getPageNum(), vo.getPageSize()), PlayCustomUserReturnVo.class, lambdaQueryWrapper); + for (PlayCustomUserReturnVo record : page.getRecords()) { + List orderInfoEntities = playOrderInfoService.list(Wrappers + .lambdaQuery(PlayOrderInfoEntity.class).eq(PlayOrderInfoEntity::getPurchaserBy, record.getId()) + .in(PlayOrderInfoEntity::getPlaceType, "0", "2")); + BigDecimal orderTotalAmount = new BigDecimal("0"); + for (PlayOrderInfoEntity orderInfoEntity : orderInfoEntities) { + orderTotalAmount = orderTotalAmount.add(orderInfoEntity.getFinalAmount()); + } + record.setOrderNumber(String.valueOf(orderInfoEntities.size())); + record.setOrderTotalAmount(orderTotalAmount); + if (!orderInfoEntities.isEmpty()) { + record.setOrderPrice(String.valueOf( + orderTotalAmount.divide(new BigDecimal(orderInfoEntities.size()), 2, RoundingMode.HALF_UP))); + } else { + record.setProvince("0"); + } + + } + return page; + + } + + /** + * 新增顾客 + * + * @param playCustomUserInfo + * 顾客 + * @return 结果 + */ + @Override + public boolean create(PlayCustomUserInfoEntity playCustomUserInfo) { + if (StrUtil.isBlankIfStr(playCustomUserInfo.getId())) { + playCustomUserInfo.setId(IdUtils.getUuid()); + } + return save(playCustomUserInfo); + } + + @Override + public void updateTokenById(String id, String token) { + PlayCustomUserInfoEntity entity = new PlayCustomUserInfoEntity(); + entity.setToken(token); + entity.setId(id); + this.baseMapper.updateById(entity); + } + + @Override + public void updateAccountBalanceById(String id, BigDecimal accountBalance) { + // 更新余额 + this.baseMapper.updateById(new PlayCustomUserInfoEntity(id, accountBalance)); + } + + @Override + public void updateAccountBalanceById(String userId, BigDecimal balanceBeforeOperation, + BigDecimal balanceAfterOperation, String operationType, String operationAction, BigDecimal balanceMoney, + BigDecimal giftAmount, String orderId) { + // 更新余额 + PlayCustomUserInfoEntity entity = new PlayCustomUserInfoEntity(); + entity.setId(userId); + entity.setAccountBalance(balanceAfterOperation); + entity.setAccountState(balanceAfterOperation.compareTo(new BigDecimal(0)) > 0 ? "1" : "0"); + this.baseMapper.updateById(entity); + // 记录余额变更记录 + playBalanceDetailsInfoService.insertBalanceDetailsInfo("1", userId, balanceBeforeOperation, + balanceAfterOperation, operationType, operationAction, balanceMoney, giftAmount, orderId); + } + + /** + * 修改顾客 + * + * @param playCustomUserInfo + * 顾客 + * @return 结果 + */ + @Override + public boolean update(PlayCustomUserInfoEntity playCustomUserInfo) { + return updateById(playCustomUserInfo); + } + + /** + * 批量删除顾客 + * + * @param ids + * 需要删除的顾客主键 + * @return 结果 + */ + @Override + public int deletePlayCustomUserInfoByIds(String[] ids) { + return playCustomUserInfoMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除顾客信息 + * + * @param id + * 顾客主键 + * @return 结果 + */ + @Override + public int deletePlayCustomUserInfoById(String id) { + return playCustomUserInfoMapper.deleteById(id); + } + + @Override + public List simpleList() { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(PlayCustomUserInfoEntity.class); + wrapper.orderByDesc(PlayCustomUserInfoEntity::getId).eq(PlayCustomUserInfoEntity::getDeleted, 0).select( + PlayCustomUserInfoEntity::getAvatar, PlayCustomUserInfoEntity::getId, + PlayCustomUserInfoEntity::getNickname, PlayCustomUserInfoEntity::getAvatar); + return baseMapper.selectList(wrapper); + } + + @Override + public void saveOrderInfo(PlayOrderInfoEntity entity) { + String id = entity.getPurchaserBy(); + LambdaUpdateWrapper wrapper = Wrappers.lambdaUpdate(PlayCustomUserInfoEntity.class) + .eq(PlayCustomUserInfoEntity::getId, id).set(PlayCustomUserInfoEntity::getLastPurchaseTime, new Date()); + PlayCustomUserInfoEntity userInfoEntity = selectById(id); + if (Objects.isNull(userInfoEntity.getFirstPurchaseTime())) { + wrapper.set(PlayCustomUserInfoEntity::getFirstPurchaseTime, new Date()); + } + wrapper.set(PlayCustomUserInfoEntity::getWeiChatCode, entity.getWeiChatCode()); + this.update(wrapper); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/controller/PlayOrderComplaintInfoController.java --- +package com.starry.admin.modules.order.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.modules.order.module.entity.PlayOrderComplaintInfoEntity; +import com.starry.admin.modules.order.module.vo.PlayOrderComplaintQueryVo; +import com.starry.admin.modules.order.module.vo.PlayOrderComplaintReturnVo; +import com.starry.admin.modules.order.service.IPlayOrderComplaintInfoService; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 订单投诉信息Controller + * + * @author admin + * @since 2024-05-07 + */ +@Api(tags = "订单投诉管理", description = "订单投诉信息管理相关接口,包括查询、新增、修改和删除等操作") +@RestController +@RequestMapping("/order/complaint") +public class PlayOrderComplaintInfoController { + @Resource + private IPlayOrderComplaintInfoService playOrderComplaintInfoService; + + /** + * 查询订单投诉信息列表 + */ + @ApiOperation(value = "分页查询投诉列表", notes = "分页查询订单投诉信息列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayOrderComplaintReturnVo.class, responseContainer = "Page")}) + @PostMapping("/listByPage") + public R list(@ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayOrderComplaintQueryVo vo) { + IPage list = playOrderComplaintInfoService.selectByPage(vo); + return R.ok(list); + } + + /** + * 获取订单投诉信息详细信息 + */ + @ApiOperation(value = "获取投诉详情", notes = "根据ID获取订单投诉详细信息") + @ApiImplicitParam(name = "id", value = "投诉记录ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = PlayOrderComplaintInfoEntity.class)}) + @GetMapping(value = "/{id}") + public R getInfo(@PathVariable("id") String id) { + return R.ok(playOrderComplaintInfoService.selectPlayOrderComplaintInfoById(id)); + } + + /** + * 新增订单投诉信息 + */ + @ApiOperation(value = "新增投诉记录", notes = "创建新的订单投诉信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "添加失败")}) + // @PreAuthorize("@customSs.hasPermission('order:complaint:add')") + @Log(title = "订单投诉信息", businessType = BusinessType.INSERT) + @PostMapping("/create") + public R create( + @ApiParam(value = "投诉信息", required = true) @RequestBody PlayOrderComplaintInfoEntity playOrderComplaintInfo) { + boolean success = playOrderComplaintInfoService.create(playOrderComplaintInfo); + if (success) { + return R.ok(); + } + return R.error("添加失败"); + } + + /** + * 修改订单投诉信息 + */ + @ApiOperation(value = "修改投诉记录", notes = "根据ID修改订单投诉信息") + @ApiImplicitParam(name = "id", value = "投诉记录ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败")}) + // @PreAuthorize("@customSs.hasPermission('order:complaint:update')") + @Log(title = "订单投诉信息", businessType = BusinessType.UPDATE) + @PostMapping(value = "/update/{id}") + public R update(@PathVariable String id, + @ApiParam(value = "投诉信息", required = true) @RequestBody PlayOrderComplaintInfoEntity playOrderComplaintInfo) { + playOrderComplaintInfo.setId(id); + boolean success = playOrderComplaintInfoService.update(playOrderComplaintInfo); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + /** + * 删除订单投诉信息 + */ + @ApiOperation(value = "删除投诉记录", notes = "根据ID批量删除订单投诉信息") + @ApiImplicitParam(name = "ids", value = "投诉记录ID数组", required = true, paramType = "path", dataType = "String[]", example = "1,2,3") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Integer.class)}) + // @PreAuthorize("@customSs.hasPermission('order:complaint:delete')") + @Log(title = "订单投诉信息", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@PathVariable String[] ids) { + return R.ok(playOrderComplaintInfoService.deletePlayOrderComplaintInfoByIds(ids)); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/controller/PlayOrderContinueInfoController.java --- +package com.starry.admin.modules.order.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.modules.order.module.vo.PlayOrderContinueQueryVo; +import com.starry.admin.modules.order.module.vo.PlayOrderContinueReturnVo; +import com.starry.admin.modules.order.module.vo.PlayOrderReviewStateEditVo; +import com.starry.admin.modules.order.service.IPlayOrderContinueInfoService; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 订单续单信息Controller + * + * @author admin + * @since 2024-05-10 + */ +@Api(tags = "订单续单管理", description = "订单续单信息管理相关接口,包括查询和审核等操作") +@RestController +@RequestMapping("/order/continue") +public class PlayOrderContinueInfoController { + @Resource + private IPlayOrderContinueInfoService playOrderContinueInfoService; + + /** + * 查询订单续单信息列表 + */ + @ApiOperation(value = "分页查询续单列表", notes = "分页查询订单续单信息列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayOrderContinueReturnVo.class, responseContainer = "Page")}) + @PostMapping("/listByPage") + public R list(@ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayOrderContinueQueryVo vo) { + IPage list = playOrderContinueInfoService.selectPlayByPage(vo); + return R.ok(list); + } + + /** + * 审批续单申申请 + */ + @ApiOperation(value = "审批续单申请", notes = "审核店员的续单申请") + @ApiResponses({@ApiResponse(code = 200, message = "审批成功"), @ApiResponse(code = 500, message = "审批失败")}) + // @PreAuthorize("@customSs.hasPermission('order:continue:update')") + @PostMapping("/updateReviewState") + public R updateReviewState( + @ApiParam(value = "审批信息", required = true) @Validated @RequestBody PlayOrderReviewStateEditVo vo) { + playOrderContinueInfoService.updateReviewState(vo); + return R.ok("成功"); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/controller/PlayOrderEvaluateInfoController.java --- +package com.starry.admin.modules.order.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.modules.order.module.entity.PlayOrderEvaluateInfoEntity; +import com.starry.admin.modules.order.module.vo.PlayOrderEvaluateEditStateVo; +import com.starry.admin.modules.order.module.vo.PlayOrderEvaluateQueryVo; +import com.starry.admin.modules.order.module.vo.PlayOrderEvaluateReturnVo; +import com.starry.admin.modules.order.service.IPlayOrderEvaluateInfoService; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import com.starry.common.utils.ConvertUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 订单评价信息Controller + * + * @author admin + * @since 2024-05-07 + */ +@Api(tags = "订单评价管理", description = "订单评价信息管理相关接口,包括查询、修改和删除等操作") +@RestController +@RequestMapping("/order/evaluate") +public class PlayOrderEvaluateInfoController { + @Resource + private IPlayOrderEvaluateInfoService playOrderEvaluateInfoService; + + /** + * 查询订单评价信息列表 + */ + @ApiOperation(value = "分页查询评价列表", notes = "分页查询订单评价信息列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayOrderEvaluateReturnVo.class, responseContainer = "Page")}) + @PostMapping("/listByPage") + public R list(@ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayOrderEvaluateQueryVo vo) { + IPage list = playOrderEvaluateInfoService.selectByPage(vo); + return R.ok(list); + } + + /** + * 修改订单评价信息 + */ + @ApiOperation(value = "修改评价状态", notes = "修改订单评价的显示状态") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败")}) + // @PreAuthorize("@customSs.hasPermission('order:evaluate:update')") + @Log(title = "修改订单评价状态", businessType = BusinessType.UPDATE) + @PostMapping(value = "/updateStatus") + public R update( + @ApiParam(value = "评价状态信息", required = true) @Validated @RequestBody PlayOrderEvaluateEditStateVo vo) { + PlayOrderEvaluateInfoEntity entity = ConvertUtil.entityToVo(vo, PlayOrderEvaluateInfoEntity.class); + boolean success = playOrderEvaluateInfoService.update(entity); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + /** + * 删除订单评价信息 + */ + @ApiOperation(value = "删除评价记录", notes = "根据ID批量删除订单评价信息") + @ApiImplicitParam(name = "ids", value = "评价记录ID数组", required = true, paramType = "path", dataType = "String[]", example = "1,2,3") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Integer.class)}) + // @PreAuthorize("@customSs.hasPermission('order:evaluate:delete')") + @Log(title = "订单评价信息", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@PathVariable String[] ids) { + return R.ok(playOrderEvaluateInfoService.deletePlayOrderEvaluateInfoByIds(ids)); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/controller/PlayOrderInfoController.java --- +package com.starry.admin.modules.order.controller; + +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity; +import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService; +import com.starry.admin.modules.custom.module.entity.PlayCustomUserInfoEntity; +import com.starry.admin.modules.custom.service.IPlayCustomUserInfoService; +import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity; +import com.starry.admin.modules.order.module.vo.*; +import com.starry.admin.modules.order.service.IPlayOrderInfoService; +import com.starry.admin.modules.order.service.IPlayOrderRefundInfoService; +import com.starry.admin.modules.shop.module.vo.PlayCommodityInfoVo; +import com.starry.admin.modules.shop.service.IPlayCommodityInfoService; +import com.starry.admin.modules.weichat.service.WxCustomMpService; +import com.starry.admin.utils.SecurityUtils; +import com.starry.common.annotation.Log; +import com.starry.common.context.CustomSecurityContextHolder; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.math.BigDecimal; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 订单管理 + * + * @author admin + * @since 2024-03-20 + */ +@Api(tags = "订单管理", description = "订单信息管理相关接口,包括查询、修改、退款和删除等操作") +@RestController +@RequestMapping("/order/order/") +public class PlayOrderInfoController { + @Resource + private IPlayOrderInfoService orderInfoService; + + @Resource + private WxCustomMpService wxCustomMpService; + + @Resource + private IPlayClerkUserInfoService playClerkUserInfoService; + + @Resource + private IPlayCommodityInfoService playCommodityInfoService; + + @Resource + private IPlayOrderRefundInfoService playOrderRefundInfoService; + @Resource + private IPlayCustomUserInfoService customUserInfoService; + + /** + * 分页查询订单列表 + */ + @ApiOperation(value = "分页查询订单列表", notes = "分页查询订单信息列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayOrderInfoEntity.class, responseContainer = "Page")}) + @PostMapping("/listByPage") + public R listByPage(@ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayOrderInfoQueryVo vo) { + return R.ok(orderInfoService.selectOrderInfoPage(vo)); + } + + /** + * 订单退款 + */ + @ApiOperation(value = "订单退款", notes = "处理订单退款操作") + @ApiResponses({@ApiResponse(code = 200, message = "退款成功"), @ApiResponse(code = 500, message = "退款失败,包含详细错误信息")}) + // @PreAuthorize("@customSs.hasPermission('order:order:update')") + @PostMapping("/orderRefund") + public R orderRefund(@ApiParam(value = "退款信息", required = true) @Validated @RequestBody PlayOrderRefundAddVo vo) { + PlayOrderInfoEntity orderInfo = orderInfoService.selectOrderInfoById(vo.getOrderId()); + if (orderInfo.getFinalAmount().compareTo(vo.getRefundAmount()) < 0) { + throw new CustomException("退款金额不能大于支付金额"); + } + if ("3".equals(orderInfo.getOrderStatus())) { + throw new CustomException("【已完成】的订单无法操作退款"); + } + if ("4".equals(orderInfo.getOrderStatus())) { + throw new CustomException("【已取消】的订单无法操作退款"); + } + if ("1".equals(orderInfo.getRefundType())) { + throw new CustomException("每个订单只能退款一次~"); + } + PlayOrderInfoEntity updateOrderInfo = new PlayOrderInfoEntity(); + updateOrderInfo.setId(orderInfo.getId()); + updateOrderInfo.setRefundType("1"); + // 订单退款,订单状态变为已取消 + updateOrderInfo.setOrderStatus("4"); + updateOrderInfo.setRefundAmount(vo.getRefundAmount()); + // 修改订单状态 + orderInfoService.update(updateOrderInfo); + // 记录退款信息 + String refundType = orderInfo.getFinalAmount().compareTo(vo.getRefundAmount()) == 0 ? "0" : "1"; + + PlayCustomUserInfoEntity customUserInfo = customUserInfoService.getById(orderInfo.getPurchaserBy()); + customUserInfoService.updateAccountBalanceById(customUserInfo.getId(), customUserInfo.getAccountBalance(), + customUserInfo.getAccountBalance().add(orderInfo.getOrderMoney()), "3", "订单退款", + orderInfo.getOrderMoney(), BigDecimal.ZERO, vo.getOrderId()); + + playOrderRefundInfoService.add(orderInfo.getId(), orderInfo.getPurchaserBy(), orderInfo.getAcceptBy(), + orderInfo.getPayMethod(), refundType, vo.getRefundAmount(), vo.getRefundReason(), "2", + SecurityUtils.getUserId(), "0", "0"); + return R.ok("退款成功"); + } + + /** + * 更换店员 + */ + @ApiOperation(value = "更换店员", notes = "修改订单的接单店员") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "操作失败")}) + // @PreAuthorize("@customSs.hasPermission('order:order:update')") + @PostMapping("/orderEditAcceptBy") + public R orderEditAcceptBy( + @ApiParam(value = "更换店员信息", required = true) @Validated @RequestBody PlayOrderEditAcceptByVo vo) { + orderInfoService.updateStateTo1("2", CustomSecurityContextHolder.getUserId(), vo.getAcceptBy(), + vo.getOrderId()); + PlayClerkUserInfoEntity clerkUserInfo = playClerkUserInfoService.selectById(vo.getAcceptBy()); + PlayOrderInfoEntity orderInfo = orderInfoService.selectOrderInfoById(vo.getOrderId()); + PlayCommodityInfoVo commodityInfo = playCommodityInfoService.queryCommodityInfo(orderInfo.getCommodityId(), + clerkUserInfo.getLevelId()); + wxCustomMpService.sendCreateOrderMessage(clerkUserInfo.getTenantId(), clerkUserInfo.getOpenid(), + orderInfo.getOrderNo(), orderInfo.getOrderMoney().toString(), commodityInfo.getCommodityName()); + return R.ok("操作成功"); + } + + /** + * 后台备注 + */ + @ApiOperation(value = "修改后台备注", notes = "修改订单的后台备注信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Boolean.class), + @ApiResponse(code = 500, message = "操作失败")}) + // @PreAuthorize("@customSs.hasPermission('order:order:update')") + @PostMapping("/orderEditBackendRemark") + public R orderEditBackendRemark( + @ApiParam(value = "后台备注信息", required = true) @Validated @RequestBody PlayOrderEditBackendRemarkByVo vo) { + PlayOrderInfoEntity orderInfo = orderInfoService.selectOrderInfoById(vo.getOrderId()); + PlayOrderInfoEntity updateOrderInfo = new PlayOrderInfoEntity(); + updateOrderInfo.setId(orderInfo.getId()); + updateOrderInfo.setBackendRemark(vo.getBackendRemark()); + return R.ok(orderInfoService.update(updateOrderInfo)); + } + + /** + * 重新抢单 + */ + @ApiOperation(value = "重新抢单", notes = "将订单重新设置为抢单状态") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Boolean.class), + @ApiResponse(code = 500, message = "操作失败,包含详细错误信息")}) + // @PreAuthorize("@customSs.hasPermission('order:order:update')") + @PostMapping("/orderEditRandomSingle") + public R orderEditRandomSingle( + @ApiParam(value = "重新抢单信息", required = true) @Validated @RequestBody PlayOrderEditRandomSingleVo vo) { + PlayOrderInfoEntity orderInfo = orderInfoService.selectOrderInfoById(vo.getOrderId()); + if (!"1".equals(orderInfo.getPlaceType())) { + throw new CustomException("订单类型错误,无法重新抢单"); + } + PlayOrderInfoEntity updateOrderInfo = new PlayOrderInfoEntity(); + updateOrderInfo.setSex(vo.getSex()); + updateOrderInfo.setLevelId(vo.getLevelId()); + updateOrderInfo.setExcludeHistory(vo.getExcludeHistory()); + updateOrderInfo.setRemark(vo.getRemark()); + updateOrderInfo.setId(vo.getOrderId()); + updateOrderInfo.setOrderStatus("0"); + updateOrderInfo.setAcceptBy(""); + updateOrderInfo.setEstimatedRevenueRatio(0); + updateOrderInfo.setEstimatedRevenue(BigDecimal.ZERO); + updateOrderInfo.setRemark(vo.getRemark()); + return R.ok(orderInfoService.update(updateOrderInfo)); + } + + /** + * 根据ID查询订单 + */ + @ApiOperation(value = "获取订单详情", notes = "根据ID获取订单详细信息") + @ApiImplicitParam(name = "id", value = "订单ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = PlayOrderInfoEntity.class)}) + @GetMapping(value = "/{id}") + public R getInfo(@PathVariable("id") String id) { + return R.ok(orderInfoService.selectById(id)); + } + + /** + * 根据ID修改订单信息 + */ + @ApiOperation(value = "修改订单信息", notes = "根据ID修改订单基本信息") + @ApiImplicitParam(name = "id", value = "订单ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败")}) + // @PreAuthorize("@customSs.hasPermission('order:order:update')") + @Log(title = "修改普通订单", businessType = BusinessType.UPDATE) + @PostMapping(value = "/update/{id}") + public R update(@PathVariable String id, + @ApiParam(value = "订单信息", required = true) @RequestBody PlayOrderInfoEntity orderInfoEntity) { + orderInfoEntity.setId(id); + boolean success = orderInfoService.update(orderInfoEntity); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + /** + * 删除订单 + */ + @ApiOperation(value = "删除订单", notes = "根据ID批量删除订单信息") + @ApiImplicitParam(name = "ids", value = "订单ID数组", required = true, paramType = "path", dataType = "String[]", example = "1,2,3") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Integer.class)}) + // @PreAuthorize("@customSs.hasPermission('order:order:delete')") + @Log(title = "删除订单", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@PathVariable String[] ids) { + return R.ok(orderInfoService.deleteOrderInfoByIds(ids)); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/controller/PlayOrderRefundInfoController.java --- +package com.starry.admin.modules.order.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.modules.order.module.entity.PlayOrderRefundInfoEntity; +import com.starry.admin.modules.order.module.vo.PlayOrderRefundQueryVo; +import com.starry.admin.modules.order.module.vo.PlayOrderRefundReturnVo; +import com.starry.admin.modules.order.service.IPlayOrderRefundInfoService; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 订单退款信息Controller + * + * @author admin + * @since 2024-05-09 + */ +@Api(tags = "订单退款管理", description = "订单退款信息管理相关接口,包括查询、新增、修改和删除等操作") +@RestController +@RequestMapping("/order/refund") +public class PlayOrderRefundInfoController { + @Resource + private IPlayOrderRefundInfoService playOrderRefundInfoService; + + /** + * 查询订单退款信息列表 + */ + @ApiOperation(value = "分页查询退款列表", notes = "分页查询订单退款信息列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayOrderRefundReturnVo.class, responseContainer = "Page")}) + @PostMapping("/list") + public R list(@ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayOrderRefundQueryVo vo) { + IPage list = playOrderRefundInfoService.selectByPage(vo); + return R.ok(list); + } + + /** + * 获取订单退款信息详细信息 + */ + @ApiOperation(value = "获取退款详情", notes = "根据ID获取订单退款详细信息") + @ApiImplicitParam(name = "id", value = "退款记录ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = PlayOrderRefundInfoEntity.class)}) + @GetMapping(value = "/{id}") + public R getInfo(@PathVariable("id") String id) { + return R.ok(playOrderRefundInfoService.selectPlayOrderRefundInfoById(id)); + } + + /** + * 新增订单退款信息 + */ + @ApiOperation(value = "新增退款记录", notes = "创建新的订单退款信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "添加失败")}) + @Log(title = "订单退款信息", businessType = BusinessType.INSERT) + @PostMapping("/create") + public R create( + @ApiParam(value = "退款信息", required = true) @RequestBody PlayOrderRefundInfoEntity playOrderRefundInfo) { + boolean success = playOrderRefundInfoService.create(playOrderRefundInfo); + if (success) { + return R.ok(); + } + return R.error("添加失败"); + } + + /** + * 修改订单退款信息 + */ + @ApiOperation(value = "修改退款记录", notes = "根据ID修改订单退款信息") + @ApiImplicitParam(name = "id", value = "退款记录ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败")}) + @Log(title = "订单退款信息", businessType = BusinessType.UPDATE) + @PostMapping(value = "/update/{id}") + public R update(@PathVariable String id, + @ApiParam(value = "退款信息", required = true) @RequestBody PlayOrderRefundInfoEntity playOrderRefundInfo) { + playOrderRefundInfo.setId(id); + boolean success = playOrderRefundInfoService.update(playOrderRefundInfo); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + /** + * 删除订单退款信息 + */ + @ApiOperation(value = "删除退款记录", notes = "根据ID批量删除订单退款信息") + @ApiImplicitParam(name = "ids", value = "退款记录ID数组", required = true, paramType = "path", dataType = "String[]", example = "1,2,3") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Integer.class)}) + @Log(title = "订单退款信息", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@PathVariable String[] ids) { + return R.ok(playOrderRefundInfoService.deletePlayOrderRefundInfoByIds(ids)); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/controller/PlayOrderRewardInfoController.java --- +package com.starry.admin.modules.order.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.modules.order.module.vo.PlayOrderRewardQueryVo; +import com.starry.admin.modules.order.module.vo.PlayOrderRewardReturnVo; +import com.starry.admin.modules.order.service.IPlayOrderInfoService; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 打赏订单 + * + * @author admin + * @since 2024-03-20 + */ +@Api(tags = "打赏订单管理", description = "打赏订单信息管理相关接口,包括查询等操作") +@RestController +@RequestMapping("/order/reward/") +public class PlayOrderRewardInfoController { + + @Resource + private IPlayOrderInfoService orderInfoService; + + /** + * 分页查询打赏订单列表 + */ + @ApiOperation(value = "分页查询打赏订单", notes = "分页查询打赏订单信息列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayOrderRewardReturnVo.class, responseContainer = "Page")}) + // @PreAuthorize("@customSs.hasPermission('order:reward:list')") + @Log(title = "查询打赏订单", businessType = BusinessType.INSERT) + @PostMapping("/listByPage") + public R queryRewardOrder( + @ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayOrderRewardQueryVo vo) { + IPage page = orderInfoService.selectRewardOrderInfoByPage(vo); + return R.ok(page); + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/mapper/PlayOrderComplaintInfoMapper.java --- +package com.starry.admin.modules.order.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.starry.admin.modules.order.module.entity.PlayOrderComplaintInfoEntity; + +/** + * 订单投诉信息Mapper接口 + * + * @author admin + * @since 2024-05-07 + */ +public interface PlayOrderComplaintInfoMapper extends MPJBaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/mapper/PlayOrderContinueInfoMapper.java --- +package com.starry.admin.modules.order.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.starry.admin.modules.order.module.entity.PlayOrderContinueInfoEntity; + +/** + * 订单续单信息Mapper接口 + * + * @author admin + * @since 2024-05-10 + */ +public interface PlayOrderContinueInfoMapper extends MPJBaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/mapper/PlayOrderEvaluateInfoMapper.java --- +package com.starry.admin.modules.order.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.starry.admin.modules.order.module.entity.PlayOrderEvaluateInfoEntity; + +/** + * 订单评价信息Mapper接口 + * + * @author admin + * @since 2024-05-07 + */ +public interface PlayOrderEvaluateInfoMapper extends MPJBaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/mapper/PlayOrderInfoMapper.java --- +package com.starry.admin.modules.order.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity; + +/** + * 订单Mapper接口 + * + * @author admin + * @since 2024-03-20 + */ +public interface PlayOrderInfoMapper extends MPJBaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/mapper/PlayOrderRefundInfoMapper.java --- +package com.starry.admin.modules.order.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.starry.admin.modules.order.module.entity.PlayOrderRefundInfoEntity; + +/** + * 订单退款信息Mapper接口 + * + * @author admin + * @since 2024-05-09 + */ +public interface PlayOrderRefundInfoMapper extends MPJBaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/module/constant/OrderConstant.java --- +package com.starry.admin.modules.order.module.constant; + +/** + * @author admin + * @since 2024/5/8 15:41 + **/ +public class OrderConstant { + + /** + * 订单状态-待接单 + * + * @since 2024/5/8 15:42 + **/ + public final static String ORDER_STATUS_0 = "0"; + + /** + * 订单状态-待开始 + * + * @since 2024/5/8 15:42 + **/ + public final static String ORDER_STATUS_1 = "1"; + + /** + * 订单状态-服务中 + * + * @since 2024/5/8 15:42 + **/ + public final static String ORDER_STATUS_2 = "2"; + + /** + * 订单状态-已完成 + * + * @since 2024/5/8 15:42 + **/ + public final static String ORDER_STATUS_3 = "3"; + + /** + * 订单状态-已取消 + * + * @since 2024/5/8 15:42 + **/ + public final static String ORDER_STATUS_4 = "4"; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/module/entity/PlayOrderComplaintInfoEntity.java --- +package com.starry.admin.modules.order.module.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.admin.common.conf.StringTypeHandler; +import com.starry.common.domain.BaseEntity; +import java.util.Date; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 订单投诉信息对象 play_order_complaint_info + * + * @author admin + * @since 2024-05-07 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName(value = "play_order_complaint_info", autoResultMap = true) +public class PlayOrderComplaintInfoEntity extends BaseEntity { + + /** + * uuid + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 订单ID + */ + private String orderId; + + /** + * 顾客ID + */ + private String customId; + + /** + * 店员ID + */ + private String clerkId; + + /** + * 商品ID + */ + private String commodityId; + + /** + * 投诉人微信号码 + */ + private String wxChatCode; + + /** + * 投诉内容 + */ + private String complaintCon; + + /** + * 投诉时间 + */ + private Date complaintTime; + + /** + * 图片列表 + */ + @TableField(typeHandler = StringTypeHandler.class) + private List images; + + /** + * 数据是否隐藏(0:显示,1:隐藏) + */ + private String hidden; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/module/entity/PlayOrderContinueInfoEntity.java --- +package com.starry.admin.modules.order.module.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.starry.admin.common.conf.StringTypeHandler; +import com.starry.common.domain.BaseEntity; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 订单续单信息对象 play_order_continue_info + * + * @author admin + * @since 2024-05-10 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName(value = "play_order_continue_info", autoResultMap = true) +public class PlayOrderContinueInfoEntity extends BaseEntity { + + /** + * uuid + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 订单ID + */ + private String orderId; + + /** + * 订单编号 + */ + private String orderNo; + + /** + * 顾客ID + */ + private String customId; + + /** + * 店员ID + */ + private String clerkId; + + /** + * 下单类型(0:指定单,1:随机单。2:打赏单) + */ + private String placeType; + + /** + * 下单金额 + */ + private BigDecimal orderMoney; + + /** + * 订单最终金额(支付金额) + */ + private BigDecimal finalAmount; + + /** + * 申请消息 + */ + private String continueMsg; + + /** + * 截图 + */ + @TableField(typeHandler = StringTypeHandler.class) + private List images; + + /** + * 是否需要审核,0:不需要,1:需要 + */ + private String reviewedRequired; + + /** + * 审核状态(0:未审核,1:已通过,2:不通过) + */ + private String reviewedState; + + /** + * 审核人 + */ + private String reviewedBy; + + /** + * 审核时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime reviewedTime; + + /** + * 审核内容 + */ + private String reviewedRemark; + + /** + * 申请时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime continueTime; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/module/entity/PlayOrderEvaluateInfoEntity.java --- +package com.starry.admin.modules.order.module.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.common.domain.BaseEntity; +import java.util.Date; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 订单评价信息对象 play_order_evaluate_info + * + * @author admin + * @since 2024-05-07 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("play_order_evaluate_info") +public class PlayOrderEvaluateInfoEntity extends BaseEntity { + + /** + * uuid + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 订单ID + */ + private String orderId; + + /** + * 顾客ID + */ + private String customId; + + /** + * 店员ID + */ + private String clerkId; + + /** + * 商品ID + */ + private String commodityId; + + /** + * 匿名评价(0:匿名,1:非匿名) + */ + private String anonymous; + + /** + * 评价类型(0:好评,1差评) + */ + private String evaluateType; + + /** + * 评价等级【1-5星,最低1星,最高5星】 + */ + private Integer evaluateLevel; + + /** + * 评价内容 + */ + private String evaluateCon; + + /** + * 评价时间 + */ + private Date evaluateTime; + + /** + * 数据是否隐藏(0:显示,1:隐藏) + */ + private String hidden; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/module/entity/PlayOrderInfoEntity.java --- +package com.starry.admin.modules.order.module.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.starry.admin.common.conf.StringTypeHandler; +import com.starry.common.domain.BaseEntity; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 订单对象 order_info + * + * @author admin + * @since 2024-03-20 + */ +@Data +@EqualsAndHashCode(callSuper = false) + +@TableName(value = "play_order_info", autoResultMap = true) +public class PlayOrderInfoEntity extends BaseEntity { + + /** + * uuid + */ + private String id; + + /** + * 订单编号 + */ + private String orderNo; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 订单状态【0:1:2:3:4】 0:已下单(待接单) 1:已接单(待开始) 2:已开始(服务中) 3:已完成 4:已取消 + */ + private String orderStatus; + + /** + * 订单类型【-1:退款订单;0:充值订单;1:提现订单;2:普通订单】 + */ + private String orderType; + + /** + * 下单类型(-1:其他类型;0:指定单;1:随机单;2:打赏单) + */ + private String placeType; + + /** + * 打赏类型(0:余额;1:礼物) + */ + private String rewardType; + + /** + * 是否是首单【0:不是,1:是】 + */ + private String firstOrder; + + /** + * 退款类型【0:未退款,1:已退款】 + */ + private String refundType; + + /** + * 退款金额 + */ + private BigDecimal refundAmount; + + /** + * 退款原因 + */ + private String refundReason; + + /** + * 商品ID + */ + private String commodityId; + + /** + * 商品类型[0:礼物,1:服务] + */ + private String commodityType; + /** + * 商品单价 + */ + private BigDecimal commodityPrice; + + /** + * 商品属性-服务时长 + **/ + private String serviceDuration; + + /** + * 商品名称 + */ + private String commodityName; + + /** + * 商品数量 + */ + private String commodityNumber; + + /** + * 订单要求 + */ + @TableField(typeHandler = StringTypeHandler.class) + private List labels; + + /** + * 是否使用优惠券[0:未使用,1:已使用] + */ + private String useCoupon; + + /** + * 优惠券列表 + */ + @TableField(typeHandler = StringTypeHandler.class) + private List couponIds; + + /** + * 是否是客服录入订单[0:不是,1:是] + */ + private String backendEntry; + + /** + * 支付方式,0:余额支付,1:微信支付,2:支付宝支付 + */ + private String payMethod; + + /** + * 支付状态,[-1:支付失败,0:未支付;1:支付完成] + */ + private String payState; + + /** + * 支付消息 + */ + private String payMsg; + + /** + * 订单金额 + */ + private BigDecimal orderMoney; + + /** + * 订单最终金额(支付金额) + */ + private BigDecimal finalAmount; + + /** + * 店员预计收入 + */ + private BigDecimal estimatedRevenue; + + /** + * 店员收入比例 + */ + private Integer estimatedRevenueRatio; + + /** + * 优惠金额 + * + * @since 2024/5/13 11:45 + **/ + private BigDecimal discountAmount; + + /** + * 下单人 + */ + private String purchaserBy; + + /** + * 下单时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime purchaserTime; + + /** + * 微信号码 + */ + private String weiChatCode; + + /** + * 是否需要审核,0:不需要,1:需要 + */ + private String reviewRequired; + + /** + * 审核状态(0:未审核,1:已通过,2:不通过) + */ + private String reviewState; + + /** + * 审核人 + */ + private String reviewedBy; + + /** + * 审核时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime reviewedTime; + + /** + * 审核内容 + */ + private String reviewedRemark; + + /** + * 接单人 + */ + private String acceptBy; + + /** + * 订单分组ID(和接单人同一个分组,接单时设置) + */ + private String groupId; + + /** + * 接单时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime acceptTime; + + /** + * 开始时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime orderStartTime; + + /** + * 结束时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime orderEndTime; + + /** + * 取消时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime orderCancelTime; + + /** + * 订单备注 + */ + private String remark; + + /** + * 后台备注 + */ + private String backendRemark; + + /** + * 订单结算状态(0:未结算;1:已结算) + */ + private String orderSettlementState; + + /** + * 订单结算时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime orderSettlementTime; + + /** + * 订单超时状态(0:未超时;1:已超时) + */ + private String ordersExpiredState; + + /** + * 随机单要求-店员性别(0:未知;1:男;2:女) + */ + private String sex; + + /** + * 随机单要求-店员等级ID + */ + private String levelId; + + /** + * 随机单要求-是否排除下单过的成员(0:不排除;1:排除) + */ + private String excludeHistory; + + private BigDecimal profitSharingAmount; + + public PlayOrderInfoEntity() { + + } + + public PlayOrderInfoEntity(String id, String orderStatus) { + this.id = id; + this.orderStatus = orderStatus; + } + + public PlayOrderInfoEntity(String id, String orderStatus, String orderType, String placeType) { + this.id = id; + this.orderStatus = orderStatus; + this.orderType = orderType; + this.placeType = placeType; + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/module/entity/PlayOrderRefundInfoEntity.java --- +package com.starry.admin.modules.order.module.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.common.domain.BaseEntity; +import java.math.BigDecimal; +import java.util.Date; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 订单退款信息对象 play_order_refund_info + * + * @author admin + * @since 2024-05-09 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("play_order_refund_info") +public class PlayOrderRefundInfoEntity extends BaseEntity { + + /** + * uuid + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 订单ID + */ + private String orderId; + + /** + * 顾客ID + */ + private String customId; + + /** + * 店员ID + */ + private String clerkId; + + /** + * 支付方式,[0:余额支付;1:微信支付,2:支付宝支付] + */ + private String payMethod; + + /** + * 是否使用优惠券[0:未使用,1:已使用] + */ + private String useCoupon; + + /** + * 退款类型【0:部分退款;1:全部退款】 + */ + private String refundType; + + /** + * 退款金额 + */ + private BigDecimal refundAmount; + + /** + * 退款原因 + */ + private String refundReason; + + /** + * 退款人类型[0:顾客;1:店员;2:管理员] + */ + private String refundByType; + + /** + * 退款人ID + */ + private String refundById; + + /** + * 截图 + */ + private String images; + + /** + * 退款状态[-1:异常;0:处理中;1:成功;2:关闭] + */ + private String refundState; + + /** + * 是否需要审核,0:不需要,1:需要 + */ + private String reviewedRequired; + + /** + * 审核状态(0:未审核,1:已通过,2:不通过) + */ + private String reviewedState; + + /** + * 审核人 + */ + private String reviewedBy; + + /** + * 审核时间 + */ + private Date reviewedTime; + + /** + * 审核内容 + */ + private String reviewedRemark; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/module/vo/ClerkEstimatedRevenueVo.java --- +package com.starry.admin.modules.order.module.vo; + +import java.math.BigDecimal; +import lombok.Data; + +/** + * @author admin + * @since 2024/7/18 16:36 + **/ +@Data +public class ClerkEstimatedRevenueVo { + + /** + * 收入比例 + * + * @since 2024/7/18 16:37 + **/ + private Integer revenueRatio; + + /** + * 收入金额 + * + * @since 2024/7/18 16:37 + **/ + private BigDecimal revenueAmount; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/module/vo/OrderInfoAddVo.java --- +package com.starry.admin.modules.order.module.vo; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.common.annotation.EnumValue; +import com.starry.common.domain.BaseEntity; +import java.util.List; +import javax.validation.constraints.NotBlank; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 陪聊订单对象 order_info + * + * @author admin + * @since 2024-03-20 + */ +@Data +@EqualsAndHashCode(callSuper = false) + +@TableName("order_info") +public class OrderInfoAddVo extends BaseEntity { + + /** + * 租户ID + */ + @NotBlank(message = "租户ID不能为空") + private String tenantId; + + /** + * 订单状态【0:1:2:3:4】 0:已下单 1:已接单 2:已开始 3:已完成 4:已取消 + */ + private String orderStatus = String.valueOf(0); + + /** + * 订单类型【0:充值订单;1:提现订单;2:普通订单】 + */ + private String orderType = String.valueOf(2); + + /** + * 下单类型(0:指定单,1:随机单。2:打赏单) + */ + @EnumValue(strValues = {"0", "1"}, message = "退款类型参数异常") + @NotBlank(message = "下单类型不能为空") + private String placeType; + + /** + * 陪聊ID + */ + @NotBlank(message = "陪聊对象不能为空") + private String playUserId; + + /** + * 优惠券ID列表 + */ + private List couponIds; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/module/vo/OrderInfoCancellationVo.java --- +package com.starry.admin.modules.order.module.vo; + +import javax.validation.constraints.NotNull; +import lombok.Data; + +/** + * 取消订单对象 order_info + * + * @author admin + * @since 2024-03-20 + */ +@Data +public class OrderInfoCancellationVo { + + /** + * uuid + */ + @NotNull(message = "订单ID不能为空") + private String id; + + /** + * 租户ID + */ + @NotNull(message = "租户ID不能为空") + private String tenantId; + + /** + * 操作人ID + */ + @NotNull(message = "操作人不能为空") + private String operatorBy; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/module/vo/OrderInfoRefundVo.java --- +package com.starry.admin.modules.order.module.vo; + +import com.starry.common.annotation.EnumValue; +import javax.validation.constraints.NotNull; +import lombok.Data; + +/** + * 订单信息对象 order_info + * + * @author admin + * @since 2024-03-20 + */ +@Data +public class OrderInfoRefundVo { + + /** + * uuid + */ + @NotNull(message = "订单ID不能为空") + private String id; + + /** + * 租户ID + */ + // @NotNull(message = "租户ID不能为空") + private String tenantId; + + /** + * 退款类型【1:部分退款,2:全部退款】 + */ + @NotNull(message = "退款类型不能为空") + @EnumValue(strValues = {"1", "2"}, message = "退款类型参数异常") + private String refundType; + + /** + * 退款金额,单位分 + */ + private String refundMoney; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/module/vo/PlayOrderComplaintQueryVo.java --- +package com.starry.admin.modules.order.module.vo; + +import com.starry.common.domain.BasePageEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 订单投诉查询对象 + * + * @author admin + */ +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel(value = "订单投诉查询参数", description = "查询订单投诉信息的条件参数") +public class PlayOrderComplaintQueryVo extends BasePageEntity { + + /** + * 数据ID + */ + @ApiModelProperty(value = "投诉ID", example = "1", notes = "特定投诉记录的ID") + private String id; + /** + * 订单ID + */ + @ApiModelProperty(value = "订单ID", example = "1", notes = "被投诉的订单ID") + private String orderId; + + /** + * 订单编号 + */ + @ApiModelProperty(value = "订单编号", example = "ORDER20240320001", notes = "被投诉的订单编号,支持模糊查询") + private String orderNo; + + /** + * 顾客ID + */ + @ApiModelProperty(value = "顾客ID", example = "1", notes = "投诉顾客的ID") + private String customId; + + /** + * 店员ID + */ + @ApiModelProperty(value = "店员ID", example = "1", notes = "被投诉店员的ID") + private String clerkId; + + /** + * 微信号码 + */ + @ApiModelProperty(value = "微信号码", example = "wx123456", notes = "顾客的微信号码") + private String weiChatCode; + + /** + * 投诉时间 + */ + @ApiModelProperty(value = "投诉时间范围", example = "['2024-01-01 00:00:00','2024-12-31 23:59:59']", notes = "投诉提交时间范围,包含开始和结束时间") + private List complaintTime; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/module/vo/PlayOrderComplaintReturnVo.java --- +package com.starry.admin.modules.order.module.vo; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.starry.admin.common.conf.StringTypeHandler; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; +import lombok.Data; + +/** + * 订单投诉查询返回对象 + * + * @author admin + */ +@Data +@ApiModel(value = "订单投诉返回数据", description = "订单投诉信息的返回数据") +public class PlayOrderComplaintReturnVo { + + /** + * uuid + */ + @ApiModelProperty(value = "投诉ID", example = "1") + private String id; + + /** + * 订单ID + */ + @ApiModelProperty(value = "订单ID", example = "1") + private String orderId; + + /** + * 顾客ID + */ + @ApiModelProperty(value = "顾客ID", example = "1") + private String customId; + + /** + * 顾客昵称 + */ + @ApiModelProperty(value = "顾客昵称", example = "张三") + private String customNickname; + + /** + * 顾客头像 + */ + @ApiModelProperty(value = "顾客头像", example = "https://example.com/avatar.jpg") + private String customAvatar; + + /** + * 店员ID + */ + @ApiModelProperty(value = "店员ID", example = "1") + private String clerkId; + + /** + * 顾客昵称 + */ + @ApiModelProperty(value = "店员昵称", example = "小明") + private String clerkNickname; + + /** + * 顾客头像 + */ + @ApiModelProperty(value = "店员头像", example = "https://example.com/clerk_avatar.jpg") + private String clerkAvatar; + + /** + * 投诉人微信号码 + */ + @ApiModelProperty(value = "微信号码", example = "wx123456") + private String wxChatCode; + + /** + * 投诉内容 + */ + @ApiModelProperty(value = "投诉内容", example = "店员服务态度差") + private String complaintCon; + + /** + * 投诉时间 + */ + @ApiModelProperty(value = "投诉时间", example = "2024-01-01 12:00:00") + private Date complaintTime; + + /** + * 图片列表 + */ + @TableField(typeHandler = StringTypeHandler.class) + @ApiModelProperty(value = "图片列表", example = "['https://example.com/img1.jpg','https://example.com/img2.jpg']") + private List images; + + /** + * 数据是否隐藏(0:显示,1:隐藏) + */ + @ApiModelProperty(value = "是否隐藏", example = "0", notes = "数据是否隐藏,0:显示,1:隐藏") + private String hidden; + + /** + * 订单号 + */ + @ApiModelProperty(value = "订单编号", example = "ORDER20240320001") + private String orderNo; + + /** + * 下单类型(0:指定单,1:随机单。2:打赏单) + */ + @ApiModelProperty(value = "下单类型", example = "0", notes = "0:指定单,1:随机单,2:打赏单") + private String placeType; + + /** + * 订单最终金额(支付金额) + */ + @ApiModelProperty(value = "支付金额", example = "100.00") + private BigDecimal finalAmount; + + /** + * 服务项目ID + */ + @ApiModelProperty(value = "商品ID", example = "1") + private String commodityId; + + /** + * 项目类型 + */ + @ApiModelProperty(value = "商品类型", example = "0", notes = "0:礼物,1:服务") + private String commodityType; + + /** + * 项目名称 + */ + @ApiModelProperty(value = "商品名称", example = "语音陪聊") + private String commodityName; + + /** + * 项目价格 + */ + @ApiModelProperty(value = "商品单价", example = "50.00") + private BigDecimal commodityPrice; + + /** + * 商品数量 + */ + @ApiModelProperty(value = "商品数量", example = "1") + private String commodityNumber; + + /** + * 服务时长(文字描述信息,不参与订单计算) + */ + @ApiModelProperty(value = "服务时长", example = "30", notes = "服务的时长,单位分钟") + private String serviceDuration; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/module/vo/PlayOrderContinueQueryVo.java --- +package com.starry.admin.modules.order.module.vo; + +import com.starry.common.domain.BasePageEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 续单分页查询对象 + * + * @author admin + * @since 2024/5/10 14:59 + **/ +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel(value = "订单续单查询参数", description = "查询订单续单信息的条件参数") +public class PlayOrderContinueQueryVo extends BasePageEntity { + + @ApiModelProperty(value = "昵称", example = "小明", notes = "店员或顾客昵称,支持模糊查询") + private String nickname; + + /** + * 店员ID + */ + @ApiModelProperty(value = "店员ID", example = "1", notes = "申请续单的店员ID") + private String clerkId; + + /** + * 顾客ID + */ + @ApiModelProperty(value = "顾客ID", example = "1", notes = "相关顾客的ID") + private String customId; + + /** + * 订单编号 + */ + @ApiModelProperty(value = "订单编号", example = "ORDER20240320001", notes = "相关订单的编号,支持模糊查询") + private String orderNo; + + /** + * 审核状态(0:未审核,1:已通过,2:不通过) + */ + @ApiModelProperty(value = "审核状态", example = "0", notes = "0:未审核,1:已通过,2:不通过") + private String reviewState; + + /** + * 申请时间 + */ + @ApiModelProperty(value = "申请时间范围", example = "['2024-01-01 00:00:00','2024-12-31 23:59:59']", notes = "续单申请时间范围,包含开始和结束时间") + private List continueTime; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/module/vo/PlayOrderContinueReturnVo.java --- +package com.starry.admin.modules.order.module.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 续单查询返回对象 + * + * @author admin + * @since 2024/5/10 14:59 + **/ +@Data +@ApiModel(value = "订单续单返回数据", description = "订单续单信息的返回数据") +public class PlayOrderContinueReturnVo { + + @ApiModelProperty(value = "续单ID", example = "1") + private String id; + + /** + * 店员ID + */ + @ApiModelProperty(value = "店员ID", example = "1") + private String clerkId; + + /** + * 店员昵称 + */ + @ApiModelProperty(value = "店员昵称", example = "小明") + private String clerkNickname; + + /** + * 店员昵称 + */ + @ApiModelProperty(value = "店员头像", example = "https://example.com/clerk_avatar.jpg") + private String clerkAvatar; + + /** + * 店员性别 + */ + @ApiModelProperty(value = "店员性别", example = "1", notes = "0:未知,1:男,2:女") + private String clerkSex; + + /** + * 顾客ID + */ + @ApiModelProperty(value = "顾客ID", example = "1") + private String customerId; + + /** + * 用户等级名称 + */ + @ApiModelProperty(value = "等级名称", example = "黄金会员") + private String levelName; + + /** + * 订单编号 + */ + @ApiModelProperty(value = "订单编号", example = "ORDER20240320001") + private String orderNo; + + /** + * 下单类型(0:指定单,1:随机单。2:打赏单) + */ + @ApiModelProperty(value = "下单类型", example = "0", notes = "0:指定单,1:随机单,2:打赏单") + private String placeType; + + /** + * 商品名称 + */ + @ApiModelProperty(value = "商品名称", example = "语音陪聊") + private String commodityName; + /** + * 商品单价 + */ + @ApiModelProperty(value = "商品单价", example = "50.00") + private BigDecimal commodityPrice; + + /** + * 服务时长 + * + * @since 2024/5/8 16:44 + **/ + @ApiModelProperty(value = "服务时长", example = "30", notes = "服务的时长,单位分钟") + private String serviceDuration; + + /** + * 商品数量 + */ + @ApiModelProperty(value = "商品数量", example = "1") + private int commodityNumber; + + /** + * 下单金额 + */ + @ApiModelProperty(value = "订单金额", example = "100.00") + private BigDecimal orderMoney; + + /** + * 订单最终金额(支付金额) + */ + @ApiModelProperty(value = "支付金额", example = "100.00") + private BigDecimal finalAmount; + + /** + * 申请消息 + */ + @ApiModelProperty(value = "申请消息", example = "顾客需要继续服务") + private String continueMsg; + + /** + * 截图 + */ + @ApiModelProperty(value = "截图列表", example = "['https://example.com/img1.jpg','https://example.com/img2.jpg']") + private List images; + + /** + * 是否需要审核,0:不需要,1:需要 + */ + @ApiModelProperty(value = "是否需要审核", example = "1", notes = "0:不需要,1:需要") + private String reviewedRequired; + + /** + * 审核状态(0:未审核,1:已通过,2:不通过) + */ + @ApiModelProperty(value = "审核状态", example = "0", notes = "0:未审核,1:已通过,2:不通过") + private String reviewedState; + + /** + * 审核内容 + */ + @ApiModelProperty(value = "审核备注", example = "审核通过,可以继续服务") + private String reviewedRemark; + + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + @ApiModelProperty(value = "申请时间", example = "2024-01-01 12:00:00") + private LocalDateTime continueTime; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/module/vo/PlayOrderDetailsReturnVo.java --- +package com.starry.admin.modules.order.module.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; +import lombok.Data; + +/** + * 订单查询返回对象 + * + * @author admin + * @since 2024-03-20 + */ +@Data +public class PlayOrderDetailsReturnVo { + + private String id; + + private String orderNo; + + /** + * 用户ID + */ + private String customId; + + /** + * 用户昵称 + */ + private String customNickname; + + /** + * 用户头像 + */ + private String customAvatar; + + /** + * 店员ID + */ + private String clerkId; + + /** + * 店员昵称 + */ + private String clerkNickname; + + /** + * 店员头像 + */ + private String clerkAvatar; + + /** + * 下单时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date purchaserTime; + + /** + * 接单时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date acceptTime = new Date(); + + /** + * 开始时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date startTime = new Date(); + + /** + * 结束时间时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date endTime = new Date(); + + /** + * 订单金额 + */ + private BigDecimal orderMoney; + + /** + * 订单最终金额 + */ + private BigDecimal finalAmount; + + /** + * 商品ID + */ + private String commodityId; + + /** + * 商品类型[0:礼物,1:服务] + */ + private String commodityType; + + /** + * 商品名称 + */ + private String commodityName; + /** + * 商品单价 + */ + private BigDecimal commodityPrice; + + /** + * 服务时长 + * + * @since 2024/5/8 16:44 + **/ + private String serviceDuration; + + /** + * 商品数量 + */ + private int commodityNumber; + + /** + * 订单状态【0:1:2:3:4】 0:已下单(待接单) 1:已接单(待开始) 2:已开始(服务中) 3:已完成 4:已取消 + */ + private String orderStatus; + + /** + * 下单类型(0:指定单,1:随机单。2:打赏单) + */ + private String placeType; + + /** + * 微信号码 + */ + private String weiChatCode; + + /** + * 支付方式,0:余额支付,1:微信支付,2:支付宝支付 + */ + private String payMethod; + + /** + * 订单备注 + */ + private String remark; + + /** + * 订单要求 + */ + private List labels; + + /** + * 是否是首单【0:不是,1:是】 + */ + private String firstOrder; + + /** + * 是否评价(1:已评价;0:未评价) + */ + private String evaluate = "0"; + + /** + * 是否投诉(1:已投诉;0:未投诉) + */ + private String complaint = "0"; + + /** + * 预计收入 + */ + private BigDecimal estimatedRevenue; + + /** + * 店员收入比例 + */ + private Integer estimatedRevenueRatio; + + /** + * 优惠金额 + */ + private BigDecimal discountAmount; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/module/vo/PlayOrderEditAcceptByVo.java --- +package com.starry.admin.modules.order.module.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotNull; +import lombok.Data; + +/** + * 订单查询对象 + * + * @author admin + * @since 2024-03-20 + */ +@Data +@ApiModel(value = "更换店员参数", description = "更换订单接单店员的请求参数") +public class PlayOrderEditAcceptByVo { + + /** + * uuid + */ + @NotNull(message = "orderId不能为空") + @ApiModelProperty(value = "订单ID", required = true, example = "1", notes = "需要更换店员的订单ID") + private String orderId; + + /** + * 店员ID + */ + @NotNull(message = "店员不能为空") + @ApiModelProperty(value = "店员ID", required = true, example = "1", notes = "新的接单店员ID") + private String acceptBy; + + /** + * 备注 + */ + @ApiModelProperty(value = "备注", example = "店员请假,需要更换", notes = "更换店员的原因说明") + private String remark; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/module/vo/PlayOrderEditBackendRemarkByVo.java --- +package com.starry.admin.modules.order.module.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotNull; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +/** + * 订单查询对象 + * + * @author admin + * @since 2024-03-20 + */ +@Data +@ApiModel(value = "修改后台备注参数", description = "修改订单后台备注的请求参数") +public class PlayOrderEditBackendRemarkByVo { + + /** + * uuid + */ + @NotNull(message = "orderId不能为空") + @ApiModelProperty(value = "订单ID", required = true, example = "1", notes = "需要修改备注的订单ID") + private String orderId; + + /** + * 后台备注不能为空 + */ + @NotNull(message = "后台备注不能为空") + @Length(min = 1, max = 100, message = "后台备注字符长度在1-100个字符之间") + @ApiModelProperty(value = "后台备注", required = true, example = "顾客要求特殊服务", notes = "订单的后台备注内容,1-100字符") + private String backendRemark; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/module/vo/PlayOrderEditRandomSingleVo.java --- +package com.starry.admin.modules.order.module.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotNull; +import lombok.Data; + +/** + * 重新抢单对象 + * + * @author admin + * @since 2024-03-20 + */ +@Data +@ApiModel(value = "重新抢单参数", description = "设置订单重新抢单的请求参数") +public class PlayOrderEditRandomSingleVo { + + /** + * uuid + */ + @NotNull(message = "orderId不能为空") + @ApiModelProperty(value = "订单ID", required = true, example = "1", notes = "需要重新抢单的订单ID") + private String orderId; + + /** + * 陪聊性别(0:未知;1:男;2:女) + * + * @since 2024/5/8 15:31 + **/ + @NotNull(message = "陪聊性别不能为空") + @ApiModelProperty(value = "店员性别", required = true, example = "2", notes = "抢单店员的性别要求,0:未知;1:男;2:女") + private String sex; + /** + * 陪聊等级 + **/ + @NotNull(message = "陪聊等级不能为空") + @ApiModelProperty(value = "店员等级", required = true, example = "1", notes = "抢单店员的等级要求") + private String levelId; + + /** + * 是否排除下单过的成员(0:不排除;1:排除) + * + * @since 2024/5/8 15:28 + **/ + @NotNull(message = "是否排除下单过的成员不能为空") + @ApiModelProperty(value = "是否排除历史", required = true, example = "1", notes = "是否排除下单过的成员,0:不排除;1:排除") + private String excludeHistory; + + /** + * 订单备注 + * + * @since 2024/5/8 15:28 + **/ + @ApiModelProperty(value = "订单备注", example = "需要擅长聊天的店员", notes = "订单的备注信息") + private String remark; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/module/vo/PlayOrderEvaluateEditStateVo.java --- +package com.starry.admin.modules.order.module.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Pattern; +import lombok.Data; + +/** + * 订单评价状态修改对象 + * + * @author admin + */ +@Data +@ApiModel(value = "评价状态修改参数", description = "修改订单评价显示状态的请求参数") +public class PlayOrderEvaluateEditStateVo { + + /** + * UUID + */ + @NotBlank(message = "id不能为空") + @ApiModelProperty(value = "评价ID", required = true, example = "1", notes = "需要修改状态的评价ID") + private String id; + + /** + * 数据是否隐藏(0:显示,1:隐藏) + */ + @NotBlank(message = "是否隐藏不能为空") + @Pattern(regexp = "[01]", message = "是否隐藏数据错误,只能位0或者1") + @ApiModelProperty(value = "是否隐藏", required = true, example = "1", notes = "数据是否隐藏,0:显示,1:隐藏") + private String hidden; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/module/vo/PlayOrderEvaluateQueryVo.java --- +package com.starry.admin.modules.order.module.vo; + +import com.starry.common.domain.BasePageEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 订单评价查询对象 + * + * @author admin + */ +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel(value = "订单评价查询参数", description = "查询订单评价信息的条件参数") +public class PlayOrderEvaluateQueryVo extends BasePageEntity { + + /** + * UUID + */ + @ApiModelProperty(value = "评价ID", example = "1", notes = "特定评价记录的ID") + private String id; + + /** + * 顾客ID + */ + @ApiModelProperty(value = "顾客ID", example = "1", notes = "评价顾客的ID") + private String customId; + + /** + * 店员ID + */ + @ApiModelProperty(value = "店员ID", example = "1", notes = "被评价店员的ID") + private String clerkId; + + /** + * 评价内容 + */ + @ApiModelProperty(value = "评价内容", example = "服务很好", notes = "评价内容,支持模糊查询") + private String evaluateCon; + + /** + * 匿名评价(0:匿名,1:非匿名) + */ + @ApiModelProperty(value = "是否匿名", example = "0", notes = "0:匿名,1:非匿名") + private String anonymous; + + /** + * 评价时间 + */ + @ApiModelProperty(value = "评价时间范围", example = "['2024-01-01 00:00:00','2024-12-31 23:59:59']", notes = "评价提交时间范围,包含开始和结束时间") + private List evaluateTime; + + /** + * 数据是否隐藏(0:显示,1:隐藏) + */ + @ApiModelProperty(value = "是否隐藏", example = "0", notes = "数据是否隐藏,0:显示,1:隐藏") + private String hidden; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/module/vo/PlayOrderEvaluateReturnVo.java --- +package com.starry.admin.modules.order.module.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.util.Date; +import lombok.Data; + +/** + * 订单评价查询返回对象 + * + * @author admin + */ +@Data +@ApiModel(value = "订单评价返回数据", description = "订单评价信息的返回数据") +public class PlayOrderEvaluateReturnVo { + + /** + * uuid + */ + @ApiModelProperty(value = "评价ID", example = "1") + private String id; + + /** + * 订单ID + */ + @ApiModelProperty(value = "订单ID", example = "1") + private String orderId; + + /** + * 匿名评价(0:匿名,1:非匿名) + */ + @ApiModelProperty(value = "是否匿名", example = "0", notes = "0:匿名,1:非匿名") + private String anonymous; + /** + * 评价类型(0:好评,1差评) + */ + @ApiModelProperty(value = "评价类型", example = "0", notes = "0:好评,1:差评") + private String evaluateType; + + /** + * 评价等级【1-5星,最低1星,最高5星】 + */ + @ApiModelProperty(value = "评价等级", example = "5", notes = "1-5星,最低1星,最高5星") + private Integer evaluateLevel; + + /** + * 评价内容 + */ + @ApiModelProperty(value = "评价内容", example = "服务很好,店员态度很好") + private String evaluateCon; + + /** + * 评价时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + @ApiModelProperty(value = "评价时间", example = "2024-01-01 12:00:00") + private Date evaluateTime; + + /** + * 数据是否隐藏(0:显示,1:隐藏) + */ + @ApiModelProperty(value = "是否隐藏", example = "0", notes = "数据是否隐藏,0:显示,1:隐藏") + private String hidden; + + /** + * 顾客ID + */ + @ApiModelProperty(value = "顾客ID", example = "1") + private String customId; + + /** + * 顾客昵称 + */ + @ApiModelProperty(value = "顾客昵称", example = "张三") + private String customNickname; + + /** + * 顾客头像 + */ + @ApiModelProperty(value = "顾客头像", example = "https://example.com/avatar.jpg") + private String customAvatar; + + /** + * 店员ID + */ + @ApiModelProperty(value = "店员ID", example = "1") + private String clerkId; + + /** + * 顾客昵称 + */ + @ApiModelProperty(value = "店员昵称", example = "小明") + private String clerkNickname; + + /** + * 顾客头像 + */ + @ApiModelProperty(value = "店员头像", example = "https://example.com/clerk_avatar.jpg") + private String clerkAvatar; + + /** + * 点赞数 + */ + @ApiModelProperty(value = "点赞数", example = "10") + private int likeCount = 10; + + /** + * 订单号 + */ + @ApiModelProperty(value = "订单编号", example = "ORDER20240320001") + private String orderNo; + + /** + * 下单类型(0:指定单,1:随机单。2:打赏单) + */ + @ApiModelProperty(value = "下单类型", example = "0", notes = "0:指定单,1:随机单,2:打赏单") + private String placeType; + + /** + * 订单最终金额(支付金额) + */ + @ApiModelProperty(value = "支付金额", example = "100.00") + private BigDecimal finalAmount; + + /** + * 服务项目ID + */ + @ApiModelProperty(value = "商品ID", example = "1") + private String commodityId; + + /** + * 项目类型 + */ + @ApiModelProperty(value = "商品类型", example = "0", notes = "0:礼物,1:服务") + private String commodityType; + + /** + * 项目名称 + */ + @ApiModelProperty(value = "商品名称", example = "语音陪聊") + private String commodityName; + + /** + * 项目价格 + */ + @ApiModelProperty(value = "商品单价", example = "50.00") + private BigDecimal commodityPrice; + + /** + * 商品数量 + */ + @ApiModelProperty(value = "商品数量", example = "1") + private String commodityNumber; + + /** + * 服务时长(文字描述信息,不参与订单计算) + */ + @ApiModelProperty(value = "服务时长", example = "30", notes = "服务的时长,单位分钟") + private String serviceDuration; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/module/vo/PlayOrderInfoQueryVo.java --- +package com.starry.admin.modules.order.module.vo; + +import com.starry.common.domain.BasePageEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 订单查询对象 + * + * @author admin + * @since 2024-03-20 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@ApiModel(value = "订单查询参数", description = "查询订单信息的条件参数") +public class PlayOrderInfoQueryVo extends BasePageEntity { + + /** + * uuid + */ + @ApiModelProperty(value = "订单ID", example = "1", notes = "特定订单的ID") + private String id; + + /** + * 订单编号 + */ + @ApiModelProperty(value = "订单编号", example = "ORDER20240320001", notes = "订单的编号,支持模糊查询") + private String orderNo; + + /** + * 订单状态【0:1:2:3:4】 0:已下单(待接单) 1:已接单(待开始) 2:已开始(服务中) 3:已完成 4:已取消 + */ + @ApiModelProperty(value = "订单状态", example = "0", notes = "0:已下单(待接单);1:已接单(待开始);2:已开始(服务中);3:已完成;4:已取消") + private String orderStatus; + + /** + * 订单类型【-1:退款订单;0:充值订单;1:提现订单;2:普通订单】 + */ + @ApiModelProperty(value = "订单类型", example = "2", notes = "-1:退款订单;0:充值订单;1:提现订单;2:普通订单") + private String orderType; + + /** + * 下单类型(-1:其他类型;0:指定单;1:随机单;2:打赏单) + */ + @ApiModelProperty(value = "下单类型", example = "0", notes = "-1:其他类型;0:指定单;1:随机单;2:打赏单") + private String placeType; + + /** + * 是否是首单【0:不是,1:是】 + */ + @ApiModelProperty(value = "是否首单", example = "1", notes = "0:不是,1:是") + private String firstOrder; + + /** + * 是否使用优惠券[0:未使用,1:已使用] + */ + @ApiModelProperty(value = "是否使用优惠券", example = "1", notes = "0:未使用,1:已使用") + private String useCoupon; + + /** + * 是否是客服录入订单[0:不是,1:是] + */ + @ApiModelProperty(value = "是否客服录入", example = "0", notes = "0:不是,1:是") + private String backendEntry; + + /** + * 支付方式,0:余额支付,1:微信支付,2:支付宝支付 + */ + @ApiModelProperty(value = "支付方式", example = "0", notes = "0:余额支付,1:微信支付,2:支付宝支付") + private String payMethod; + + /** + * 微信号码 + */ + @ApiModelProperty(value = "微信号码", example = "wx123456", notes = "顾客的微信号码") + private String weiChatCode; + + /** + * 下单人 + */ + @ApiModelProperty(value = "下单人ID", example = "1", notes = "下单顾客的ID") + private String purchaserBy; + + /** + * 下单时间 + */ + @ApiModelProperty(value = "下单时间范围", example = "['2024-01-01 00:00:00','2024-12-31 23:59:59']", notes = "下单时间范围,包含开始和结束时间") + private List purchaserTime; + + /** + * 接单人 + */ + @ApiModelProperty(value = "接单人ID", example = "1", notes = "接单店员的ID") + private String acceptBy; + + /** + * 接单时间 + */ + @ApiModelProperty(value = "接单时间范围", example = "['2024-01-01 00:00:00','2024-12-31 23:59:59']", notes = "接单时间范围,包含开始和结束时间") + private List acceptTime; + + /** + * 开始订单时间(开始服务时间) + */ + @ApiModelProperty(value = "开始服务时间范围", example = "['2024-01-01 00:00:00','2024-12-31 23:59:59']", notes = "订单开始服务时间范围,包含开始和结束时间") + private List startOrderTime; + + /** + * 完成订单时间(开始服务时间) + */ + @ApiModelProperty(value = "完成服务时间范围", example = "['2024-01-01 00:00:00','2024-12-31 23:59:59']", notes = "订单完成服务时间范围,包含开始和结束时间") + private List endOrderTime; + + /** + * 分组ID + */ + @ApiModelProperty(value = "分组ID", example = "1", notes = "订单所属分组的ID") + private String groupId; + + @ApiModelProperty(value = "店员昵称", example = "小明", notes = "接单店员的昵称,支持模糊查询") + private String clerkNickName; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/module/vo/PlayOrderInfoReturnVo.java --- +package com.starry.admin.modules.order.module.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; +import lombok.Data; + +/** + * 订单查询返回对象 + * + * @author admin + * @since 2024-03-20 + */ +@Data +public class PlayOrderInfoReturnVo { + + private String id; + + /** + * 用户ID + */ + private String customId; + + /** + * 用户昵称 + */ + private String customNickname; + + /** + * 用户头像 + */ + private String customAvatar; + + private String orderNo; + + /** + * 店员ID + */ + private String clerkId; + + /** + * 店员昵称 + */ + private String clerkNickname; + + /** + * 店员头像 + */ + private String clerkAvatar; + + /** + * 下单时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date purchaserTime; + + /** + * 接单时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date acceptTime; + + /** + * 开始时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date startTime; + + /** + * 结束时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date endTime; + + /** + * 取消时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date cancelTime; + + /** + * 订单金额 + */ + private BigDecimal orderMoney; + + /** + * 退款类型【0:未退款,1:已退款】 + */ + private String refundType; + + /** + * 商品ID + */ + private String commodityId; + + /** + * 商品类型[0:礼物,1:服务] + */ + private String commodityType; + + /** + * 商品类型[0:礼物,1:服务] + */ + private String commodityName; + /** + * 商品单价 + */ + private BigDecimal commodityPrice; + + /** + * 服务时长 + * + * @since 2024/5/8 16:44 + **/ + private String serviceDuration; + + /** + * 商品数量 + */ + private int commodityNumber; + + /** + * 订单状态【0:1:2:3:4】 0:已下单(待接单) 1:已接单(待开始) 2:已开始(服务中) 3:已完成 4:已取消 + */ + private String orderStatus; + + /** + * 下单类型(0:指定单,1:随机单。2:打赏单) + */ + private String placeType; + + /** + * 支付方式,0:余额支付,1:微信支付,2:支付宝支付 + */ + private String payMethod; + + /** + * 是否是首单【0:不是,1:是】 + */ + private String firstOrder; + + /** + * 订单最终金额(支付金额) + */ + private BigDecimal finalAmount; + + /** + * 店员收入 + */ + private BigDecimal estimatedRevenue = BigDecimal.ZERO; + + /** + * 店员收入比例 + */ + private Integer estimatedRevenueRatio; + + /** + * 微信号码 + */ + private String weiChatCode; + + /** + * 订单备注 + */ + private String remark; + + /** + * 后台备注 + */ + private String backendRemark; + + private List labels; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/module/vo/PlayOrderRefundAddVo.java --- +package com.starry.admin.modules.order.module.vo; + +import com.starry.common.domain.BasePageEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import javax.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.hibernate.validator.constraints.Length; + +/** + * 订单查询对象 + * + * @author admin + * @since 2024-03-20 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@ApiModel(value = "订单退款参数", description = "订单退款操作的请求参数") +public class PlayOrderRefundAddVo extends BasePageEntity { + + /** + * uuid + */ + @NotNull(message = "orderId不能为空") + @ApiModelProperty(value = "订单ID", required = true, example = "1", notes = "需要退款的订单ID") + private String orderId; + + /** + * 退款金额 + */ + @NotNull(message = "退款金额不能为空") + @ApiModelProperty(value = "退款金额", required = true, example = "100.00", notes = "退款的金额,不能大于支付金额") + private BigDecimal refundAmount; + + /** + * 退款原因 + */ + @NotNull(message = "退款原因不能为空") + @Length(min = 1, max = 100, message = "退款原因必须在1-100个字符之间") + @ApiModelProperty(value = "退款原因", required = true, example = "顾客要求退款", notes = "退款的原因说明,1-100字符") + private String refundReason; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/module/vo/PlayOrderRefundQueryVo.java --- +package com.starry.admin.modules.order.module.vo; + +import com.starry.common.domain.BasePageEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @author admin + * @since 2024/5/9 下午11:10 + **/ +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel(value = "订单退款查询参数", description = "查询订单退款信息的条件参数") +public class PlayOrderRefundQueryVo extends BasePageEntity { + + @ApiModelProperty(value = "订单ID", example = "1", notes = "特定订单的ID") + private String orderId; + + @ApiModelProperty(value = "退款类型", example = "0", notes = "0:全额退款,1:部分退款") + private String refundType; + + @ApiModelProperty(value = "退款状态", example = "1", notes = "退款处理状态") + private String refundStatus; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/module/vo/PlayOrderRefundReturnVo.java --- +package com.starry.admin.modules.order.module.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.util.Date; +import lombok.Data; + +/** + * @author admin + * @since 2024/5/9 下午11:10 + **/ +@Data +@ApiModel(value = "订单退款返回数据", description = "订单退款信息的返回数据") +public class PlayOrderRefundReturnVo { + + @ApiModelProperty(value = "退款ID", example = "1") + private String id; + + @ApiModelProperty(value = "订单ID", example = "1") + private String orderId; + + @ApiModelProperty(value = "订单编号", example = "ORDER20240320001") + private String orderNo; + + @ApiModelProperty(value = "退款金额", example = "100.00") + private BigDecimal refundAmount; + + @ApiModelProperty(value = "退款原因", example = "顾客要求退款") + private String refundReason; + + @ApiModelProperty(value = "退款类型", example = "0", notes = "0:全额退款,1:部分退款") + private String refundType; + + @ApiModelProperty(value = "退款状态", example = "1", notes = "退款处理状态") + private String refundStatus; + + @ApiModelProperty(value = "退款时间", example = "2024-01-01 12:00:00") + private Date refundTime; + + @ApiModelProperty(value = "支付方式", example = "0", notes = "0:余额支付,1:微信支付,2:支付宝支付") + private String payMethod; + + @ApiModelProperty(value = "操作人ID", example = "1") + private String operatorId; + + @ApiModelProperty(value = "操作人名称", example = "管理员") + private String operatorName; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/module/vo/PlayOrderReviewStateEditVo.java --- +package com.starry.admin.modules.order.module.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Pattern; +import lombok.Data; + +/** + * 续单申请审批状态修改对象 + * + * @author admin + * @since 2024/5/10 14:59 + **/ +@Data +@ApiModel(value = "审批状态修改参数", description = "续单申请审批状态修改的请求参数") +public class PlayOrderReviewStateEditVo { + + @NotBlank(message = "ID不能为空") + @ApiModelProperty(value = "续单ID", required = true, example = "1", notes = "需要审批的续单ID") + private String id; + + /** + * 审核状态(0:未审核,1:已通过,2:不通过) + */ + @NotBlank(message = "审核状态不能为空") + @Pattern(regexp = "[12]", message = "审核状态必须为1或2") + @ApiModelProperty(value = "审核状态", required = true, example = "1", notes = "1:已通过,2:不通过") + private String reviewState; + + @ApiModelProperty(value = "审核备注", example = "审核通过,可以继续服务", notes = "审核意见或备注信息") + private String remark; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/module/vo/PlayOrderRewardQueryVo.java --- +package com.starry.admin.modules.order.module.vo; + +import com.starry.common.domain.BasePageEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 打赏订单查询对象 + * + * @author admin + */ +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel(value = "打赏订单查询参数", description = "查询打赏订单信息的条件参数") +public class PlayOrderRewardQueryVo extends BasePageEntity { + /** + * UUID + */ + @ApiModelProperty(value = "订单ID", example = "1", notes = "特定订单的ID") + private String id; + + /** + * 顾客ID + */ + @ApiModelProperty(value = "顾客ID", example = "1", notes = "打赏顾客的ID") + private String purchaserBy; + + /** + * 店员ID + */ + @ApiModelProperty(value = "店员ID", example = "1", notes = "接收打赏的店员ID") + private String acceptBy; + + /** + * 打赏留言 + */ + @ApiModelProperty(value = "打赏留言", example = "感谢服务", notes = "打赏时的留言内容,支持模糊查询") + private String rewardCon; + + /** + * 打赏类型(0:打赏礼物,1:自定义金额) + */ + @ApiModelProperty(value = "打赏类型", example = "0", notes = "0:打赏礼物,1:自定义金额") + private String rewardType; + + /** + * 礼物ID + */ + @ApiModelProperty(value = "礼物ID", example = "1", notes = "打赏礼物的ID") + private String commodityId; + + /** + * 打赏时间 + */ + @ApiModelProperty(value = "打赏时间范围", example = "['2024-01-01 00:00:00','2024-12-31 23:59:59']", notes = "打赏时间范围,包含开始和结束时间") + private List purchaserTime; + + /** + * 数据是否隐藏(0:显示,1:隐藏) + */ + @ApiModelProperty(value = "是否隐藏", example = "0", notes = "数据是否隐藏,0:显示,1:隐藏") + private String hidden; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/module/vo/PlayOrderRewardReturnVo.java --- +package com.starry.admin.modules.order.module.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 打赏订单查询返回信息 + * + * @author admin + */ +@Data +@ApiModel(value = "打赏订单返回数据", description = "打赏订单信息的返回数据") +public class PlayOrderRewardReturnVo { + + /** + * 订单ID + */ + @ApiModelProperty(value = "订单ID", example = "1") + private String id; + + /** + * 用户ID + */ + @ApiModelProperty(value = "顾客ID", example = "1") + private String customId; + + /** + * 用户昵称 + */ + @ApiModelProperty(value = "顾客昵称", example = "张三") + private String customNickname; + + /** + * 用户头像 + */ + @ApiModelProperty(value = "顾客头像", example = "https://example.com/avatar.jpg") + private String customAvatar; + + /** + * 店员ID + */ + @ApiModelProperty(value = "店员ID", example = "1") + private String clerkId; + + /** + * 店员昵称 + */ + @ApiModelProperty(value = "店员昵称", example = "小明") + private String clerkNickname; + + /** + * 店员头像 + */ + @ApiModelProperty(value = "店员头像", example = "https://example.com/clerk_avatar.jpg") + private String clerkAvatar; + + /** + * 打赏类型 + */ + @ApiModelProperty(value = "打赏类型", example = "0", notes = "0:打赏礼物,1:自定义金额") + private String rewardType; + + /** + * 订单金额 + */ + @ApiModelProperty(value = "订单金额", example = "100.00") + private String orderMoney; + + /** + * 支付金额 + */ + @ApiModelProperty(value = "支付金额", example = "100.00") + private String finalAmount; + + /** + * 商品ID + */ + @ApiModelProperty(value = "商品ID", example = "1") + private String commodityId; + + /** + * 商品类型[0:礼物,1:服务] + */ + @ApiModelProperty(value = "商品类型", example = "0", notes = "0:礼物,1:服务") + private String commodityType; + + /** + * 商品名称 + */ + @ApiModelProperty(value = "商品名称", example = "爱心礼物") + private String commodityName; + /** + * 商品单价 + */ + @ApiModelProperty(value = "商品单价", example = "50.00") + private BigDecimal commodityPrice; + + /** + * 服务时长 + * + * @since 2024/5/8 16:44 + **/ + @ApiModelProperty(value = "服务时长", example = "30", notes = "服务的时长,单位分钟") + private String serviceDuration; + + /** + * 打赏留言 + */ + @ApiModelProperty(value = "打赏留言", example = "感谢服务") + private String remark; + + /** + * 打赏时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + @ApiModelProperty(value = "打赏时间", example = "2024-01-01 12:00:00") + private LocalDateTime purchaserTime; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/module/vo/PlayOrderStateEditVo.java --- +package com.starry.admin.modules.order.module.vo; + +import java.util.ArrayList; +import java.util.List; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +/** + * 订单状态修改对象 + * + * @author admin + * @since 2024-03-20 + */ +@Data +public class PlayOrderStateEditVo { + + /** + * 订单ID + */ + @NotBlank(message = "订单ID不能为空") + private String orderId; + + /** + * 取消原因 + */ + @NotBlank(message = "取消原因不能为空") + private String refundReason; + + private List images = new ArrayList<>(); + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/service/IPlayOrderComplaintInfoService.java --- +package com.starry.admin.modules.order.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.order.module.entity.PlayOrderComplaintInfoEntity; +import com.starry.admin.modules.order.module.vo.PlayOrderComplaintQueryVo; +import com.starry.admin.modules.order.module.vo.PlayOrderComplaintReturnVo; +import java.util.List; + +/** + * 订单投诉信息Service接口 + * + * @author admin + * @since 2024-05-07 + */ +public interface IPlayOrderComplaintInfoService extends IService { + /** + * 查询订单投诉信息 + * + * @param id + * 订单投诉信息主键 + * @return 订单投诉信息 + */ + PlayOrderComplaintInfoEntity selectPlayOrderComplaintInfoById(String id); + + /** + * 查询顾客对订单的评价内容 + * + * @param customId + * 顾客ID + * @param orderId + * 订单ID + * @return boolean true:已评价,false:未评价 + **/ + PlayOrderComplaintInfoEntity queryCustomToOrderOrderComplaintInfo(String customId, String orderId); + + /** + * 查询订单评价列表 + * + * @param entity + * 订单评价对象 + * @return 订单评价列表 + */ + List selectByList(PlayOrderComplaintInfoEntity entity); + + /** + * 分页查询订单投诉列表 + * + * @param vo + * 订单投诉查询对象 + * @return 订单投诉列表 + */ + + IPage selectByPage(PlayOrderComplaintQueryVo vo); + + /** + * 查询订单投诉信息列表 + * + * @param playOrderComplaintInfo + * 订单投诉信息 + * @return 订单投诉信息集合 + */ + IPage selectPlayOrderComplaintInfoByPage( + PlayOrderComplaintInfoEntity playOrderComplaintInfo); + + /** + * 新增订单投诉信息 + * + * @param playOrderComplaintInfo + * 订单投诉信息 + * @return 结果 + */ + boolean create(PlayOrderComplaintInfoEntity playOrderComplaintInfo); + + /** + * 修改订单投诉信息 + * + * @param playOrderComplaintInfo + * 订单投诉信息 + * @return 结果 + */ + boolean update(PlayOrderComplaintInfoEntity playOrderComplaintInfo); + + /** + * 批量删除订单投诉信息 + * + * @param ids + * 需要删除的订单投诉信息主键集合 + * @return 结果 + */ + int deletePlayOrderComplaintInfoByIds(String[] ids); + + /** + * 删除订单投诉信息信息 + * + * @param id + * 订单投诉信息主键 + * @return 结果 + */ + int deletePlayOrderComplaintInfoById(String id); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/service/IPlayOrderContinueInfoService.java --- +package com.starry.admin.modules.order.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.order.module.entity.PlayOrderContinueInfoEntity; +import com.starry.admin.modules.order.module.vo.PlayOrderContinueQueryVo; +import com.starry.admin.modules.order.module.vo.PlayOrderContinueReturnVo; +import com.starry.admin.modules.order.module.vo.PlayOrderReviewStateEditVo; + +/** + * 订单续单信息Service接口 + * + * @author admin + * @since 2024-05-10 + */ +public interface IPlayOrderContinueInfoService extends IService { + + /** + * 根据订单ID查询订单续单信息 + * + * @param orderId + * 订单ID + * @return 订单续单信息 + */ + PlayOrderContinueInfoEntity selectPlayOrderId(String orderId); + + /** + * 查询订单续单信息 + * + * @param id + * 订单续单信息主键 + * @return 订单续单信息 + */ + PlayOrderContinueInfoEntity selectPlayOrderContinueInfoById(String id); + + /** + * 分页查询订单续单对象 + * + * @param vo + * 订单续单对象查询对象 + * @return 订单续单信息集合 + */ + IPage selectPlayByPage(PlayOrderContinueQueryVo vo); + + /** + * 修改续单审核状态 + * + * @param vo + * 续单审核申请对象 + */ + void updateReviewState(PlayOrderReviewStateEditVo vo); + + /** + * 查询订单续单信息列表 + * + * @param playOrderContinueInfo + * 订单续单信息 + * @return 订单续单信息集合 + */ + IPage selectPlayOrderContinueInfoByPage( + PlayOrderContinueInfoEntity playOrderContinueInfo); + + /** + * 新增订单续单信息 + * + * @param playOrderContinueInfo + * 订单续单信息 + * @return 结果 + */ + boolean create(PlayOrderContinueInfoEntity playOrderContinueInfo); + + /** + * 修改订单续单信息 + * + * @param playOrderContinueInfo + * 订单续单信息 + * @return 结果 + */ + boolean update(PlayOrderContinueInfoEntity playOrderContinueInfo); + + /** + * 批量删除订单续单信息 + * + * @param ids + * 需要删除的订单续单信息主键集合 + * @return 结果 + */ + int deletePlayOrderContinueInfoByIds(String[] ids); + + /** + * 删除订单续单信息信息 + * + * @param id + * 订单续单信息主键 + * @return 结果 + */ + int deletePlayOrderContinueInfoById(String id); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/service/IPlayOrderEvaluateInfoService.java --- +package com.starry.admin.modules.order.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.order.module.entity.PlayOrderEvaluateInfoEntity; +import com.starry.admin.modules.order.module.vo.PlayOrderEvaluateQueryVo; +import com.starry.admin.modules.order.module.vo.PlayOrderEvaluateReturnVo; +import java.util.List; + +/** + * 订单评价信息Service接口 + * + * @author admin + * @since 2024-05-07 + */ +public interface IPlayOrderEvaluateInfoService extends IService { + + /** + * 查询订单评价信息 + * + * @param id + * 订单评价信息主键 + * @return 订单评价信息 + */ + PlayOrderEvaluateInfoEntity selectPlayOrderEvaluateInfoById(String id); + + /** + * 查询顾客对订单的评价内容 + * + * @param customId + * 顾客ID + * @param orderId + * 订单ID + * @return boolean true:已评价,false:未评价 + **/ + PlayOrderEvaluateInfoEntity queryCustomToOrderEvaluateInfo(String customId, String orderId); + + /** + * 查询订单评价列表 + * + * @param entity + * 订单评价对象 + * @return 订单评价列表 + */ + List selectByList(PlayOrderEvaluateInfoEntity entity); + + /** + * 分页查询订单评价列表 + * + * @param vo + * 订单评价查询对象 + * @return 订单评价列表 + */ + IPage selectByPage(PlayOrderEvaluateQueryVo vo); + + /** + * 查询订单评价信息列表 + * + * @param playOrderEvaluateInfo + * 订单评价信息 + * @return 订单评价信息集合 + */ + IPage selectPlayOrderEvaluateInfoByPage( + PlayOrderEvaluateInfoEntity playOrderEvaluateInfo); + + /** + * 新增订单评价信息 + * + * @param playOrderEvaluateInfo + * 订单评价信息 + * @return 结果 + */ + boolean create(PlayOrderEvaluateInfoEntity playOrderEvaluateInfo); + + /** + * 修改订单评价信息 + * + * @param playOrderEvaluateInfo + * 订单评价信息 + * @return 结果 + */ + boolean update(PlayOrderEvaluateInfoEntity playOrderEvaluateInfo); + + /** + * 批量删除订单评价信息 + * + * @param ids + * 需要删除的订单评价信息主键集合 + * @return 结果 + */ + int deletePlayOrderEvaluateInfoByIds(String[] ids); + + /** + * 删除订单评价信息信息 + * + * @param id + * 订单评价信息主键 + * @return 结果 + */ + int deletePlayOrderEvaluateInfoById(String id); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/service/IPlayOrderInfoService.java --- +package com.starry.admin.modules.order.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity; +import com.starry.admin.modules.order.module.vo.*; +import com.starry.admin.modules.weichat.entity.order.*; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import org.springframework.stereotype.Service; + +/** + * 订单Service接口 + * + * @author admin + * @since 2024-03-20 + */ +@Service +public interface IPlayOrderInfoService extends IService { + + /** + * 查询当前租户店员总数 + * + * @param tenantId + * 租户ID + * @return 店员总数 + */ + List getTotalOrderInfo(String tenantId); + + /** + * 新增充值单 + * + * @param orderNo + * 订单编号 + * @param orderMoney + * 订单金额 + * @param finalAmount + * 订单最终金额(支付金额) + * @param purchaserBy + * 下单人ID + */ + void createRechargeOrder(String orderNo, BigDecimal orderMoney, BigDecimal finalAmount, String purchaserBy); + + /** + * 新增订单信息 + * + * @param orderId + * 订单ID + * @param orderNo + * 订单编号 + * @param orderState + * 订单状态【0:已下单(待接单);1:已接单(待开始);2:已开始(服务中);3;已完成:4:已取消】 + * @param orderType + * 订单类型【-1:退款订单;0:充值订单;1:提现订单;2:普通订单】 + * @param placeType + * 下单类型(-1:其他类型;0:指定单;1:随机单;2:打赏单) + * @param rewardType + * (0:余额;1:礼物) + * @param firstOrder + * 是否是首单【0:不是,1:是】 + * @param commodityId + * 商品ID + * @param commodityType + * 商品类型[0:礼物,1:服务] + * @param commodityPrice + * 商品属性-商品单价 + * @param serviceDuration + * 商品属性-服务时长 + * @param commodityName + * 商品名称 + * @param commodityNumber + * 商品数量 + * @param orderMoney + * 订单金额 + * @param finalAmount + * 订单最终金额(支付金额) + * @param discountAmount + * 优惠金额 + * @param purchaserBy + * 下单人 + * @param acceptBy + * 接单人 + * @param weiChatCode + * 订单微信号码 + * @param couponIds + * 优惠券ID列表 + * @param remark + * 订单备注 + * @param clerkSex + * 随机单要求-店员性别(0:未知;1:男;2:女) + * @param clerkLevelId + * 随机单要求-店员等级ID + * @param excludeHistory + * 随机单要求-是否排除下单过的成员(0:不排除;1:排除) + * @author admin + * @since 2024/6/3 10:53 + **/ + void createOrderInfo(String orderId, String orderNo, String orderState, String orderType, String placeType, + String rewardType, String firstOrder, String commodityId, String commodityType, BigDecimal commodityPrice, + String serviceDuration, String commodityName, String commodityNumber, BigDecimal orderMoney, + BigDecimal finalAmount, BigDecimal discountAmount, String purchaserBy, String acceptBy, String weiChatCode, + List couponIds, String remark, String clerkSex, String clerkLevelId, String excludeHistory); + + /** + * 据店员等级和订单金额,获取店员预计收入 + * + * @param clerkId + * 店员ID + * @param croupIds + * 优惠券ID列表 + * @param placeType + * 下单类型(-1:其他类型;0:指定单;1:随机单;2:打赏单) + * @param firstOrder + * 是否是首单【0:不是,1:是】 + * @param finalAmount + * 订单支付金额 + * @return com.starry.admin.modules.order.module.vo.ClerkEstimatedRevenueVo + * @author admin + * @since 2024/7/18 16:39 + **/ + ClerkEstimatedRevenueVo getClerkEstimatedRevenue(String clerkId, List croupIds, String placeType, + String firstOrder, BigDecimal finalAmount); + + /** + * 根据店员等级和订单金额,获取店员预计收入 + * + * @param clerkId + * 店员ID + * @param placeType + * 下单类型(-1:其他类型;0:指定单;1:随机单;2:打赏单) + * @param firstOrder + * 是否是首单【0:不是,1:是】 + * @param finalAmount + * 订单支付金额 + * @return math.BigDecimal 店员预计收入 + * @author admin + * @since 2024/6/3 11:12 + **/ + BigDecimal getEstimatedRevenue(String clerkId, String placeType, String firstOrder, BigDecimal finalAmount); + + /** + * 根据店员等级,获取店员提成比例 + * + * @param clerkId + * 店员ID + * @param placeType + * 下单类型(-1:其他类型;0:指定单;1:随机单;2:打赏单) + * @param firstOrder + * 是否是首单【0:不是,1:是】 + * @return math.BigDecimal 店员预计收入 + * @author admin + * @since 2024/6/3 11:12 + **/ + Integer getEstimatedRevenueRatio(String clerkId, String placeType, String firstOrder); + + /** + * 根据订单结算状态查询订单 + * + * @param clerkId + * 店员ID + * @param orderSettlementState + * 订单结算状态(0:未结算;1:已结算) + * @return List + */ + List queryBySettlementOrder(String clerkId, String orderSettlementState); + + /** + * 查询指定店员在指定时间前完成,并且未结算工资的订单 + * + * @param clerkId + * 店员ID + * @param endTime + * 结束时间 + * @return List + */ + List listByEndTime(String clerkId, LocalDateTime endTime); + + /** + * 查询指定店员在一定时间内的订单 + * + * @param clerkId + * 店员ID + * @param startTime + * 开始时间 + * @param endTime + * 结束时间 + * @param orderStatus + * 店员状态列表 + * @return List + */ + List listByTime(String clerkId, String startTime, String endTime, List orderStatus); + + /** + * 分页查询打赏订单 + * + * @param vo + * 打赏订单查询对象 + * @return 打赏订单 + */ + IPage selectRewardOrderInfoByPage(PlayOrderRewardQueryVo vo); + + /** + * 根据订单ID查询订单信息 + * + * @param orderId + * 订单ID + * @return 订单信息 + */ + PlayOrderDetailsReturnVo selectById(String orderId); + + /** + * 查询订单 + * + * @param id + * 订单主键 + * @return 订单 + */ + PlayOrderInfoEntity selectOrderInfoById(String id); + + /** + * 查询订单列表 + * + * @param orderInfoEntity + * 订单 + * @return 订单集合 + */ + IPage selectOrderInfoPage(PlayOrderInfoQueryVo orderInfoEntity); + + /** + * 店员查询本人订单详情 + * + * @param clerkId + * 店员ID + * @param id + * 订单ID + * @return 订单详情 + */ + + PlayClerkOrderDetailsReturnVo clerkSelectOrderDetails(String clerkId, String id); + + /** + * 店员分页查询订单本人列表 + * + * @param vo + * 订单列表查询对象 + * @return 订单集合 + */ + IPage clerkSelectOrderInfoByPage(PlayClerkOrderInfoQueryVo vo); + + /** + * 店员查询自己一段时间内的订单 + * + * @param clerkId + * 店员ID + * @param startTime + * 开始时间 + * @param endTime + * 结束时间 + * @return 订单列表 + */ + List clerkSelectOrderInfoList(String clerkId, String startTime, String endTime); + + /** + * 顾客查询订单详情 + * + * @param customId + * 顾客ID + * @param orderId + * 订单ID + * @return 订单详情 + */ + PlayCustomOrderDetailsReturnVo customSelectOrderDetails(String customId, String orderId); + + /** + * 顾客分页查询订单列表 + * + * @param vo + * 订单列表查询对象 + * @return 订单集合 + */ + IPage customSelectOrderInfoByPage(PlayCustomOrderInfoQueryVo vo); + + /** + * 顾客查询本人订单列表 + * + * @param customId + * 顾客ID + * @return 订单集合 + */ + List customSelectOrderInfoByList(String customId); + + /** + * 修改订单状态为接单 只有管理员或者店员本人才能操作 + * + * @param operatorByType + * 操作人类型(0:顾客;1:店员;2:管理员) + * @param operatorBy + * 操作人ID + * @param acceptBy + * 接单人ID + * @param orderId + * 订单Id + **/ + void updateStateTo1(String operatorByType, String operatorBy, String acceptBy, String orderId); + + /** + * 修改订单状态为开始订单或者完成订单 只有管理员或者店员本人才能操作 + * + * @param operatorByType + * 操作人类型(0:顾客;1:店员;2:管理员) + * @param operatorBy + * 操作人ID + * @param orderState + * 订单状态 + * @param orderId + * 订单Id + **/ + void updateStateTo23(String operatorByType, String operatorBy, String orderState, String orderId); + + /** + * 修改订单状态为取消订单 管理员、店员、顾客均可操作 + * + * @param operatorByType + * 操作人类型(0:顾客;1:店员;2:管理员) + * @param operatorBy + * 操作人ID + * @param orderId + * 订单Id + * @param refundReason + * 订单取消原因 + * @param images + * 证据图片列表 + **/ + void updateStateTo4(String operatorByType, String operatorBy, String orderId, String refundReason, + List images); + + /** + * 修改订单 + * + * @param orderInfoEntity + * 订单 + * @return 结果 + */ + boolean update(PlayOrderInfoEntity orderInfoEntity); + + /** + * 批量删除订单 + * + * @param ids + * 需要删除的订单主键集合 + * @return 结果 + */ + int deleteOrderInfoByIds(String[] ids); + + /** + * 根据订单编号查询订单信息 + * + * @param orderNo + * 订单编号 + * @return 订单信息 + */ + PlayOrderInfoEntity queryByOrderNo(String orderNo); + + /** + * 删除订单信息 + * + * @param id + * 订单主键 + * @return 结果 + */ + int deleteOrderInfoById(String id); + + /** + * 获得订单编号 订单编号组成规则为 YYYYMMHH+4位随机数字+当日的订单顺序 + * + * @return 订单编号 + */ + String getOrderNo(); + + /** + * 查询未接单的订单 + * + * @param vo + * 查询对象 + * @param clerkId + * 店员ID + * @return 订单列表 + */ + IPage selectRandomOrderByPage(PlayOrderInfoRandomQueryVo vo, String clerkId); + + /** + * 分页获取打赏动态 + * + * @param vo + * 查询对象 + * @return 打赏动态列表 + */ + IPage selectRewardByPage(PlayRewardOrderQueryVo vo); + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/service/IPlayOrderRefundInfoService.java --- +package com.starry.admin.modules.order.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.order.module.entity.PlayOrderRefundInfoEntity; +import com.starry.admin.modules.order.module.vo.PlayOrderRefundQueryVo; +import com.starry.admin.modules.order.module.vo.PlayOrderRefundReturnVo; +import java.math.BigDecimal; + +/** + * 订单退款信息Service接口 + * + * @author admin + * @since 2024-05-09 + */ +public interface IPlayOrderRefundInfoService extends IService { + /** + * 查询订单退款信息 + * + * @param id + * 订单退款信息主键 + * @return 订单退款信息 + */ + PlayOrderRefundInfoEntity selectPlayOrderRefundInfoById(String id); + + /** + * 根据订单ID查询订单退款信息 + * + * @param orderId + * 订单ID + * @return 订单退款信息 + */ + PlayOrderRefundInfoEntity selectPlayOrderRefundInfoByOrderId(String orderId); + + /** + * 分页查询订单退款信息 + * + * @param vo + * 订单退款信息 + * @return 订单退款信息集合 + */ + IPage selectByPage(PlayOrderRefundQueryVo vo); + + /** + * 查询订单退款信息列表 + * + * @param playOrderRefundInfo + * 订单退款信息 + * @return 订单退款信息集合 + */ + IPage selectPlayOrderRefundInfoByPage(PlayOrderRefundInfoEntity playOrderRefundInfo); + + /** + * 新增退款信息 + * + * @param orderId + * 订单ID + * @param customId + * 顾客ID + * @param clerkId + * 店员ID + * @param payMethod + * 支付方式,[0:余额支付;1:微信支付,2:支付宝支付] + * @param refundType + * 退款类型【0:部分退款;1:全部退款】 + * @param refundAmount + * 退款金额 + * @param refundReason + * 退款原因 + * @param refundByType + * 退款人类型[0:顾客;1:店员;2:管理员] + * @param refundById + * 退款人ID + * @param refundState + * 退款状态[-1:异常;0:处理中;1:成功;2:关闭] + * @param reviewedRequired + * 是否需要审核,0:不需要,1:需要 + * @author xuhq + * @since 2024/8/23 17:10 + **/ + void add(String orderId, String customId, String clerkId, String payMethod, String refundType, + BigDecimal refundAmount, String refundReason, String refundByType, String refundById, String refundState, + String reviewedRequired); + + /** + * 新增订单退款信息 + * + * @param playOrderRefundInfo + * 订单退款信息 + * @return 结果 + */ + boolean create(PlayOrderRefundInfoEntity playOrderRefundInfo); + + /** + * 修改订单退款信息 + * + * @param playOrderRefundInfo + * 订单退款信息 + * @return 结果 + */ + boolean update(PlayOrderRefundInfoEntity playOrderRefundInfo); + + /** + * 批量删除订单退款信息 + * + * @param ids + * 需要删除的订单退款信息主键集合 + * @return 结果 + */ + int deletePlayOrderRefundInfoByIds(String[] ids); + + /** + * 删除订单退款信息信息 + * + * @param id + * 订单退款信息主键 + * @return 结果 + */ + int deletePlayOrderRefundInfoById(String id); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/service/impl/PlayOrderComplaintInfoServiceImpl.java --- +package com.starry.admin.modules.order.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.github.yulichang.wrapper.MPJLambdaWrapper; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity; +import com.starry.admin.modules.custom.module.entity.PlayCustomUserInfoEntity; +import com.starry.admin.modules.order.mapper.PlayOrderComplaintInfoMapper; +import com.starry.admin.modules.order.module.entity.PlayOrderComplaintInfoEntity; +import com.starry.admin.modules.order.module.entity.PlayOrderEvaluateInfoEntity; +import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity; +import com.starry.admin.modules.order.module.vo.PlayOrderComplaintQueryVo; +import com.starry.admin.modules.order.module.vo.PlayOrderComplaintReturnVo; +import com.starry.admin.modules.order.service.IPlayOrderComplaintInfoService; +import com.starry.admin.modules.personnel.service.IPlayPersonnelGroupInfoService; +import com.starry.admin.modules.weichat.service.WxCustomMpService; +import com.starry.admin.utils.SecurityUtils; +import com.starry.common.utils.IdUtils; +import java.util.Arrays; +import java.util.List; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 订单投诉信息Service业务层处理 + * + * @author admin + * @since 2024-05-07 + */ +@Service +public class PlayOrderComplaintInfoServiceImpl + extends + ServiceImpl + implements + IPlayOrderComplaintInfoService { + @Resource + private PlayOrderComplaintInfoMapper playOrderComplaintInfoMapper; + + @Resource + private PlayOrderInfoServiceImpl playOrderInfoService; + + @Resource + private IPlayPersonnelGroupInfoService playClerkGroupInfoService; + @Resource + private WxCustomMpService wxCustomMpService; + + /** + * 查询订单投诉信息 + * + * @param id + * 订单投诉信息主键 + * @return 订单投诉信息 + */ + @Override + public PlayOrderComplaintInfoEntity selectPlayOrderComplaintInfoById(String id) { + return this.baseMapper.selectById(id); + } + + @Override + public PlayOrderComplaintInfoEntity queryCustomToOrderOrderComplaintInfo(String customId, String orderId) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayOrderComplaintInfoEntity::getCustomId, customId); + lambdaQueryWrapper.eq(PlayOrderComplaintInfoEntity::getOrderId, orderId); + return this.baseMapper.selectOne(lambdaQueryWrapper); + } + + @Override + public List selectByList(PlayOrderComplaintInfoEntity entity) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + if (StrUtil.isNotBlank(entity.getClerkId())) { + lambdaQueryWrapper.eq(PlayOrderComplaintInfoEntity::getClerkId, entity.getClerkId()); + } + if (StrUtil.isNotBlank(entity.getCustomId())) { + lambdaQueryWrapper.eq(PlayOrderComplaintInfoEntity::getCustomId, entity.getCustomId()); + } + if (StrUtil.isNotBlank(entity.getOrderId())) { + lambdaQueryWrapper.eq(PlayOrderComplaintInfoEntity::getOrderId, entity.getOrderId()); + } + return this.baseMapper.selectList(lambdaQueryWrapper); + } + + @Override + public IPage selectByPage(PlayOrderComplaintQueryVo vo) { + MPJLambdaWrapper lambdaQueryWrapper = new MPJLambdaWrapper(); + // 查询主表全部字段 + lambdaQueryWrapper.selectAll(PlayOrderComplaintInfoEntity.class); + // 查询订单表 + lambdaQueryWrapper.selectAs(PlayOrderInfoEntity::getOrderNo, "orderNo") + .selectAs(PlayOrderInfoEntity::getPlaceType, "placeType") + .selectAs(PlayOrderInfoEntity::getFinalAmount, "finalAmount") + .selectAs(PlayOrderInfoEntity::getCommodityPrice, "commodityPrice") + .selectAs(PlayOrderInfoEntity::getServiceDuration, "serviceDuration") + .selectAs(PlayOrderInfoEntity::getCommodityName, "commodityName") + .selectAs(PlayOrderInfoEntity::getCommodityType, "commodityType") + .selectAs(PlayOrderInfoEntity::getCommodityId, "commodityId") + .selectAs(PlayOrderInfoEntity::getCommodityNumber, "commodityNumber"); + lambdaQueryWrapper.leftJoin(PlayOrderInfoEntity.class, PlayOrderInfoEntity::getId, + PlayOrderEvaluateInfoEntity::getOrderId); + // 查询顾客表字段 + lambdaQueryWrapper.selectAs(PlayCustomUserInfoEntity::getId, "customId") + .selectAs(PlayCustomUserInfoEntity::getAvatar, "customAvatar") + .selectAs(PlayCustomUserInfoEntity::getNickname, "customNickname"); + lambdaQueryWrapper.leftJoin(PlayCustomUserInfoEntity.class, PlayCustomUserInfoEntity::getId, + PlayOrderComplaintInfoEntity::getCustomId); + // 查询陪聊表 + lambdaQueryWrapper.selectAs(PlayClerkUserInfoEntity::getId, "clerkId") + .selectAs(PlayClerkUserInfoEntity::getAvatar, "clerkAvatar") + .selectAs(PlayClerkUserInfoEntity::getNickname, "clerkNickname"); + lambdaQueryWrapper.leftJoin(PlayClerkUserInfoEntity.class, PlayClerkUserInfoEntity::getId, + PlayOrderComplaintInfoEntity::getClerkId); + if (StrUtil.isNotBlank(vo.getClerkId())) { + lambdaQueryWrapper.eq(PlayOrderComplaintInfoEntity::getClerkId, vo.getClerkId()); + } + if (StrUtil.isNotBlank(vo.getCustomId())) { + lambdaQueryWrapper.eq(PlayOrderComplaintInfoEntity::getCustomId, vo.getCustomId()); + } + if (StrUtil.isNotBlank(vo.getOrderNo())) { + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getOrderNo, vo.getOrderNo()); + } + if (StrUtil.isNotBlank(vo.getWeiChatCode())) { + lambdaQueryWrapper.eq(PlayOrderComplaintInfoEntity::getWxChatCode, vo.getWeiChatCode()); + } + if (vo.getComplaintTime() != null && vo.getComplaintTime().size() == 2) { + lambdaQueryWrapper.between(PlayOrderComplaintInfoEntity::getComplaintTime, vo.getComplaintTime().get(0), + vo.getComplaintTime().get(1)); + } + // 加入组员的筛选 + List clerkIdList = playClerkGroupInfoService.getValidClerkIdList(SecurityUtils.getLoginUser(), null); + lambdaQueryWrapper.in(PlayOrderComplaintInfoEntity::getClerkId, clerkIdList); + + return this.baseMapper.selectJoinPage(new Page<>(vo.getPageNum(), vo.getPageSize()), + PlayOrderComplaintReturnVo.class, lambdaQueryWrapper); + } + + /** + * 查询订单投诉信息列表 + * + * @param playOrderComplaintInfo + * 订单投诉信息 + * @return 订单投诉信息 + */ + @Override + public IPage selectPlayOrderComplaintInfoByPage( + PlayOrderComplaintInfoEntity playOrderComplaintInfo) { + Page page = new Page<>(1, 10); + return this.baseMapper.selectPage(page, new LambdaQueryWrapper<>()); + } + + /** + * 新增订单投诉信息 + * + * @param playOrderComplaintInfo + * 订单投诉信息 + * @return 结果 + */ + @Override + public boolean create(PlayOrderComplaintInfoEntity playOrderComplaintInfo) { + if (allowComplaint(playOrderComplaintInfo.getCustomId(), playOrderComplaintInfo.getOrderId())) { + throw new CustomException("一个订单只能投诉一次"); + } + if (StrUtil.isBlankIfStr(playOrderComplaintInfo.getId())) { + playOrderComplaintInfo.setId(IdUtils.getUuid()); + } + PlayOrderInfoEntity orderInfo = playOrderInfoService.selectOrderInfoById(playOrderComplaintInfo.getOrderId()); + playOrderComplaintInfo.setClerkId(orderInfo.getAcceptBy()); + playOrderComplaintInfo.setCommodityId(orderInfo.getCommodityId()); + // 发送投诉消息给管理员以及客服 + wxCustomMpService.sendComplaintMessage(playOrderComplaintInfo, orderInfo); + return save(playOrderComplaintInfo); + } + + /** + * 当前订单是否已投诉 + * + * @param customerId + * 顾客ID + * @param orderId + * 订单ID + * @return true:订单已评价,false:订单未评价 + */ + public boolean allowComplaint(String customerId, String orderId) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayOrderComplaintInfoEntity::getCustomId, customerId); + lambdaQueryWrapper.eq(PlayOrderComplaintInfoEntity::getOrderId, orderId); + return this.baseMapper.selectOne(lambdaQueryWrapper) != null; + + } + + /** + * 修改订单投诉信息 + * + * @param playOrderComplaintInfo + * 订单投诉信息 + * @return 结果 + */ + @Override + public boolean update(PlayOrderComplaintInfoEntity playOrderComplaintInfo) { + return updateById(playOrderComplaintInfo); + } + + /** + * 批量删除订单投诉信息 + * + * @param ids + * 需要删除的订单投诉信息主键 + * @return 结果 + */ + @Override + public int deletePlayOrderComplaintInfoByIds(String[] ids) { + return playOrderComplaintInfoMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除订单投诉信息信息 + * + * @param id + * 订单投诉信息主键 + * @return 结果 + */ + @Override + public int deletePlayOrderComplaintInfoById(String id) { + return playOrderComplaintInfoMapper.deleteById(id); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/service/impl/PlayOrderContinueInfoServiceImpl.java --- +package com.starry.admin.modules.order.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.github.yulichang.wrapper.MPJLambdaWrapper; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity; +import com.starry.admin.modules.order.mapper.PlayOrderContinueInfoMapper; +import com.starry.admin.modules.order.module.entity.PlayOrderContinueInfoEntity; +import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity; +import com.starry.admin.modules.order.module.vo.PlayOrderContinueQueryVo; +import com.starry.admin.modules.order.module.vo.PlayOrderContinueReturnVo; +import com.starry.admin.modules.order.module.vo.PlayOrderReviewStateEditVo; +import com.starry.admin.modules.order.service.IPlayOrderContinueInfoService; +import com.starry.admin.modules.personnel.service.IPlayPersonnelGroupInfoService; +import com.starry.admin.utils.SecurityUtils; +import com.starry.common.context.CustomSecurityContextHolder; +import com.starry.common.utils.IdUtils; +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.List; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 订单续单信息Service业务层处理 + * + * @author admin + * @since 2024-05-10 + */ +@Service +public class PlayOrderContinueInfoServiceImpl + extends + ServiceImpl + implements + IPlayOrderContinueInfoService { + @Resource + private PlayOrderContinueInfoMapper playOrderContinueInfoMapper; + + @Resource + private IPlayPersonnelGroupInfoService playClerkGroupInfoService; + + @Override + public PlayOrderContinueInfoEntity selectPlayOrderId(String orderId) { + MPJLambdaWrapper lambdaQueryWrapper = new MPJLambdaWrapper<>(); + lambdaQueryWrapper.eq(PlayOrderContinueInfoEntity::getOrderId, orderId); + return playOrderContinueInfoMapper.selectOne(lambdaQueryWrapper); + } + + /** + * 查询订单续单信息 + * + * @param id + * 订单续单信息主键 + * @return 订单续单信息 + */ + @Override + public PlayOrderContinueInfoEntity selectPlayOrderContinueInfoById(String id) { + PlayOrderContinueInfoEntity entity = this.baseMapper.selectById(id); + if (entity != null) { + return entity; + } + throw new CustomException("续单申请不存在"); + } + + @Override + public void updateReviewState(PlayOrderReviewStateEditVo vo) { + PlayOrderContinueInfoEntity entity = this.selectPlayOrderContinueInfoById(vo.getId()); + entity.setReviewedState(vo.getReviewState()); + entity.setReviewedRemark(vo.getRemark()); + entity.setReviewedBy(CustomSecurityContextHolder.getUserId()); + entity.setReviewedTime(LocalDateTime.now()); + this.baseMapper.updateById(entity); + // 添加订单信息 + if ("1".equals(vo.getReviewState())) { + + } + } + + @Override + public IPage selectPlayByPage(PlayOrderContinueQueryVo vo) { + MPJLambdaWrapper lambdaQueryWrapper = new MPJLambdaWrapper<>(); + // 主表 + lambdaQueryWrapper.selectAll(PlayOrderContinueInfoEntity.class); + lambdaQueryWrapper.selectAs(PlayClerkUserInfoEntity::getId, "clerkId") + .selectAs(PlayClerkUserInfoEntity::getAvatar, "clerkAvatar") + .selectAs(PlayClerkUserInfoEntity::getNickname, "clerkNickname") + .selectAs(PlayClerkUserInfoEntity::getSex, "clerkSex"); + lambdaQueryWrapper.leftJoin(PlayClerkUserInfoEntity.class, PlayClerkUserInfoEntity::getId, + PlayOrderContinueInfoEntity::getClerkId); + lambdaQueryWrapper.leftJoin(PlayOrderInfoEntity.class, PlayOrderInfoEntity::getId, + PlayOrderContinueInfoEntity::getOrderId); + if (StrUtil.isNotBlank(vo.getCustomId())) { + lambdaQueryWrapper.like(PlayOrderContinueInfoEntity::getCustomId, vo.getCustomId()); + } + if (StrUtil.isNotBlank(vo.getClerkId())) { + lambdaQueryWrapper.like(PlayClerkUserInfoEntity::getId, vo.getClerkId()); + } + if (StrUtil.isNotBlank(vo.getOrderNo())) { + lambdaQueryWrapper.like(PlayClerkUserInfoEntity::getNickname, vo.getNickname()); + } + if (StrUtil.isNotBlank(vo.getReviewState())) { + lambdaQueryWrapper.like(PlayOrderContinueInfoEntity::getReviewedState, vo.getReviewState()); + } + if (vo.getContinueTime() != null && vo.getContinueTime().size() == 2) { + lambdaQueryWrapper.between(PlayOrderContinueInfoEntity::getContinueTime, vo.getContinueTime().get(0), + vo.getContinueTime().get(1)); + } + if (vo.getContinueTime() != null && vo.getContinueTime().size() == 2) { + lambdaQueryWrapper.between(PlayOrderContinueInfoEntity::getContinueTime, vo.getContinueTime().get(0), + vo.getContinueTime().get(1)); + } + // 加入组员的筛选 + List clerkIdList = playClerkGroupInfoService.getValidClerkIdList(SecurityUtils.getLoginUser(), null); + lambdaQueryWrapper.in(PlayOrderContinueInfoEntity::getClerkId, clerkIdList); + + return this.baseMapper.selectJoinPage(new Page<>(vo.getPageNum(), vo.getPageSize()), + PlayOrderContinueReturnVo.class, lambdaQueryWrapper); + } + + /** + * 查询订单续单信息列表 + * + * @param playOrderContinueInfo + * 订单续单信息 + * @return 订单续单信息 + */ + @Override + public IPage selectPlayOrderContinueInfoByPage( + PlayOrderContinueInfoEntity playOrderContinueInfo) { + Page page = new Page<>(1, 10); + return this.baseMapper.selectPage(page, new LambdaQueryWrapper<>()); + } + + /** + * 新增订单续单信息 + * + * @param playOrderContinueInfo + * 订单续单信息 + * @return 结果 + */ + @Override + public boolean create(PlayOrderContinueInfoEntity playOrderContinueInfo) { + if (StrUtil.isBlankIfStr(playOrderContinueInfo.getId())) { + playOrderContinueInfo.setId(IdUtils.getUuid()); + } + return save(playOrderContinueInfo); + } + + /** + * 修改订单续单信息 + * + * @param playOrderContinueInfo + * 订单续单信息 + * @return 结果 + */ + @Override + public boolean update(PlayOrderContinueInfoEntity playOrderContinueInfo) { + return updateById(playOrderContinueInfo); + } + + /** + * 批量删除订单续单信息 + * + * @param ids + * 需要删除的订单续单信息主键 + * @return 结果 + */ + @Override + public int deletePlayOrderContinueInfoByIds(String[] ids) { + return playOrderContinueInfoMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除订单续单信息信息 + * + * @param id + * 订单续单信息主键 + * @return 结果 + */ + @Override + public int deletePlayOrderContinueInfoById(String id) { + return playOrderContinueInfoMapper.deleteById(id); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/service/impl/PlayOrderEvaluateInfoServiceImpl.java --- +package com.starry.admin.modules.order.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.github.yulichang.wrapper.MPJLambdaWrapper; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity; +import com.starry.admin.modules.custom.module.entity.PlayCustomUserInfoEntity; +import com.starry.admin.modules.order.mapper.PlayOrderEvaluateInfoMapper; +import com.starry.admin.modules.order.module.entity.PlayOrderEvaluateInfoEntity; +import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity; +import com.starry.admin.modules.order.module.vo.PlayOrderEvaluateQueryVo; +import com.starry.admin.modules.order.module.vo.PlayOrderEvaluateReturnVo; +import com.starry.admin.modules.order.service.IPlayOrderEvaluateInfoService; +import com.starry.admin.modules.personnel.service.IPlayPersonnelGroupInfoService; +import com.starry.admin.utils.SecurityUtils; +import com.starry.common.utils.IdUtils; +import com.starry.common.utils.StringUtils; +import java.util.Arrays; +import java.util.List; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 订单评价信息Service业务层处理 + * + * @author admin + * @since 2024-05-07 + */ +@Service +public class PlayOrderEvaluateInfoServiceImpl + extends + ServiceImpl + implements + IPlayOrderEvaluateInfoService { + @Resource + private PlayOrderEvaluateInfoMapper playOrderEvaluateInfoMapper; + + @Resource + private PlayOrderInfoServiceImpl playOrderInfoService; + + @Resource + private IPlayPersonnelGroupInfoService playClerkGroupInfoService; + + @Override + public PlayOrderEvaluateInfoEntity queryCustomToOrderEvaluateInfo(String customId, String orderId) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayOrderEvaluateInfoEntity::getCustomId, customId); + lambdaQueryWrapper.eq(PlayOrderEvaluateInfoEntity::getOrderId, orderId); + return this.baseMapper.selectOne(lambdaQueryWrapper); + } + + /** + * 查询订单评价信息 + * + * @param id + * 订单评价信息主键 + * @return 订单评价信息 + */ + @Override + public PlayOrderEvaluateInfoEntity selectPlayOrderEvaluateInfoById(String id) { + PlayOrderEvaluateInfoEntity entity = this.baseMapper.selectById(id); + if (entity == null) { + throw new CustomException("评价信息不存在"); + } + return this.baseMapper.selectById(id); + } + + @Override + public List selectByList(PlayOrderEvaluateInfoEntity entity) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + if (StrUtil.isNotBlank(entity.getClerkId())) { + lambdaQueryWrapper.eq(PlayOrderEvaluateInfoEntity::getClerkId, entity.getClerkId()); + } + if (StrUtil.isNotBlank(entity.getCustomId())) { + lambdaQueryWrapper.eq(PlayOrderEvaluateInfoEntity::getCustomId, entity.getCustomId()); + } + if (StrUtil.isNotBlank(entity.getOrderId())) { + lambdaQueryWrapper.eq(PlayOrderEvaluateInfoEntity::getOrderId, entity.getOrderId()); + } + return this.baseMapper.selectList(lambdaQueryWrapper); + } + + @Override + public IPage selectByPage(PlayOrderEvaluateQueryVo vo) { + MPJLambdaWrapper lambdaQueryWrapper = new MPJLambdaWrapper(); + // 查询主表全部字段 + lambdaQueryWrapper.selectAll(PlayOrderEvaluateInfoEntity.class); + + // 查询顾客表字段 + lambdaQueryWrapper.selectAs(PlayCustomUserInfoEntity::getId, "customId") + .selectAs(PlayCustomUserInfoEntity::getAvatar, "customAvatar") + .selectAs(PlayCustomUserInfoEntity::getNickname, "customNickname"); + lambdaQueryWrapper.leftJoin(PlayCustomUserInfoEntity.class, PlayCustomUserInfoEntity::getId, + PlayOrderEvaluateInfoEntity::getCustomId); + // 查询店员表字典 + lambdaQueryWrapper.selectAs(PlayClerkUserInfoEntity::getId, "clerkId") + .selectAs(PlayClerkUserInfoEntity::getAvatar, "clerkAvatar") + .selectAs(PlayClerkUserInfoEntity::getNickname, "clerkNickname"); + lambdaQueryWrapper.leftJoin(PlayClerkUserInfoEntity.class, PlayClerkUserInfoEntity::getId, + PlayOrderEvaluateInfoEntity::getClerkId); + // 查询订单表 + lambdaQueryWrapper.selectAs(PlayOrderInfoEntity::getOrderNo, "orderNo") + .selectAs(PlayOrderInfoEntity::getPlaceType, "placeType") + .selectAs(PlayOrderInfoEntity::getFinalAmount, "finalAmount") + .selectAs(PlayOrderInfoEntity::getCommodityPrice, "commodityPrice") + .selectAs(PlayOrderInfoEntity::getServiceDuration, "serviceDuration") + .selectAs(PlayOrderInfoEntity::getCommodityName, "commodityName") + .selectAs(PlayOrderInfoEntity::getCommodityType, "commodityType") + .selectAs(PlayOrderInfoEntity::getCommodityId, "commodityId") + .selectAs(PlayOrderInfoEntity::getCommodityNumber, "commodityNumber"); + lambdaQueryWrapper.leftJoin(PlayOrderInfoEntity.class, PlayOrderInfoEntity::getId, + PlayOrderEvaluateInfoEntity::getOrderId); + + if (StrUtil.isNotBlank(vo.getClerkId())) { + lambdaQueryWrapper.eq(PlayOrderEvaluateInfoEntity::getClerkId, vo.getClerkId()); + } + if (StrUtil.isNotBlank(vo.getCustomId())) { + lambdaQueryWrapper.eq(PlayOrderEvaluateInfoEntity::getCustomId, vo.getCustomId()); + } + if (StrUtil.isNotBlank(vo.getId())) { + lambdaQueryWrapper.eq(PlayOrderEvaluateInfoEntity::getId, vo.getId()); + } + if (StrUtil.isNotBlank(vo.getEvaluateCon())) { + lambdaQueryWrapper.like(PlayOrderEvaluateInfoEntity::getEvaluateCon, vo.getEvaluateCon()); + } + if (StrUtil.isNotBlank(vo.getAnonymous())) { + lambdaQueryWrapper.eq(PlayOrderEvaluateInfoEntity::getAnonymous, vo.getAnonymous()); + } + if (StrUtil.isNotBlank(vo.getHidden())) { + lambdaQueryWrapper.eq(PlayOrderEvaluateInfoEntity::getHidden, vo.getHidden()); + } + if (vo.getEvaluateTime() != null && vo.getEvaluateTime().size() == 2) { + lambdaQueryWrapper.between(PlayOrderEvaluateInfoEntity::getEvaluateTime, vo.getEvaluateTime().get(0), + vo.getEvaluateTime().get(1)); + } + // 加入组员的筛选 + if (StringUtils.isEmpty(vo.getClerkId())) { + List clerkIdList = playClerkGroupInfoService.getValidClerkIdList(SecurityUtils.getLoginUser(), + null); + lambdaQueryWrapper.in(PlayOrderEvaluateInfoEntity::getClerkId, clerkIdList); + } + + return this.baseMapper.selectJoinPage(new Page<>(vo.getPageNum(), vo.getPageSize()), + PlayOrderEvaluateReturnVo.class, lambdaQueryWrapper); + } + + /** + * 查询订单评价信息列表 + * + * @param playOrderEvaluateInfo + * 订单评价信息 + * @return 订单评价信息 + */ + @Override + public IPage selectPlayOrderEvaluateInfoByPage( + PlayOrderEvaluateInfoEntity playOrderEvaluateInfo) { + Page page = new Page<>(1, 10); + return this.baseMapper.selectPage(page, new LambdaQueryWrapper<>()); + } + + /** + * 新增订单评价信息 + * + * @param playOrderEvaluateInfo + * 订单评价信息 + * @return 结果 + */ + @Override + public boolean create(PlayOrderEvaluateInfoEntity playOrderEvaluateInfo) { + if (allowComplaint(playOrderEvaluateInfo.getCustomId(), playOrderEvaluateInfo.getOrderId())) { + throw new CustomException("一个订单只能评价一次"); + } + if (StrUtil.isBlankIfStr(playOrderEvaluateInfo.getId())) { + playOrderEvaluateInfo.setId(IdUtils.getUuid()); + } + PlayOrderInfoEntity orderInfo = playOrderInfoService.selectOrderInfoById(playOrderEvaluateInfo.getOrderId()); + playOrderEvaluateInfo.setClerkId(orderInfo.getAcceptBy()); + playOrderEvaluateInfo.setCommodityId(orderInfo.getCommodityId()); + return save(playOrderEvaluateInfo); + } + + /** + * 当前订单是否已评价 + * + * @param customerId + * 顾客ID + * @param orderId + * 订单ID + * @return true:订单已评价,false:订单未评价 + */ + public boolean allowComplaint(String customerId, String orderId) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayOrderEvaluateInfoEntity::getCustomId, customerId); + lambdaQueryWrapper.eq(PlayOrderEvaluateInfoEntity::getOrderId, orderId); + return this.baseMapper.selectOne(lambdaQueryWrapper) != null; + + } + + /** + * 修改订单评价信息 + * + * @param playOrderEvaluateInfo + * 订单评价信息 + * @return 结果 + */ + @Override + public boolean update(PlayOrderEvaluateInfoEntity playOrderEvaluateInfo) { + return updateById(playOrderEvaluateInfo); + } + + /** + * 批量删除订单评价信息 + * + * @param ids + * 需要删除的订单评价信息主键 + * @return 结果 + */ + @Override + public int deletePlayOrderEvaluateInfoByIds(String[] ids) { + return playOrderEvaluateInfoMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除订单评价信息信息 + * + * @param id + * 订单评价信息主键 + * @return 结果 + */ + @Override + public int deletePlayOrderEvaluateInfoById(String id) { + return playOrderEvaluateInfoMapper.deleteById(id); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/service/impl/PlayOrderInfoServiceImpl.java --- +package com.starry.admin.modules.order.service.impl; + +import static com.starry.admin.modules.order.module.constant.OrderConstant.ORDER_STATUS_2; +import static com.starry.admin.modules.order.module.constant.OrderConstant.ORDER_STATUS_3; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.github.yulichang.wrapper.MPJLambdaWrapper; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.clerk.module.entity.PlayClerkLevelInfoEntity; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity; +import com.starry.admin.modules.clerk.service.IPlayClerkLevelInfoService; +import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService; +import com.starry.admin.modules.custom.module.entity.PlayCustomLevelInfoEntity; +import com.starry.admin.modules.custom.module.entity.PlayCustomUserInfoEntity; +import com.starry.admin.modules.custom.service.IPlayCustomUserInfoService; +import com.starry.admin.modules.order.mapper.PlayOrderInfoMapper; +import com.starry.admin.modules.order.module.constant.OrderConstant; +import com.starry.admin.modules.order.module.entity.PlayOrderComplaintInfoEntity; +import com.starry.admin.modules.order.module.entity.PlayOrderEvaluateInfoEntity; +import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity; +import com.starry.admin.modules.order.module.entity.PlayOrderRefundInfoEntity; +import com.starry.admin.modules.order.module.vo.*; +import com.starry.admin.modules.order.service.IPlayOrderComplaintInfoService; +import com.starry.admin.modules.order.service.IPlayOrderEvaluateInfoService; +import com.starry.admin.modules.order.service.IPlayOrderInfoService; +import com.starry.admin.modules.order.service.IPlayOrderRefundInfoService; +import com.starry.admin.modules.personnel.service.IPlayPersonnelGroupInfoService; +import com.starry.admin.modules.shop.module.vo.PlayCouponDetailsReturnVo; +import com.starry.admin.modules.shop.service.IPlayCouponDetailsService; +import com.starry.admin.modules.weichat.entity.order.*; +import com.starry.admin.modules.weichat.service.WxCustomMpService; +import com.starry.admin.utils.SecurityUtils; +import com.starry.common.utils.ConvertUtil; +import com.starry.common.utils.IdUtils; +import com.starry.common.utils.StringUtils; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.stream.Collectors; +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * 订单Service业务层处理 + * + * @author admin + * @since 2024-03-20 + */ +@Slf4j +@Service +public class PlayOrderInfoServiceImpl extends ServiceImpl + implements + IPlayOrderInfoService { + @Resource + private PlayOrderInfoMapper orderInfoMapper; + @Resource + private IPlayClerkUserInfoService playClerkUserInfoService; + @Resource + private IPlayCustomUserInfoService playCustomUserInfoService; + @Resource + private IPlayCustomUserInfoService userInfoService; + @Resource + private IPlayOrderRefundInfoService playOrderRefundInfoService; + @Resource + private IPlayOrderEvaluateInfoService playOrderEvaluateInfoService; + @Resource + private IPlayOrderComplaintInfoService playOrderComplaintInfoService; + @Resource + private IPlayPersonnelGroupInfoService playClerkGroupInfoService; + + @Resource + private IPlayCouponDetailsService playCouponDetailsService; + + @Resource + private WxCustomMpService wxCustomMpService; + + @Resource + private IPlayCustomUserInfoService customUserInfoService; + + @Resource + private IPlayClerkLevelInfoService playClerkLevelInfoService; + + @Override + public List getTotalOrderInfo(String tenantId) { + MPJLambdaWrapper lambdaWrapper = new MPJLambdaWrapper<>(); + lambdaWrapper.eq(PlayOrderInfoEntity::getTenantId, tenantId); + return this.baseMapper.selectList(lambdaWrapper); + } + + @Override + public void createOrderInfo(String orderId, String orderNo, String orderState, String orderType, String placeType, + String rewardType, String firstOrder, String commodityId, String commodityType, BigDecimal commodityPrice, + String serviceDuration, String commodityName, String commodityNumber, BigDecimal orderMoney, + BigDecimal finalAmount, BigDecimal discountAmount, String purchaserBy, String acceptBy, String weiChatCode, + List couponIds, String remark, String clerkSex, String clerkLevelId, String excludeHistory) { + PlayOrderInfoEntity entity = new PlayOrderInfoEntity(); + entity.setId(orderId); + entity.setOrderNo(orderNo); + entity.setOrderStatus(orderState); + entity.setOrderType(orderType); + entity.setPlaceType(placeType); + entity.setRewardType(rewardType); + entity.setFirstOrder(firstOrder); + entity.setRefundType("0"); + entity.setCommodityId(commodityId); + entity.setCommodityType(commodityType); + entity.setCommodityPrice(commodityPrice); + entity.setServiceDuration(serviceDuration); + entity.setCommodityName(commodityName); + entity.setCommodityNumber(commodityNumber); + entity.setBackendEntry("0"); + entity.setPayMethod("0"); + entity.setOrderMoney(orderMoney); + entity.setFinalAmount(finalAmount); + entity.setDiscountAmount(discountAmount); + entity.setWeiChatCode(weiChatCode); + entity.setRemark(remark); + entity.setOrderSettlementState("0"); + entity.setOrdersExpiredState("0"); + entity.setPurchaserBy(purchaserBy); + entity.setPurchaserTime(LocalDateTime.now()); + entity.setCouponIds(couponIds); + entity.setUseCoupon(couponIds != null && !couponIds.isEmpty() ? "1" : "0"); + if ("1".equals(placeType)) { + entity.setSex(clerkSex); + entity.setLevelId(clerkLevelId); + entity.setExcludeHistory(excludeHistory); + } + if (StrUtil.isNotBlank(acceptBy)) { + entity.setAcceptBy(acceptBy); + ClerkEstimatedRevenueVo estimatedRevenueVo = getClerkEstimatedRevenue(acceptBy, couponIds, placeType, + firstOrder, finalAmount); + entity.setEstimatedRevenue(estimatedRevenueVo.getRevenueAmount()); + entity.setEstimatedRevenueRatio(estimatedRevenueVo.getRevenueRatio()); + } + // 如果订单是打赏单,订单直接完成 + if ("2".equals(placeType)) { + entity.setAcceptTime(LocalDateTime.now()); + entity.setOrderStartTime(LocalDateTime.now()); + entity.setOrderEndTime(LocalDateTime.now()); + } + // 修改顾客下单信息 + userInfoService.saveOrderInfo(entity); + // 保存订单 + this.baseMapper.insert(entity); + // 修改优惠券状态 + playCouponDetailsService.updateCouponUseStateByIds(couponIds, "2"); + } + + @Override + public ClerkEstimatedRevenueVo getClerkEstimatedRevenue(String clerkId, List croupIds, String placeType, + String firstOrder, BigDecimal finalAmount) { + PlayClerkLevelInfoEntity entity = playClerkUserInfoService.queryLevelCommission(clerkId); + ClerkEstimatedRevenueVo estimatedRevenueVo = new ClerkEstimatedRevenueVo(); + switch (placeType) { + case "0" : { + if ("1".equals(firstOrder)) { + estimatedRevenueVo.setRevenueRatio(entity.getFirstRegularRatio()); + estimatedRevenueVo + .setRevenueAmount( + finalAmount + .multiply(new BigDecimal(entity.getFirstRegularRatio()) + .divide(new BigDecimal(100), 4, RoundingMode.HALF_UP)) + .setScale(2, RoundingMode.HALF_UP)); + } else { + estimatedRevenueVo.setRevenueRatio(entity.getNotFirstRegularRatio()); + estimatedRevenueVo + .setRevenueAmount(finalAmount + .multiply(new BigDecimal(entity.getNotFirstRegularRatio()) + .divide(new BigDecimal(100), 4, RoundingMode.HALF_UP)) + .setScale(2, RoundingMode.HALF_UP)); + } + break; + } + case "1" : { + if ("1".equals(firstOrder)) { + estimatedRevenueVo.setRevenueRatio(entity.getFirstRandomRadio()); + estimatedRevenueVo + .setRevenueAmount( + finalAmount + .multiply(new BigDecimal(entity.getFirstRandomRadio()) + .divide(new BigDecimal(100), 4, RoundingMode.HALF_UP)) + .setScale(2, RoundingMode.HALF_UP)); + } else { + estimatedRevenueVo.setRevenueRatio(entity.getNotFirstRandomRadio()); + estimatedRevenueVo + .setRevenueAmount(finalAmount + .multiply(new BigDecimal(entity.getNotFirstRandomRadio()) + .divide(new BigDecimal(100), 4, RoundingMode.HALF_UP)) + .setScale(2, RoundingMode.HALF_UP)); + } + break; + } + case "2" : { + if ("1".equals(firstOrder)) { + estimatedRevenueVo.setRevenueRatio(entity.getFirstRewardRatio()); + estimatedRevenueVo + .setRevenueAmount( + finalAmount + .multiply(new BigDecimal(entity.getFirstRewardRatio()) + .divide(new BigDecimal(100), 4, RoundingMode.HALF_UP)) + .setScale(2, RoundingMode.HALF_UP)); + } else { + estimatedRevenueVo.setRevenueRatio(entity.getNotFirstRewardRatio()); + estimatedRevenueVo + .setRevenueAmount(finalAmount + .multiply(new BigDecimal(entity.getNotFirstRewardRatio()) + .divide(new BigDecimal(100), 4, RoundingMode.HALF_UP)) + .setScale(2, RoundingMode.HALF_UP)); + } + break; + } + case "-1" : { + log.error("下单类型异常,placeType={}", placeType); + estimatedRevenueVo.setRevenueAmount(finalAmount); + estimatedRevenueVo.setRevenueRatio(100); + break; + } + default : { + log.error("下单类型错误,placeType={}", placeType); + estimatedRevenueVo.setRevenueAmount(finalAmount); + estimatedRevenueVo.setRevenueRatio(100); + break; + } + } + + // 如果优惠券不由店铺承担,那么店员预计收入减去优惠金额 + for (String croupId : croupIds) { + PlayCouponDetailsReturnVo couponInfo = playCouponDetailsService.selectPlayCouponDetailsById(croupId); + if ("0".equals(couponInfo.getAttributionDiscounts())) { + BigDecimal revenueAmount = estimatedRevenueVo.getRevenueAmount(); + if ("0".equals(couponInfo.getDiscountType())) { + revenueAmount = revenueAmount.subtract(couponInfo.getDiscountAmount()); + } else { + revenueAmount = revenueAmount.subtract(revenueAmount.subtract(couponInfo.getDiscountAmount())); + } + log.debug("优惠券ID={},优惠券类型={},优惠金额={},优惠前金额={},优惠前金额={}", croupId, couponInfo.getDiscountType(), + couponInfo.getDiscountAmount(), estimatedRevenueVo.getRevenueAmount(), revenueAmount); + estimatedRevenueVo.setRevenueAmount(revenueAmount); + } + } + return estimatedRevenueVo; + } + + /** + * 根据店员等级和订单金额,获取店员预计收入 + * + * @param clerkId + * 店员ID + * @param placeType + * 下单类型(-1:其他类型;0:指定单;1:随机单;2:打赏单) + * @param firstOrder + * 是否是首单【0:不是,1:是】 + * @param finalAmount + * 订单支付金额 + * @return math.BigDecimal 店员预计收入 + * @author admin + * @since 2024/6/3 11:12 + **/ + @Override + public BigDecimal getEstimatedRevenue(String clerkId, String placeType, String firstOrder, BigDecimal finalAmount) { + PlayClerkLevelInfoEntity entity = playClerkUserInfoService.queryLevelCommission(clerkId); + switch (placeType) { + case "0" : { + if ("1".equals(firstOrder)) { + return finalAmount.multiply(new BigDecimal(entity.getFirstRegularRatio()) + .divide(new BigDecimal(100), 4, RoundingMode.HALF_UP)).setScale(2, RoundingMode.HALF_UP); + } else { + return finalAmount.multiply(new BigDecimal(entity.getNotFirstRegularRatio()) + .divide(new BigDecimal(100), 4, RoundingMode.HALF_UP)).setScale(2, RoundingMode.HALF_UP); + } + } + case "1" : { + if ("1".equals(firstOrder)) { + return finalAmount.multiply(new BigDecimal(entity.getFirstRandomRadio()).divide(new BigDecimal(100), + 4, RoundingMode.HALF_UP)).setScale(2, RoundingMode.HALF_UP); + } else { + return finalAmount.multiply(new BigDecimal(entity.getNotFirstRandomRadio()) + .divide(new BigDecimal(100), 4, RoundingMode.HALF_UP)).setScale(2, RoundingMode.HALF_UP); + } + } + case "2" : { + if ("1".equals(firstOrder)) { + return finalAmount.multiply(new BigDecimal(entity.getFirstRewardRatio()).divide(new BigDecimal(100), + 4, RoundingMode.HALF_UP)).setScale(2, RoundingMode.HALF_UP); + } else { + return finalAmount.multiply(new BigDecimal(entity.getNotFirstRewardRatio()) + .divide(new BigDecimal(100), 4, RoundingMode.HALF_UP)).setScale(2, RoundingMode.HALF_UP); + } + } + case "-1" : { + log.error("下单类型异常,placeType={}", placeType); + return finalAmount; + } + default : { + log.error("下单类型错误,placeType={}", placeType); + return finalAmount; + } + } + } + + @Override + public Integer getEstimatedRevenueRatio(String clerkId, String placeType, String firstOrder) { + PlayClerkLevelInfoEntity entity = playClerkUserInfoService.queryLevelCommission(clerkId); + switch (placeType) { + case "0" : { + if ("1".equals(firstOrder)) { + return entity.getFirstRegularRatio(); + } else { + return entity.getNotFirstRegularRatio(); + } + } + case "1" : { + if ("1".equals(firstOrder)) { + return entity.getFirstRandomRadio(); + } else { + return entity.getNotFirstRandomRadio(); + } + } + case "2" : { + if ("1".equals(firstOrder)) { + return entity.getFirstRewardRatio(); + } else { + return entity.getNotFirstRewardRatio(); + } + } + case "-1" : { + log.error("下单类型异常,placeType={}", placeType); + return 100; + } + default : { + log.error("下单类型错误,placeType={}", placeType); + return 100; + } + } + } + + /** + * 新增充值订单 + * + * @param orderId + * 订单编号 + * @param orderMoney + * 订单金额 + * @param finalAmount + * 订单最终金额(支付金额) + * @param purchaserBy + * 下单人ID + */ + + @Override + public void createRechargeOrder(String orderId, BigDecimal orderMoney, BigDecimal finalAmount, String purchaserBy) { + PlayOrderInfoEntity entity = new PlayOrderInfoEntity(IdUtils.getUuid(), ORDER_STATUS_3, "0", "-1"); + entity.setOrderNo(orderId); + entity.setId(IdUtils.getUuid()); + entity.setOrderMoney(orderMoney); + entity.setFinalAmount(finalAmount); + entity.setPurchaserBy(purchaserBy); + entity.setPayMethod("1"); + entity.setPayState("0"); + this.baseMapper.insert(entity); + } + + /** + * 订单编号由2部分组成 第一部分是是时间,长度8位 第二部分是随机数,长度4位 + * + * @return 订单编号 + */ + @Override + public String getOrderNo() { + String one = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")); + String two = String.valueOf(new Random().nextInt(9000)); + return one + two; + } + + @Override + public List queryBySettlementOrder(String clerkId, String orderSettlementState) { + MPJLambdaWrapper lambdaQueryWrapper = new MPJLambdaWrapper<>(); + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getAcceptBy, clerkId); + if (StrUtil.isNotBlank(orderSettlementState)) { + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getOrderSettlementState, orderSettlementState); + } + + return this.baseMapper.selectList(lambdaQueryWrapper); + } + + @Override + public List listByEndTime(String clerkId, LocalDateTime endTime) { + MPJLambdaWrapper lambdaQueryWrapper = new MPJLambdaWrapper<>(); + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getAcceptBy, clerkId); + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getOrderStatus, "3"); + lambdaQueryWrapper.lt(PlayOrderInfoEntity::getOrderEndTime, endTime); + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getOrderSettlementState, "0"); + return this.baseMapper.selectList(lambdaQueryWrapper); + } + + @Override + public List listByTime(String clerkId, String startTime, String endTime, + List orderStatus) { + MPJLambdaWrapper lambdaQueryWrapper = new MPJLambdaWrapper<>(); + if (StrUtil.isNotEmpty(clerkId)) { + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getAcceptBy, clerkId); + } + if (orderStatus != null && !orderStatus.isEmpty()) { + lambdaQueryWrapper.in(PlayOrderInfoEntity::getOrderStatus, orderStatus); + } + lambdaQueryWrapper.between(PlayOrderInfoEntity::getPurchaserTime, startTime, endTime); + return this.baseMapper.selectList(lambdaQueryWrapper); + } + + @Override + public IPage selectRewardOrderInfoByPage(PlayOrderRewardQueryVo vo) { + MPJLambdaWrapper lambdaQueryWrapper = new MPJLambdaWrapper<>(); + // 查询主表全部字段 + lambdaQueryWrapper.selectAll(PlayOrderInfoEntity.class); + // 查询顾客表 + lambdaQueryWrapper.selectAs(PlayCustomUserInfoEntity::getId, "customId") + .selectAs(PlayCustomUserInfoEntity::getAvatar, "customAvatar") + .selectAs(PlayCustomUserInfoEntity::getNickname, "customNickname"); + lambdaQueryWrapper.leftJoin(PlayCustomUserInfoEntity.class, PlayCustomUserInfoEntity::getId, + PlayOrderInfoEntity::getPurchaserBy).leftJoin(PlayClerkUserInfoEntity.class, + PlayClerkUserInfoEntity::getId, PlayOrderInfoEntity::getAcceptBy); + // 查询陪聊表 + lambdaQueryWrapper.selectAs(PlayClerkUserInfoEntity::getId, "clerkId") + .selectAs(PlayClerkUserInfoEntity::getAvatar, "clerkAvatar") + .selectAs(PlayClerkUserInfoEntity::getNickname, "clerkNickname"); + + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getPlaceType, "2"); + if (StrUtil.isNotBlank(vo.getRewardType())) { + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getRewardType, vo.getRewardType()); + } + if (StrUtil.isNotBlank(vo.getAcceptBy())) { + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getAcceptBy, vo.getAcceptBy()); + } + if (StrUtil.isNotBlank(vo.getPurchaserBy())) { + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getPurchaserBy, vo.getPurchaserBy()); + } + if (vo.getPurchaserTime() != null && vo.getPurchaserTime().size() == 2) { + lambdaQueryWrapper.between(PlayOrderInfoEntity::getPurchaserTime, vo.getPurchaserTime().get(0), + vo.getPurchaserTime().get(1)); + } + lambdaQueryWrapper.orderByDesc(PlayOrderInfoEntity::getPurchaserTime); + // 加入组员的筛选 + List clerkIdList = playClerkGroupInfoService.getValidClerkIdList(SecurityUtils.getLoginUser(), null); + lambdaQueryWrapper.in(PlayOrderInfoEntity::getAcceptBy, clerkIdList); + + return this.baseMapper.selectJoinPage(new Page<>(vo.getPageNum(), vo.getPageSize()), + PlayOrderRewardReturnVo.class, lambdaQueryWrapper); + + } + + @Override + public IPage selectRandomOrderByPage(PlayOrderInfoRandomQueryVo vo, String clerkId) { + PlayClerkUserInfoEntity entity = playClerkUserInfoService.getById(clerkId); + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getPlaceType, "1"); + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getOrderStatus, "0"); + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getLevelId, entity.getLevelId()); + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getSex, entity.getSex()); + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getExcludeHistory, "0") + .or(wrapper1 -> wrapper1.ne(PlayOrderInfoEntity::getAcceptBy, clerkId) + .and(wrapper2 -> wrapper2.eq(PlayOrderInfoEntity::getExcludeHistory, 1))); + return this.baseMapper.selectPage(new Page<>(vo.getPageNum(), vo.getPageSize()), lambdaQueryWrapper); + } + + @Override + public IPage selectRewardByPage(PlayRewardOrderQueryVo vo) { + MPJLambdaWrapper lambdaQueryWrapper = new MPJLambdaWrapper<>(); + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getPlaceType, "2"); + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getRefundType, "0"); + lambdaQueryWrapper.selectAll(PlayOrderInfoEntity.class); + lambdaQueryWrapper.orderByDesc(PlayOrderInfoEntity::getPurchaserTime); + // 查询陪聊表 + lambdaQueryWrapper.selectAs(PlayClerkUserInfoEntity::getId, "clerkId") + .selectAs(PlayClerkUserInfoEntity::getAvatar, "clerkAvatar") + .selectAs(PlayClerkUserInfoEntity::getNickname, "clerkNickname"); + // 子表 + lambdaQueryWrapper.leftJoin(PlayCustomUserInfoEntity.class, PlayCustomUserInfoEntity::getId, + PlayOrderInfoEntity::getPurchaserBy).leftJoin(PlayClerkUserInfoEntity.class, + PlayClerkUserInfoEntity::getId, PlayOrderInfoEntity::getAcceptBy); + lambdaQueryWrapper.orderByDesc(PlayOrderInfoEntity::getPurchaserTime); + return this.baseMapper.selectJoinPage(new Page<>(vo.getPageNum(), vo.getPageSize()), + PlayRewardInfoReturnVo.class, lambdaQueryWrapper); + } + + /** + * 查询订单 + * + * @param id + * 订单主键 + * @return 订单 + */ + @Override + public PlayOrderInfoEntity selectOrderInfoById(String id) { + PlayOrderInfoEntity entity = this.baseMapper.selectById(id); + if (entity == null) { + throw new CustomException("订单不存在"); + } + return entity; + } + + @Override + public PlayOrderDetailsReturnVo selectById(String orderId) { + MPJLambdaWrapper lambdaQueryWrapper = new MPJLambdaWrapper<>(); + // 查询主表全部字段 + lambdaQueryWrapper.selectAll(PlayOrderInfoEntity.class); + // 查询顾客表 + lambdaQueryWrapper.selectAs(PlayCustomUserInfoEntity::getId, "customId") + .selectAs(PlayCustomUserInfoEntity::getAvatar, "customAvatar") + .selectAs(PlayCustomUserInfoEntity::getNickname, "customNickname"); + // 查询陪聊表 + lambdaQueryWrapper.selectAs(PlayClerkUserInfoEntity::getId, "clerkId") + .selectAs(PlayClerkUserInfoEntity::getAvatar, "clerkAvatar") + .selectAs(PlayClerkUserInfoEntity::getNickname, "clerkNickname"); + // 子表 + lambdaQueryWrapper.leftJoin(PlayCustomUserInfoEntity.class, PlayCustomUserInfoEntity::getId, + PlayOrderInfoEntity::getPurchaserBy).leftJoin(PlayClerkUserInfoEntity.class, + PlayClerkUserInfoEntity::getId, PlayOrderInfoEntity::getAcceptBy); + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getId, orderId); + lambdaQueryWrapper.orderByDesc(PlayOrderInfoEntity::getPurchaserTime); + return this.baseMapper.selectJoinOne(PlayOrderDetailsReturnVo.class, lambdaQueryWrapper); + } + + /** + * 分页查询订单信息 + * + * @param vo + * 订单分页查询对象 + * @return 订单分页查询结果 + */ + @Override + public IPage selectOrderInfoPage(PlayOrderInfoQueryVo vo) { + + MPJLambdaWrapper lambdaQueryWrapper = getCommonOrderQueryVo( + ConvertUtil.entityToVo(vo, PlayOrderInfoEntity.class)); + if (StringUtils.isNotBlank(vo.getGroupId())) { + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getGroupId, vo.getGroupId()); + } + if (StringUtils.isNotBlank(vo.getPurchaserBy())) { + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getPurchaserBy, vo.getPurchaserBy()); + } + if (StringUtils.isNotBlank(vo.getAcceptBy())) { + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getAcceptBy, vo.getAcceptBy()); + } + if (StringUtils.isNotBlank(vo.getOrderStatus())) { + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getOrderStatus, vo.getOrderStatus()); + } + if (StringUtils.isNotBlank(vo.getPlaceType())) { + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getPlaceType, vo.getPlaceType()); + } + if (StringUtils.isNotBlank(vo.getOrderType())) { + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getOrderType, vo.getOrderType()); + } + // 加入组员的筛选,要么acceptBy为空,要么就在in里面 + List clerkIdList = playClerkGroupInfoService.getValidClerkIdList(SecurityUtils.getLoginUser(), + vo.getClerkNickName()); + lambdaQueryWrapper.and( + i -> i.isNull(PlayOrderInfoEntity::getAcceptBy).or().in(PlayOrderInfoEntity::getAcceptBy, clerkIdList)); + return this.baseMapper.selectJoinPage(new Page<>(vo.getPageNum(), vo.getPageSize()), + PlayOrderInfoReturnVo.class, lambdaQueryWrapper); + } + + @Override + public PlayClerkOrderDetailsReturnVo clerkSelectOrderDetails(String clerkId, String orderId) { + PlayOrderInfoEntity entity = new PlayOrderInfoEntity(); + entity.setId(orderId); + entity.setAcceptBy(clerkId); + MPJLambdaWrapper lambdaQueryWrapper = getCommonOrderQueryVo(entity); + // 拼接用户等级 + lambdaQueryWrapper.selectAs(PlayCustomLevelInfoEntity::getId, "customLevelId") + .selectAs(PlayCustomLevelInfoEntity::getName, "customLevelName"); + lambdaQueryWrapper.leftJoin(PlayCustomLevelInfoEntity.class, PlayCustomLevelInfoEntity::getId, + PlayCustomUserInfoEntity::getLevelId); + PlayClerkOrderDetailsReturnVo returnVo = this.baseMapper.selectJoinOne(PlayClerkOrderDetailsReturnVo.class, + lambdaQueryWrapper); + // 如果订单状态为退款,查询订单退款原因 + if (returnVo.getOrderStatus().equals(OrderConstant.ORDER_STATUS_4)) { + PlayOrderRefundInfoEntity orderRefundInfoEntity = playOrderRefundInfoService + .selectPlayOrderRefundInfoByOrderId(returnVo.getId()); + returnVo.setRefundByType(orderRefundInfoEntity.getRefundByType()); + returnVo.setRefundById(orderRefundInfoEntity.getRefundById()); + returnVo.setRefundReason(orderRefundInfoEntity.getRefundReason()); + } + returnVo.setEstimatedRevenue(returnVo.getFinalAmount()); + return returnVo; + } + + @Override + public List clerkSelectOrderInfoList(String clerkId, String startTime, String endTime) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getAcceptBy, clerkId); + lambdaQueryWrapper.between(PlayOrderInfoEntity::getPurchaserTime, startTime, endTime); + return this.baseMapper.selectList(lambdaQueryWrapper); + } + + @Override + public IPage clerkSelectOrderInfoByPage(PlayClerkOrderInfoQueryVo vo) { + MPJLambdaWrapper lambdaQueryWrapper = getCommonOrderQueryVo( + ConvertUtil.entityToVo(vo, PlayOrderInfoEntity.class)); + // 拼接用户等级 + lambdaQueryWrapper.selectAs(PlayCustomLevelInfoEntity::getId, "customLevelId") + .selectAs(PlayCustomLevelInfoEntity::getName, "customLevelName"); + lambdaQueryWrapper.leftJoin(PlayCustomLevelInfoEntity.class, PlayCustomLevelInfoEntity::getId, + PlayCustomUserInfoEntity::getLevelId); + return this.baseMapper.selectJoinPage(new Page<>(vo.getPageNum(), vo.getPageSize()), + PlayClerkOrderListReturnVo.class, lambdaQueryWrapper); + } + + @Override + public PlayCustomOrderDetailsReturnVo customSelectOrderDetails(String customId, String orderId) { + PlayOrderInfoEntity entity = new PlayOrderInfoEntity(); + entity.setId(orderId); + entity.setPurchaserBy(customId); + MPJLambdaWrapper lambdaQueryWrapper = getCommonOrderQueryVo(entity); + PlayCustomOrderDetailsReturnVo returnVo = this.baseMapper.selectJoinOne(PlayCustomOrderDetailsReturnVo.class, + lambdaQueryWrapper); + // 如果订单状态为退款,查询订单退款原因 + if (returnVo.getOrderStatus().equals(OrderConstant.ORDER_STATUS_4)) { + PlayOrderRefundInfoEntity orderRefundInfoEntity = playOrderRefundInfoService + .selectPlayOrderRefundInfoByOrderId(returnVo.getId()); + returnVo.setRefundByType(orderRefundInfoEntity.getRefundByType()); + returnVo.setRefundById(orderRefundInfoEntity.getRefundById()); + returnVo.setRefundReason(orderRefundInfoEntity.getRefundReason()); + } + // 查询订单是否评价 + PlayOrderEvaluateInfoEntity orderEvaluateInfoEntity = playOrderEvaluateInfoService + .queryCustomToOrderEvaluateInfo(customId, orderId); + returnVo.setEvaluate(orderEvaluateInfoEntity != null ? "1" : "0"); + PlayOrderComplaintInfoEntity orderComplaintInfoEntity = playOrderComplaintInfoService + .queryCustomToOrderOrderComplaintInfo(customId, orderId); + // 查询订单是否投诉 + returnVo.setComplaint(orderComplaintInfoEntity != null ? "1" : "0"); + + return returnVo; + } + + @Override + public IPage customSelectOrderInfoByPage(PlayCustomOrderInfoQueryVo vo) { + MPJLambdaWrapper lambdaQueryWrapper = getCommonOrderQueryVo( + ConvertUtil.entityToVo(vo, PlayOrderInfoEntity.class)); + IPage page = this.baseMapper.selectJoinPage( + new Page<>(vo.getPageNum(), vo.getPageSize()), PlayCustomOrderListReturnVo.class, lambdaQueryWrapper); + // 获取当前顾客所有订单评价信息,将订单评价信息转化为 map<订单ID,订单ID>的结构 + PlayOrderEvaluateInfoEntity orderEvaluateInfoEntity = new PlayOrderEvaluateInfoEntity(); + orderEvaluateInfoEntity.setCustomId(vo.getPurchaserBy()); + Map evaluateInfos = playOrderEvaluateInfoService.selectByList(orderEvaluateInfoEntity).stream() + .collect(Collectors.toMap(PlayOrderEvaluateInfoEntity::getOrderId, + PlayOrderEvaluateInfoEntity::getOrderId)); + for (PlayCustomOrderListReturnVo record : page.getRecords()) { + record.setEvaluate(evaluateInfos.containsKey(record.getId()) ? "1" : "0"); + } + // 获取当前顾客所有订单投诉信息,将订单评价信息转化为 map<订单ID,订单ID>的结构 + PlayOrderComplaintInfoEntity orderComplaintInfoEntity = new PlayOrderComplaintInfoEntity(); + orderComplaintInfoEntity.setCustomId(vo.getPurchaserBy()); + Map complaintInfos = playOrderComplaintInfoService.selectByList(orderComplaintInfoEntity) + .stream().collect(Collectors.toMap(PlayOrderComplaintInfoEntity::getOrderId, + PlayOrderComplaintInfoEntity::getOrderId)); + for (PlayCustomOrderListReturnVo record : page.getRecords()) { + record.setComplaint(complaintInfos.containsKey(record.getId()) ? "1" : "0"); + } + return page; + } + + @Override + public List customSelectOrderInfoByList(String customId) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getPurchaserBy, customId); + return this.baseMapper.selectList(lambdaQueryWrapper); + } + + /** + * 获取通用的订单查询对象 订单作为主表 连接顾客用户表、店员用户表、商品表 + * + * @return MPJLambdaWrapper + */ + public MPJLambdaWrapper getCommonOrderQueryVo(PlayOrderInfoEntity entity) { + MPJLambdaWrapper lambdaQueryWrapper = new MPJLambdaWrapper<>(); + // 查询主表全部字段 + lambdaQueryWrapper.selectAll(PlayOrderInfoEntity.class); + // 查询顾客表 + lambdaQueryWrapper.selectAs(PlayCustomUserInfoEntity::getId, "customId") + .selectAs(PlayCustomUserInfoEntity::getAvatar, "customAvatar") + .selectAs(PlayCustomUserInfoEntity::getNickname, "customNickname"); + // 查询陪聊表 + lambdaQueryWrapper.selectAs(PlayClerkUserInfoEntity::getId, "clerkId") + .selectAs(PlayClerkUserInfoEntity::getAvatar, "clerkAvatar") + .selectAs(PlayClerkUserInfoEntity::getNickname, "clerkNickname"); + // 子表-店员服务项目表 + lambdaQueryWrapper.leftJoin(PlayCustomUserInfoEntity.class, PlayCustomUserInfoEntity::getId, + PlayOrderInfoEntity::getPurchaserBy); + // 子表-店员表 + lambdaQueryWrapper.leftJoin(PlayClerkUserInfoEntity.class, PlayClerkUserInfoEntity::getId, + PlayOrderInfoEntity::getAcceptBy); + if (StringUtils.isNotBlank(entity.getId())) { + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getId, entity.getId()); + } + if (StringUtils.isNotBlank(entity.getPurchaserBy())) { + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getPurchaserBy, entity.getPurchaserBy()); + } + if (StringUtils.isNotBlank(entity.getAcceptBy())) { + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getAcceptBy, entity.getAcceptBy()); + } + if (StringUtils.isNotBlank(entity.getOrderStatus())) { + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getOrderStatus, entity.getOrderStatus()); + } + if (StringUtils.isNotBlank(entity.getPlaceType())) { + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getPlaceType, entity.getPlaceType()); + } + if (StringUtils.isNotBlank(entity.getOrderType())) { + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getOrderType, entity.getOrderType()); + } + lambdaQueryWrapper.orderByDesc(PlayOrderInfoEntity::getCreatedTime); + return lambdaQueryWrapper; + + } + + /** + * 修改订单状态为接单 只有管理员或者店员本人才能操作 + * + * @param operatorByType + * 操作人类型(0:顾客;1:店员;2:管理员) + * @param operatorBy + * 操作人ID + * @param acceptBy + * 接单人ID + * @param orderId + * 订单Id + **/ + @Override + public void updateStateTo1(String operatorByType, String operatorBy, String acceptBy, String orderId) { + if (!"1".equals(operatorByType) && !"2".equals(operatorByType)) { + throw new CustomException("禁止操作"); + } + PlayOrderInfoEntity orderInfo = this.selectOrderInfoById(orderId); + PlayClerkUserInfoEntity clerkUserInfoEntity = playClerkUserInfoService.selectById(acceptBy); + // 店员接单时,判断店员是否符合资格 + if ("1".equals(operatorByType) && "1".equals(orderInfo.getPlaceType())) { + // 判断店员等级是否符合规则 + if (orderInfo.getLevelId().equals(clerkUserInfoEntity.getLevelId())) { + PlayClerkLevelInfoEntity levelInfo = playClerkLevelInfoService + .selectPlayClerkLevelInfoById(orderInfo.getLevelId()); + throw new CustomException("等级为" + levelInfo.getName() + "的店员才可接单"); + } + // 判断店员性别是否符合规则 + if (orderInfo.getSex().equals(clerkUserInfoEntity.getSex())) { + String sex = "0".equals(orderInfo.getSex()) ? "未知" : "1".equals(orderInfo.getSex()) ? "男" : "女"; + throw new CustomException("性别为" + sex + "的店员才可接单"); + } + // 如果排除已下单的店员 + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getAcceptBy, acceptBy); + if ("1".equals(orderInfo.getExcludeHistory()) && this.baseMapper.selectOne(lambdaQueryWrapper) != null) { + throw new CustomException("只有未接单的店员才可接单"); + } + } + PlayOrderInfoEntity entity = new PlayOrderInfoEntity(orderId, OrderConstant.ORDER_STATUS_1); + entity.setAcceptBy(acceptBy); + entity.setAcceptTime(LocalDateTime.now()); + ClerkEstimatedRevenueVo estimatedRevenueVo = this.getClerkEstimatedRevenue(acceptBy, orderInfo.getCouponIds(), + orderInfo.getPlaceType(), orderInfo.getFirstOrder(), orderInfo.getFinalAmount()); + entity.setEstimatedRevenue(estimatedRevenueVo.getRevenueAmount()); + entity.setEstimatedRevenueRatio(estimatedRevenueVo.getRevenueRatio()); + this.baseMapper.updateById(entity); + + wxCustomMpService.sendOrderMessage(orderInfo); + } + + /** + * 修改订单状态为开始订单或者完成订单 只有管理员或者店员本人才能操作 + * + * @param operatorByType + * 操作人类型(0:顾客;1:店员;2:管理员) + * @param operatorBy + * 操作人ID + * @param orderState + * 订单状态 + * @param orderId + * 订单Id + **/ + @Override + public void updateStateTo23(String operatorByType, String operatorBy, String orderState, String orderId) { + // 开始订单只能店员或者管理员操作 + if (orderState.equals(ORDER_STATUS_2) && "0".equals(operatorByType)) { + throw new CustomException("禁止操作"); + } + // 完成订单只能顾客或者管理员操作 + if (orderState.equals(ORDER_STATUS_3) && "1".equals(operatorByType)) { + throw new CustomException("禁止操作"); + } + PlayOrderInfoEntity entity = this.selectOrderInfoById(orderId); + // 如果该接口是顾客调用,判断是否是本人订单 + if ("0".equals(operatorByType) && !entity.getPurchaserBy().equals(operatorBy)) { + throw new CustomException("只能操作本人订单"); + } + // 如果该接口是店员调用,判断是否是本人订单 + if ("1".equals(operatorByType) && !entity.getAcceptBy().equals(operatorBy)) { + throw new CustomException("只能操作本人订单"); + } + switch (orderState) { + case ORDER_STATUS_2 : { + // 开始订单前,订单状态必须为接单状态 + if (!entity.getOrderStatus().equals(OrderConstant.ORDER_STATUS_1)) { + log.error("订单状态异常,不能开始接单,orderId={},orderStace={}", orderId, orderState); + throw new CustomException("订单状态异常,不能开始订单"); + } + PlayOrderInfoEntity entity2 = new PlayOrderInfoEntity(orderId, ORDER_STATUS_2); + entity2.setOrderStartTime(LocalDateTime.now()); + this.baseMapper.updateById(entity2); + break; + } + case ORDER_STATUS_3 : { + // 完成订单前,订单状态必须为开始状态 + if (!entity.getOrderStatus().equals(ORDER_STATUS_2)) { + log.error("订单状态异常,不能完成订单,orderId={},orderStace={}", orderId, orderState); + throw new CustomException("订单状态异常,不能开始订单"); + } + // 完成订单 + PlayOrderInfoEntity entity2 = new PlayOrderInfoEntity(orderId, ORDER_STATUS_3); + entity2.setOrderEndTime(LocalDateTime.now()); + this.baseMapper.updateById(entity2); + // 发送消息 + wxCustomMpService.sendOrderFinishMessage(this.selectOrderInfoById(orderId)); + break; + } + default : { + log.error("修改订单状态异常,orderId={},orderStace={}", orderId, orderState); + } + } + } + + /** + * 修改订单状态为取消订单 管理员、店员、顾客均可操作 + * + * @param operatorByType + * 操作人类型(0:顾客;1:店员;2:管理员) + * @param operatorBy + * 操作人ID + * @param orderId + * 订单Id + **/ + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateStateTo4(String operatorByType, String operatorBy, String orderId, String refundReason, + List images) { + PlayOrderInfoEntity orderInfo = this.selectOrderInfoById(orderId); + if ("0".equals(operatorByType) && !operatorBy.equals(orderInfo.getPurchaserBy())) { + throw new CustomException("只能操作本人订单"); + } + if ("1".equals(operatorByType) && !operatorBy.equals(orderInfo.getAcceptBy())) { + throw new CustomException("只能操作本人订单"); + } + // 取消订单(必须订单未接单或者为开始状态) + if (!orderInfo.getOrderStatus().equals(OrderConstant.ORDER_STATUS_0) + && !orderInfo.getOrderStatus().equals(OrderConstant.ORDER_STATUS_1)) { + throw new CustomException("订单状态异常,无法取消"); + } + // 修改订单状态 + this.baseMapper.updateById(new PlayOrderInfoEntity(orderId, OrderConstant.ORDER_STATUS_4)); + // 用户增加余额 + PlayCustomUserInfoEntity customUserInfo = customUserInfoService.getById(orderInfo.getPurchaserBy()); + customUserInfoService.updateAccountBalanceById(customUserInfo.getId(), customUserInfo.getAccountBalance(), + customUserInfo.getAccountBalance().add(orderInfo.getOrderMoney()), "3", "订单退款", + orderInfo.getOrderMoney(), BigDecimal.ZERO, orderId); + // 取消订单后,记录退款信息 + playOrderRefundInfoService.add(orderId, orderInfo.getPurchaserBy(), orderInfo.getAcceptBy(), + orderInfo.getPayMethod(), "0", orderInfo.getFinalAmount(), refundReason, operatorByType, operatorBy, + "0", "0"); + wxCustomMpService.sendOrderCancelMessage(orderInfo, refundReason); + } + + @Override + public PlayOrderInfoEntity queryByOrderNo(String orderNo) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getOrderNo, orderNo); + return this.baseMapper.selectOne(lambdaQueryWrapper); + } + + /** + * 修改订单 + * + * @param orderInfo + * 订单 + * @return 结果 + */ + @Override + public boolean update(PlayOrderInfoEntity orderInfo) { + return updateById(orderInfo); + } + + /** + * 批量删除订单 + * + * @param ids + * 需要删除的订单主键 + * @return 结果 + */ + @Override + public int deleteOrderInfoByIds(String[] ids) { + return orderInfoMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除订单信息 + * + * @param id + * 订单主键 + * @return 结果 + */ + @Override + public int deleteOrderInfoById(String id) { + return orderInfoMapper.deleteById(id); + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/order/service/impl/PlayOrderRefundInfoServiceImpl.java --- +package com.starry.admin.modules.order.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.github.yulichang.wrapper.MPJLambdaWrapper; +import com.starry.admin.modules.order.mapper.PlayOrderRefundInfoMapper; +import com.starry.admin.modules.order.module.entity.PlayOrderRefundInfoEntity; +import com.starry.admin.modules.order.module.vo.PlayOrderRefundQueryVo; +import com.starry.admin.modules.order.module.vo.PlayOrderRefundReturnVo; +import com.starry.admin.modules.order.service.IPlayOrderRefundInfoService; +import com.starry.common.utils.IdUtils; +import java.math.BigDecimal; +import java.util.Arrays; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 订单退款信息Service业务层处理 + * + * @author admin + * @since 2024-05-09 + */ +@Service +public class PlayOrderRefundInfoServiceImpl extends ServiceImpl + implements + IPlayOrderRefundInfoService { + @Resource + private PlayOrderRefundInfoMapper playOrderRefundInfoMapper; + + @Override + public PlayOrderRefundInfoEntity selectPlayOrderRefundInfoByOrderId(String orderId) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayOrderRefundInfoEntity::getOrderId, orderId); + return this.baseMapper.selectOne(lambdaQueryWrapper); + } + + /** + * 查询订单退款信息 + * + * @param id + * 订单退款信息主键 + * @return 订单退款信息 + */ + @Override + public PlayOrderRefundInfoEntity selectPlayOrderRefundInfoById(String id) { + return this.baseMapper.selectById(id); + } + + @Override + public IPage selectByPage(PlayOrderRefundQueryVo vo) { + MPJLambdaWrapper lambdaQueryWrapper = new MPJLambdaWrapper<>(); + return this.baseMapper.selectJoinPage(new Page<>(vo.getPageNum(), vo.getPageSize()), + PlayOrderRefundReturnVo.class, lambdaQueryWrapper); + } + + /** + * 查询订单退款信息列表 + * + * @param playOrderRefundInfo + * 订单退款信息 + * @return 订单退款信息 + */ + @Override + public IPage selectPlayOrderRefundInfoByPage( + PlayOrderRefundInfoEntity playOrderRefundInfo) { + Page page = new Page<>(1, 10); + return this.baseMapper.selectPage(page, new LambdaQueryWrapper()); + } + + @Override + public void add(String orderId, String customId, String clerkId, String payMethod, String refundType, + BigDecimal refundAmount, String refundReason, String refundByType, String refundById, String refundState, + String reviewedRequired) { + PlayOrderRefundInfoEntity orderRefundInfo = new PlayOrderRefundInfoEntity(); + orderRefundInfo.setOrderId(orderId); + orderRefundInfo.setCustomId(customId); + orderRefundInfo.setClerkId(clerkId); + orderRefundInfo.setPayMethod(payMethod); + orderRefundInfo.setRefundType(refundType); + orderRefundInfo.setRefundAmount(refundAmount); + orderRefundInfo.setRefundReason(refundReason); + orderRefundInfo.setRefundByType(refundByType); + orderRefundInfo.setRefundById(refundById); + orderRefundInfo.setRefundState(refundState); + orderRefundInfo.setReviewedRequired(reviewedRequired); + this.save(orderRefundInfo); + } + + /** + * 新增订单退款信息 + * + * @param playOrderRefundInfo + * 订单退款信息 + * @return 结果 + */ + @Override + public boolean create(PlayOrderRefundInfoEntity playOrderRefundInfo) { + if (StrUtil.isBlankIfStr(playOrderRefundInfo.getId())) { + playOrderRefundInfo.setId(IdUtils.getUuid()); + } + return save(playOrderRefundInfo); + } + + /** + * 修改订单退款信息 + * + * @param playOrderRefundInfo + * 订单退款信息 + * @return 结果 + */ + @Override + public boolean update(PlayOrderRefundInfoEntity playOrderRefundInfo) { + return updateById(playOrderRefundInfo); + } + + /** + * 批量删除订单退款信息 + * + * @param ids + * 需要删除的订单退款信息主键 + * @return 结果 + */ + @Override + public int deletePlayOrderRefundInfoByIds(String[] ids) { + return playOrderRefundInfoMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除订单退款信息信息 + * + * @param id + * 订单退款信息主键 + * @return 结果 + */ + @Override + public int deletePlayOrderRefundInfoById(String id) { + return playOrderRefundInfoMapper.deleteById(id); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/controller/PlayBalanceDetailsInfoController.java --- +package com.starry.admin.modules.personnel.controller; + +import com.starry.admin.modules.personnel.module.entity.PlayBalanceDetailsInfoEntity; +import com.starry.admin.modules.personnel.module.vo.PlayBalanceDetailsQueryVo; +import com.starry.admin.modules.personnel.service.IPlayBalanceDetailsInfoService; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 余额明细Controller + * + * @author admin + * @since 2024-04-30 + */ +@Api(tags = "余额明细管理", description = "余额明细信息管理相关接口,包括查询、修改和删除等操作") +@RestController +@RequestMapping("/balance/details") +public class PlayBalanceDetailsInfoController { + @Resource + private IPlayBalanceDetailsInfoService playBalanceDetailsInfoService; + + /** + * 查询余额明细列表 + */ + @ApiOperation(value = "分页查询明细列表", notes = "分页查询余额明细信息列表") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @PostMapping("/listByPage") + public R list(@ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayBalanceDetailsQueryVo vo) { + return R.ok(playBalanceDetailsInfoService.selectByPage(vo)); + } + + /** + * 获取余额明细详细信息 + */ + @ApiOperation(value = "获取明细详情", notes = "根据ID获取余额明细详细信息") + @ApiImplicitParam(name = "id", value = "明细ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = PlayBalanceDetailsInfoEntity.class)}) + @GetMapping(value = "/{id}") + public R getInfo(@PathVariable("id") String id) { + return R.ok(playBalanceDetailsInfoService.selectPlayBalanceDetailsInfoById(id)); + } + + /** + * 修改余额明细 + */ + @ApiOperation(value = "修改明细信息", notes = "修改余额明细信息") + @ApiImplicitParam(name = "id", value = "明细ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败,包含详细错误信息")}) + // @PreAuthorize("@customSs.hasPermission('balance:details:update')") + @Log(title = "余额明细", businessType = BusinessType.UPDATE) + @PostMapping(value = "/update/{id}") + public R update(@PathVariable String id, + @ApiParam(value = "明细信息", required = true) @RequestBody PlayBalanceDetailsInfoEntity playBalanceDetailsInfo) { + playBalanceDetailsInfo.setId(id); + boolean success = playBalanceDetailsInfoService.update(playBalanceDetailsInfo); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + /** + * 删除余额明细 + */ + @ApiOperation(value = "删除明细信息", notes = "根据ID批量删除余额明细信息") + @ApiImplicitParam(name = "ids", value = "明细ID数组", required = true, paramType = "path", dataType = "String[]", example = "1,2,3") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + // @PreAuthorize("@customSs.hasPermission('balance:details:delete')") + @Log(title = "余额明细", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@PathVariable String[] ids) { + return R.ok(playBalanceDetailsInfoService.deletePlayBalanceDetailsInfoByIds(ids)); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/controller/PlayPersonnelAdminInfoController.java --- +package com.starry.admin.modules.personnel.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.personnel.module.entity.PlayPersonnelAdminInfoEntity; +import com.starry.admin.modules.personnel.module.vo.PlayPersonnelAdminInfoEditAddInfoVo; +import com.starry.admin.modules.personnel.module.vo.PlayPersonnelAdminInfoEditBaseInfoVo; +import com.starry.admin.modules.personnel.module.vo.PlayPersonnelAdminInfoQueryVo; +import com.starry.admin.modules.personnel.module.vo.PlayPersonnelAdminInfoReturnVo; +import com.starry.admin.modules.personnel.service.IPlayPersonnelAdminInfoService; +import com.starry.admin.modules.system.module.entity.SysUserEntity; +import com.starry.admin.modules.system.service.SysRoleService; +import com.starry.admin.modules.system.service.SysUserRoleService; +import com.starry.admin.modules.system.service.SysUserService; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import com.starry.common.utils.ConvertUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.time.LocalDateTime; +import javax.annotation.Resource; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 管理员管理Controller + * + * @author admin + * @since 2024-06-14 + */ +@Api(tags = "管理员管理", description = "管理员信息管理相关接口,包括查询、新增、修改和删除等操作") +@RestController +@RequestMapping("/personnel/admin") +public class PlayPersonnelAdminInfoController { + @Resource + private IPlayPersonnelAdminInfoService playPersonnelAdminInfoService; + + @Resource + private SysUserService sysUserService; + + @Resource + private SysRoleService sysRoleService; + + @Resource + private SysUserRoleService userRoleService; + + /** + * 查询管理员管理信息列表 + */ + @ApiOperation(value = "分页查询管理员列表", notes = "分页查询管理员信息列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayPersonnelAdminInfoReturnVo.class, responseContainer = "Page")}) + @PostMapping("/listByPage") + public R listByPage( + @ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayPersonnelAdminInfoQueryVo vo) { + IPage list = playPersonnelAdminInfoService.selectByPage(vo); + return R.ok(list); + } + + /** + * 获取管理员管理详细信息 + */ + @ApiOperation(value = "获取管理员详情", notes = "根据ID获取管理员详细信息") + @ApiImplicitParam(name = "id", value = "管理员ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = PlayPersonnelAdminInfoEntity.class)}) + @GetMapping(value = "/{id}") + public R getInfo(@PathVariable("id") String id) { + return R.ok(playPersonnelAdminInfoService.selectPlayPersonnelAdminInfoById(id)); + } + + /** + * 新增管理员管理信息 + */ + @ApiOperation(value = "新增管理员信息", notes = "创建新的管理员信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "添加失败,包含详细错误信息")}) + @Log(title = "管理员管理信息", businessType = BusinessType.INSERT) + @PostMapping("/createBaseInfo") + public R createBaseInfo( + @ApiParam(value = "管理员信息", required = true) @Validated @RequestBody PlayPersonnelAdminInfoEditAddInfoVo vo) { + // 校验对应用户是否存在 + SysUserEntity sysUserEntity = sysUserService.selectUserById(vo.getSysUserId()); + // 校验当前用户是否已经是组长 + PlayPersonnelAdminInfoEntity groupInfoEntity = playPersonnelAdminInfoService.selectByUserId(vo.getSysUserId()); + if (groupInfoEntity != null) { + throw new CustomException("当前账号已经是管理员,无法重复添加"); + } + // 添加管理员 + PlayPersonnelAdminInfoEntity entity = ConvertUtil.entityToVo(vo, PlayPersonnelAdminInfoEntity.class); + entity.setSysUserCode(sysUserEntity.getUserCode()); + entity.setAddTime(LocalDateTime.now()); + boolean success = playPersonnelAdminInfoService.create(entity); + if (success) { + // 新建管理员后,添加对应的用户角色权限 + userRoleService.addUserRole(vo.getSysUserId(), sysRoleService.selectByRoleKey("operator").getRoleId()); + return R.ok(); + } + return R.error("添加失败"); + } + + /** + * 修改管理员管理信息 + */ + @ApiOperation(value = "修改管理员信息", notes = "修改管理员基本信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败,包含详细错误信息")}) + @Log(title = "管理员管理信息", businessType = BusinessType.UPDATE) + @PostMapping(value = "/updateBaseInfo") + public R updateBaseInfo( + @ApiParam(value = "管理员信息", required = true) @Validated @RequestBody PlayPersonnelAdminInfoEditBaseInfoVo vo) { + + // 校验对应用户是否存在 + SysUserEntity sysUserEntity = sysUserService.selectUserById(vo.getSysUserId()); + // 校验当前用户是否已经是组长 + PlayPersonnelAdminInfoEntity adminInfoEntity = playPersonnelAdminInfoService.selectByUserId(vo.getSysUserId()); + if (adminInfoEntity != null && !adminInfoEntity.getId().equals(vo.getId())) { + throw new CustomException("当前账号已经是管理员,无法重复添加"); + } + PlayPersonnelAdminInfoEntity entity = ConvertUtil.entityToVo(vo, PlayPersonnelAdminInfoEntity.class); + entity.setSysUserCode(sysUserEntity.getUserCode()); + boolean success = playPersonnelAdminInfoService.update(entity); + if (success) { + // 新建管理员后,添加对应的用户角色权限 + userRoleService.addUserRole(vo.getSysUserId(), sysRoleService.selectByRoleKey("operator").getRoleId()); + } + return R.error("修改失败"); + } + + /** + * 删除管理员管理 + */ + @ApiOperation(value = "删除管理员信息", notes = "根据ID批量删除管理员信息") + @ApiImplicitParam(name = "ids", value = "管理员ID数组", required = true, paramType = "path", dataType = "String[]", example = "1,2,3") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @PreAuthorize("@customSs.hasPermission('play:info:remove')") + @Log(title = "管理员管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@PathVariable String[] ids) { + Long ruleId = sysRoleService.selectByRoleKey("operator").getRoleId(); + for (String id : ids) { + // 判断数据是否存在 + PlayPersonnelAdminInfoEntity entity = playPersonnelAdminInfoService.selectPlayPersonnelAdminInfoById(id); + // 删除管理员 + playPersonnelAdminInfoService.deletePlayPersonnelAdminInfoById(id); + // 删除对应的权限信息 + userRoleService.delUserRole(entity.getSysUserId(), ruleId); + } + return R.ok(); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/controller/PlayPersonnelGroupInfoController.java --- +package com.starry.admin.modules.personnel.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity; +import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService; +import com.starry.admin.modules.personnel.module.entity.PlayPersonnelGroupInfoEntity; +import com.starry.admin.modules.personnel.module.vo.PlayPersonnelGroupInfoEditAddInfoVo; +import com.starry.admin.modules.personnel.module.vo.PlayPersonnelGroupInfoEditBaseInfoVo; +import com.starry.admin.modules.personnel.module.vo.PlayPersonnelGroupInfoQueryVo; +import com.starry.admin.modules.personnel.module.vo.PlayPersonnelGroupInfoReturnVo; +import com.starry.admin.modules.personnel.service.IPlayPersonnelGroupInfoService; +import com.starry.admin.modules.system.module.entity.SysUserEntity; +import com.starry.admin.modules.system.service.SysRoleService; +import com.starry.admin.modules.system.service.SysUserRoleService; +import com.starry.admin.modules.system.service.SysUserService; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import com.starry.common.utils.ConvertUtil; +import com.starry.common.utils.IdUtils; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.time.LocalDateTime; +import java.util.List; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 店员分组信息Controller + * + * @author admin + * @since 2024-05-31 + */ +@Api(tags = "店员分组管理", description = "店员分组信息管理相关接口,包括查询、新增、修改和删除等操作") +@RestController +@RequestMapping("/personnel/group") +public class PlayPersonnelGroupInfoController { + + @Resource + private IPlayPersonnelGroupInfoService playClerkGroupInfoService; + + @Resource + private IPlayClerkUserInfoService playClerkUserInfoService; + + @Resource + private SysUserService sysUserService; + + @Resource + private SysRoleService sysRoleService; + + @Resource + private SysUserRoleService userRoleService; + + /** + * 查询店员分类信息列表 + */ + @ApiOperation(value = "分页查询分组列表", notes = "分页查询店员分组信息列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayPersonnelGroupInfoReturnVo.class, responseContainer = "Page")}) + @PostMapping("/listByPage") + public R listByPage( + @ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayPersonnelGroupInfoQueryVo vo) { + IPage list = playClerkGroupInfoService.selectByPage(vo); + for (PlayPersonnelGroupInfoReturnVo record : list.getRecords()) { + List clerkUserInfoEntities = playClerkUserInfoService + .listAllByGroupId(record.getId()); + record.setTotalEmployeesNumber(clerkUserInfoEntities.size()); + Integer listingEmployeesNumber = 0; + for (PlayClerkUserInfoEntity clerkUserInfoEntity : clerkUserInfoEntities) { + if ("1".equals(clerkUserInfoEntity.getListingState())) { + listingEmployeesNumber++; + } + } + record.setListingEmployeesNumber(listingEmployeesNumber); + } + return R.ok(list); + } + + /** + * 新增店员分组信息 + */ + @ApiOperation(value = "新增分组信息", notes = "创建新的店员分组信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "添加失败,包含详细错误信息")}) + @Log(title = "店员分组信息", businessType = BusinessType.INSERT) + @PostMapping("/createBaseInfo") + public R createBaseInfo( + @ApiParam(value = "分组信息", required = true) @Validated @RequestBody PlayPersonnelGroupInfoEditAddInfoVo vo) { + // 校验对应用户是否存在 + SysUserEntity sysUserEntity = sysUserService.selectUserById(vo.getSysUserId()); + // 校验当前用户是否已经是组长 + PlayPersonnelGroupInfoEntity groupInfoEntity = playClerkGroupInfoService.selectByUserId(vo.getSysUserId()); + if (groupInfoEntity != null) { + throw new CustomException("当前账号已经是组长,无法重复添加"); + } + // 添加组长配置 + PlayPersonnelGroupInfoEntity entity = ConvertUtil.entityToVo(vo, PlayPersonnelGroupInfoEntity.class); + entity.setId(IdUtils.getUuid()); + entity.setSysUserCode(sysUserEntity.getUserCode()); + entity.setAddTime(LocalDateTime.now()); + boolean success = playClerkGroupInfoService.create(entity); + if (success) { + // 新建组长后,添加对应的用户角色权限 + userRoleService.addUserRole(vo.getSysUserId(), sysRoleService.selectByRoleKey("leader").getRoleId()); + return R.ok("成功"); + } + return R.error("添加失败"); + } + + /** + * 修改店员分组信息 + */ + @ApiOperation(value = "修改分组信息", notes = "修改店员分组基本信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败,包含详细错误信息")}) + @Log(title = "店员分组信息", businessType = BusinessType.UPDATE) + @PostMapping(value = "/updateBaseInfo") + public R updateBaseInfo( + @ApiParam(value = "分组信息", required = true) @Validated @RequestBody PlayPersonnelGroupInfoEditBaseInfoVo vo) { + SysUserEntity sysUserEntity = sysUserService.selectUserById(vo.getSysUserId()); + // 校验当前用户是否已经是组长 + PlayPersonnelGroupInfoEntity groupInfoEntity = playClerkGroupInfoService.selectByUserId(vo.getSysUserId()); + // 校验当前用户是否已经是组长,只有当前用户不为组长时 + if (groupInfoEntity != null && !groupInfoEntity.getId().equals(vo.getId())) { + throw new CustomException("当前账号已经是组长,无法重复添加"); + } + PlayPersonnelGroupInfoEntity entity = ConvertUtil.entityToVo(vo, PlayPersonnelGroupInfoEntity.class); + entity.setSysUserCode(sysUserEntity.getUserCode()); + boolean success = playClerkGroupInfoService.update(entity); + if (success) { + // 新建组长后,添加对应的用户角色权限 + userRoleService.addUserRole(vo.getSysUserId(), sysRoleService.selectByRoleKey("leader").getRoleId()); + return R.ok("成功"); + } + return R.error("修改失败"); + } + + /** + * 删除店员分组信息 + */ + @ApiOperation(value = "删除分组信息", notes = "根据ID批量删除店员分组信息") + @ApiImplicitParam(name = "ids", value = "分组ID数组", required = true, paramType = "path", dataType = "String[]", example = "1,2,3") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "删除失败,包含详细错误信息")}) + @Log(title = "店员分组信息", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@PathVariable String[] ids) { + for (String id : ids) { + List clerkUserInfoEntities = playClerkUserInfoService.listAllByGroupId(id); + if (!clerkUserInfoEntities.isEmpty()) { + throw new CustomException("分组中存在店员,禁止删除"); + } + } + Long ruleId = sysRoleService.selectByRoleKey("leader").getRoleId(); + for (String id : ids) { + // 判断数据是否存在 + PlayPersonnelGroupInfoEntity entity = playClerkGroupInfoService.selectPlayClerkGroupInfoById(id); + // 删除组长 + playClerkGroupInfoService.deletePlayClerkGroupInfoById(id); + // 删除对应的权限信息 + userRoleService.delUserRole(entity.getSysUserId(), ruleId); + + } + return R.ok(); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/controller/PlayPersonnelUserInfoController.java --- +package com.starry.admin.modules.personnel.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.modules.personnel.module.vo.PlayPersonnelUserInfoQueryVo; +import com.starry.admin.modules.personnel.module.vo.PlayPersonnelUserInfoReturnVo; +import com.starry.admin.modules.system.module.entity.SysUserEntity; +import com.starry.admin.modules.system.service.SysUserService; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.util.List; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 管理员管理Controller + * + * @author admin + * @since 2024-06-14 + */ +@Api(tags = "系统用户管理", description = "系统用户信息管理相关接口,包括查询等操作") +@RestController +@RequestMapping("/personnel/user") +public class PlayPersonnelUserInfoController { + + @Resource + private SysUserService sysUserService; + + /** + * 分页查询账户信息列表 + */ + @ApiOperation(value = "分页查询用户列表", notes = "分页查询系统用户信息列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayPersonnelUserInfoReturnVo.class, responseContainer = "Page")}) + @PostMapping("/listByPage") + public R listByPage( + @ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayPersonnelUserInfoQueryVo vo) { + IPage list = sysUserService.selectByPage(vo); + return R.ok(list); + } + + /** + * 查询所有账户信息列表 + */ + @ApiOperation(value = "查询所有用户", notes = "查询所有系统用户信息") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = SysUserEntity.class, responseContainer = "List")}) + @GetMapping("/listAll") + public R listAll() { + List list = sysUserService.selectAll(); + return R.ok(list); + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/controller/PlayPersonnelWaiterInfoController.java --- +package com.starry.admin.modules.personnel.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.personnel.module.entity.PlayPersonnelWaiterInfoEntity; +import com.starry.admin.modules.personnel.module.vo.PlayPersonnelWaiterInfoEditAddInfoVo; +import com.starry.admin.modules.personnel.module.vo.PlayPersonnelWaiterInfoEditBaseInfoVo; +import com.starry.admin.modules.personnel.module.vo.PlayPersonnelWaiterInfoQueryVo; +import com.starry.admin.modules.personnel.module.vo.PlayPersonnelWaiterInfoReturnVo; +import com.starry.admin.modules.personnel.service.IPlayPersonnelWaiterInfoService; +import com.starry.admin.modules.system.module.entity.SysUserEntity; +import com.starry.admin.modules.system.service.SysRoleService; +import com.starry.admin.modules.system.service.SysUserRoleService; +import com.starry.admin.modules.system.service.SysUserService; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import com.starry.common.utils.ConvertUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.time.LocalDateTime; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 客服信息Controller + * + * @author admin + * @since 2024-06-14 + */ +@Api(tags = "客服管理", description = "客服信息管理相关接口,包括查询、新增、修改和删除等操作") +@RestController +@RequestMapping("/personnel/waiter") +public class PlayPersonnelWaiterInfoController { + @Resource + private IPlayPersonnelWaiterInfoService playClerkWaiterInfoService; + + @Resource + private SysUserService sysUserService; + + @Resource + private SysRoleService sysRoleService; + + @Resource + private SysUserRoleService userRoleService; + + /** + * 查询客服信息列表 + */ + @ApiOperation(value = "分页查询客服列表", notes = "分页查询客服信息列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayPersonnelWaiterInfoReturnVo.class, responseContainer = "Page")}) + @PostMapping("/listByPage") + public R listByPage( + @ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayPersonnelWaiterInfoQueryVo vo) { + IPage list = playClerkWaiterInfoService.selectByPage(vo); + return R.ok(list); + } + + /** + * 新增客服信息列表 + */ + @ApiOperation(value = "新增客服信息", notes = "创建新的客服信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "添加失败,包含详细错误信息")}) + @Log(title = "客服管理信息", businessType = BusinessType.INSERT) + @PostMapping("/createBaseInfo") + public R createBaseInfo( + @ApiParam(value = "客服信息", required = true) @Validated @RequestBody PlayPersonnelWaiterInfoEditAddInfoVo vo) { + // 校验对应用户是否存在 + SysUserEntity sysUserEntity = sysUserService.selectUserById(vo.getSysUserId()); + // 校验当前用户是否已经是组长 + PlayPersonnelWaiterInfoEntity waiterInfoEntity = playClerkWaiterInfoService.selectByUserId(vo.getSysUserId()); + if (waiterInfoEntity != null) { + throw new CustomException("当前账号已经是客服,无法重复添加"); + } + + PlayPersonnelWaiterInfoEntity entity = ConvertUtil.entityToVo(vo, PlayPersonnelWaiterInfoEntity.class); + entity.setSysUserCode(sysUserEntity.getUserCode()); + entity.setAddTime(LocalDateTime.now()); + boolean success = playClerkWaiterInfoService.create(entity); + if (success) { + // 新建客服后,添加对应的用户角色权限 + userRoleService.addUserRole(vo.getSysUserId(), sysRoleService.selectByRoleKey("waiter").getRoleId()); + return R.ok(); + } + return R.error("添加失败"); + } + + /** + * 修改客服信息列表 + */ + @ApiOperation(value = "修改客服信息", notes = "修改客服基本信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败,包含详细错误信息")}) + @Log(title = "客服管理信息", businessType = BusinessType.UPDATE) + @PostMapping(value = "/updateBaseInfo") + public R updateBaseInfo( + @ApiParam(value = "客服信息", required = true) @Validated @RequestBody PlayPersonnelWaiterInfoEditBaseInfoVo vo) { + + // 校验对应用户是否存在 + SysUserEntity sysUserEntity = sysUserService.selectUserById(vo.getSysUserId()); + // 校验当前用户是否已经是组长 + PlayPersonnelWaiterInfoEntity waiterInfoEntity = playClerkWaiterInfoService.selectByUserId(vo.getSysUserId()); + if (waiterInfoEntity != null && !waiterInfoEntity.getId().equals(vo.getId())) { + throw new CustomException("当前账号已经是客服,无法重复添加"); + } + + PlayPersonnelWaiterInfoEntity entity = ConvertUtil.entityToVo(vo, PlayPersonnelWaiterInfoEntity.class); + entity.setSysUserCode(sysUserEntity.getUserCode()); + boolean success = playClerkWaiterInfoService.update(entity); + if (success) { + // 新建客服后,添加对应的用户角色权限 + userRoleService.addUserRole(vo.getSysUserId(), sysRoleService.selectByRoleKey("waiter").getRoleId()); + return R.ok(); + } + return R.error("修改失败"); + } + + /** + * 删除客服信息 + */ + @ApiOperation(value = "删除客服信息", notes = "根据ID批量删除客服信息") + @ApiImplicitParam(name = "ids", value = "客服ID数组", required = true, paramType = "path", dataType = "String[]", example = "1,2,3") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "删除失败,包含详细错误信息")}) + @Log(title = "客服信息", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@PathVariable String[] ids) { + Long ruleId = sysRoleService.selectByRoleKey("operator").getRoleId(); + for (String id : ids) { + // 判断数据是否存在 + PlayPersonnelWaiterInfoEntity entity = playClerkWaiterInfoService.selectPlayClerkWaiterInfoById(id); + // 删除客服 + playClerkWaiterInfoService.deletePlayClerkWaiterInfoById(id); + // 删除对应的权限信息 + userRoleService.delUserRole(entity.getSysUserId(), ruleId); + + } + return R.ok(); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/mapper/PlayBalanceDetailsInfoMapper.java --- +package com.starry.admin.modules.personnel.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.starry.admin.modules.personnel.module.entity.PlayBalanceDetailsInfoEntity; + +/** + * 余额明细Mapper接口 + * + * @author admin + * @since 2024-04-30 + */ +public interface PlayBalanceDetailsInfoMapper extends MPJBaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/mapper/PlayPersonnelAdminInfoMapper.java --- +package com.starry.admin.modules.personnel.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.starry.admin.modules.personnel.module.entity.PlayPersonnelAdminInfoEntity; + +/** + * 管理员管理Mapper接口 + * + * @author admin + * @since 2024-06-14 + */ +public interface PlayPersonnelAdminInfoMapper extends MPJBaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/mapper/PlayPersonnelGroupInfoMapper.java --- +package com.starry.admin.modules.personnel.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.starry.admin.modules.personnel.module.entity.PlayPersonnelGroupInfoEntity; + +/** + * 店员分组信息Mapper接口 + * + * @author admin + * @since 2024-05-31 + */ +public interface PlayPersonnelGroupInfoMapper extends MPJBaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/mapper/PlayPersonnelWaiterInfoMapper.java --- +package com.starry.admin.modules.personnel.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.starry.admin.modules.personnel.module.entity.PlayPersonnelWaiterInfoEntity; + +/** + * 客服信息Mapper接口 + * + * @author admin + * @since 2024-06-14 + */ +public interface PlayPersonnelWaiterInfoMapper extends MPJBaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/module/entity/PlayBalanceDetailsInfoEntity.java --- +package com.starry.admin.modules.personnel.module.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.starry.common.domain.BaseEntity; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 余额明细对象 play_balance_details_info + * + * @author admin + * @since 2024-04-30 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("play_balance_details_info") +public class PlayBalanceDetailsInfoEntity extends BaseEntity { + + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 用户ID + */ + private String userId; + + /** + * 用户类型[0:陪聊;1:顾客] + */ + private String userType; + + /** + * 操作前余额 + */ + private BigDecimal balanceBeforeOperation; + + /** + * 操作后余额 + */ + private BigDecimal balanceAfterOperation; + + /** + * 操作类型(0:充值;1:消费;2:服务) + */ + private String operationType; + + /** + * 操作动作 + */ + private String operationAction; + + /** + * 操作时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime operationTime; + + /** + * 操作金额 + */ + private BigDecimal balanceMoney; + + /** + * 赠送金额 + */ + private BigDecimal giftAmount; + + /** + * 支付金额 + */ + private BigDecimal paymentAmount; + + /** + * 订单ID + */ + private String orderId; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/module/entity/PlayPersonnelAdminInfoEntity.java --- +package com.starry.admin.modules.personnel.module.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.starry.common.domain.BaseEntity; +import java.time.LocalDateTime; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 管理员管理对象 play_personnel_admin_info + * + * @author admin + * @since 2024-06-14 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("play_personnel_admin_info") +public class PlayPersonnelAdminInfoEntity extends BaseEntity { + + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 账号ID + */ + private String sysUserId; + + /** + * 用户账号 + */ + private String sysUserCode; + + /** + * 分组名称 + */ + private String adminName; + + /** + * 责任人 + */ + private String leaderName; + + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime addTime; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/module/entity/PlayPersonnelGroupInfoEntity.java --- +package com.starry.admin.modules.personnel.module.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.starry.common.domain.BaseEntity; +import java.time.LocalDateTime; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 店员分组信息对象 play_clerk_group_info + * + * @author admin + * @since 2024-05-31 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("play_personnel_group_info") +public class PlayPersonnelGroupInfoEntity extends BaseEntity { + + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 用户ID + **/ + private String sysUserId; + + /** + * 用户账号 + **/ + private String sysUserCode; + + /** + * 分组名称 + */ + private String groupName; + + /** + * 组长名称 + **/ + private String leaderName; + + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime addTime; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/module/entity/PlayPersonnelWaiterInfoEntity.java --- +package com.starry.admin.modules.personnel.module.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.starry.common.domain.BaseEntity; +import java.time.LocalDateTime; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 客服信息对象 play_clerk_waiter_info + * + * @author admin + * @since 2024-06-14 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("play_personnel_waiter_info") +public class PlayPersonnelWaiterInfoEntity extends BaseEntity { + + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 用户账号ID + */ + private String sysUserId; + + /** + * 用户账号 + */ + private String sysUserCode; + + /** + * 客服名称 + */ + private String waiterName; + + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime addTime; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/module/vo/PlayBalanceDetailsQueryVo.java --- +package com.starry.admin.modules.personnel.module.vo; + +import com.starry.common.domain.BasePageEntity; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 分页查询余额明细 + * + * @author admin + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class PlayBalanceDetailsQueryVo extends BasePageEntity { + + /** + * 店员昵称 + */ + private String nickname; + + /** + * 操作类型(0:充值;1:消费;2:服务) + */ + private String operationType; + + /** + * 支付方式,0:余额支付,1:微信支付,2:支付宝支付 + */ + private String payMethod; + + private String userType = "1"; + + private List operationTime; + + private String userId; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/module/vo/PlayBalanceDetailsReturnVo.java --- +package com.starry.admin.modules.personnel.module.vo; + +import java.math.BigDecimal; +import java.util.Date; +import lombok.Data; + +/** + * 余额明细查询对象 + * + * @author admin + */ +@Data +public class PlayBalanceDetailsReturnVo { + + /** + * UUID + */ + private String id; + + /** + * 操作前余额 + */ + private BigDecimal balanceBeforeOperation; + + /** + * 操作后余额 + */ + private BigDecimal balanceAfterOperation; + + /** + * 操作类型(0:充值;1:消费;2:服务) + */ + private String operationType; + + /** + * 操作动作 + */ + private String operationAction; + + /** + * 操作时间 + */ + private Date operationTime; + + /** + * 操作金额 + */ + private BigDecimal balanceMoney; + + /** + * 支付方式,0:余额支付,1:微信支付,2:支付宝支付 + */ + private String payMethod; + + /** + * 订单ID + */ + private String orderId; + + /** + * 订单ID + */ + private String orderNo; + + /** + * 订单金额 + */ + private BigDecimal orderMoney; + + /** + * 赠送金额 + */ + private BigDecimal giftAmount; + + /** + * 订单最终金额 + */ + private BigDecimal finalAmount; + + /** + * 订单备注 + */ + private String orderRemark; + + /** + * 顾客Id + */ + private String customId; + + /** + * 顾客昵称 + */ + private String customNickname; + + /** + * 顾客头像 + */ + private String customAvatar; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/module/vo/PlayPersonnelAdminInfoEditAddInfoVo.java --- +package com.starry.admin.modules.personnel.module.vo; + +import javax.validation.constraints.NotBlank; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +/** + * 管理员管理信息新增 + * + * @author admin + * @since 2024/6/14 14:45 + **/ +@Data +public class PlayPersonnelAdminInfoEditAddInfoVo { + + /** + * 分组名称 + */ + @NotBlank(message = "用户ID不能为空") + private String sysUserId; + + /** + * 管理员名称 + */ + @NotBlank(message = "管理员名称不能为空") + @Length(min = 1, max = 100, message = "字符长度在1-100之间") + private String adminName; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/module/vo/PlayPersonnelAdminInfoEditBaseInfoVo.java --- +package com.starry.admin.modules.personnel.module.vo; + +import javax.validation.constraints.NotBlank; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +/** + * 管理员管理信息修改 + * + * @author admin + * @since 2024/6/14 14:45 + **/ +@Data +public class PlayPersonnelAdminInfoEditBaseInfoVo { + /** + * UUID + * + * @since 2024/6/14 16:08 + **/ + @NotBlank(message = "ID不能为空") + private String id; + + /** + * 分组名称 + */ + @NotBlank(message = "用户ID不能为空") + private String sysUserId; + + /** + * 管理员名称 + */ + @NotBlank(message = "管理员名称不能为空") + @Length(min = 1, max = 100, message = "字符长度在1-100之间") + private String adminName; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/module/vo/PlayPersonnelAdminInfoQueryVo.java --- +package com.starry.admin.modules.personnel.module.vo; + +import com.starry.common.domain.BasePageEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 管理员管理信息 + * + * @author admin + * @since 2024/6/14 14:45 + **/ +@EqualsAndHashCode(callSuper = true) +@Data +public class PlayPersonnelAdminInfoQueryVo extends BasePageEntity { + + /** + * 管理员名称 + */ + private String adminName; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/module/vo/PlayPersonnelAdminInfoReturnVo.java --- +package com.starry.admin.modules.personnel.module.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import java.time.LocalDateTime; +import javax.validation.constraints.NotBlank; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 管理员管理信息 + * + * @author admin + * @since 2024/6/14 14:45 + **/ +@Data +public class PlayPersonnelAdminInfoReturnVo { + + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 用户ID + **/ + private String sysUserId; + + /** + * 用户账号 + **/ + private String sysUserCode; + + /** + * 管理员名称 + */ + @NotBlank(message = "管理员名称不能为空") + @Length(min = 1, max = 100, message = "字符长度在1-100之间") + private String adminName; + + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime addTime; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/module/vo/PlayPersonnelGroupInfoEditAddInfoVo.java --- +package com.starry.admin.modules.personnel.module.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotBlank; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +/** + * 店员分组基本信息修改 + * + * @author admin + * @since 2024/6/14 14:45 + **/ +@Data +@ApiModel(value = "新增分组参数", description = "新增店员分组信息的请求参数") +public class PlayPersonnelGroupInfoEditAddInfoVo { + + /** + * 分组名称 + */ + @NotBlank(message = "用户ID不能为空") + @ApiModelProperty(value = "用户ID", required = true, example = "1", notes = "系统用户ID") + private String sysUserId; + + /** + * 分组名称 + */ + @NotBlank(message = "分组名称不能为空") + @Length(min = 1, max = 100, message = "字符长度在1-100之间") + @ApiModelProperty(value = "分组名称", required = true, example = "销售组", notes = "分组的名称,1-100字符") + private String groupName; + + /** + * 分组名称 + */ + @NotBlank(message = "组长名称不能为空") + @Length(min = 1, max = 100, message = "字符长度在1-100之间") + @ApiModelProperty(value = "组长名称", required = true, example = "张三", notes = "组长的名称,1-100字符") + private String leaderName; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/module/vo/PlayPersonnelGroupInfoEditBaseInfoVo.java --- +package com.starry.admin.modules.personnel.module.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotBlank; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +/** + * 店员分组基本信息修改 + * + * @author admin + * @since 2024/6/14 14:45 + **/ +@Data +@ApiModel(value = "修改分组参数", description = "修改店员分组信息的请求参数") +public class PlayPersonnelGroupInfoEditBaseInfoVo { + /** + * UUID + * + * @since 2024/6/14 16:08 + **/ + @NotBlank(message = "ID不能为空") + @ApiModelProperty(value = "分组ID", required = true, example = "1", notes = "需要修改的分组ID") + private String id; + + /** + * 分组名称 + */ + @NotBlank(message = "用户ID不能为空") + @ApiModelProperty(value = "用户ID", required = true, example = "1", notes = "系统用户ID") + private String sysUserId; + + /** + * 分组名称 + */ + @NotBlank(message = "分组名称不能为空") + @Length(min = 1, max = 100, message = "字符长度在1-100之间") + @ApiModelProperty(value = "分组名称", required = true, example = "销售组", notes = "分组的名称,1-100字符") + private String groupName; + + /** + * 分组名称 + */ + @NotBlank(message = "组长名称不能为空") + @Length(min = 1, max = 100, message = "字符长度在1-100之间") + @ApiModelProperty(value = "组长名称", required = true, example = "张三", notes = "组长的名称,1-100字符") + private String leaderName; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/module/vo/PlayPersonnelGroupInfoQueryVo.java --- +package com.starry.admin.modules.personnel.module.vo; + +import com.starry.common.domain.BasePageEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 店员分组管理信息 + * + * @author admin + * @since 2024/6/14 14:45 + **/ +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel(value = "分组查询参数", description = "查询店员分组信息的条件参数") +public class PlayPersonnelGroupInfoQueryVo extends BasePageEntity { + + /** + * 分组名称 + */ + @ApiModelProperty(value = "组长名称", example = "张三", notes = "组长的名称,支持模糊查询") + private String leaderName; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/module/vo/PlayPersonnelGroupInfoReturnVo.java --- +package com.starry.admin.modules.personnel.module.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 店员分组管理信息 + * + * @author admin + * @since 2024/6/14 14:45 + **/ +@Data +@ApiModel(value = "分组返回数据", description = "店员分组信息的返回数据") +public class PlayPersonnelGroupInfoReturnVo { + + /** + * UUID + */ + @ApiModelProperty(value = "分组ID", example = "1") + private String id; + + /** + * 租户ID + */ + @ApiModelProperty(value = "租户ID", example = "1") + private String tenantId; + + /** + * 用户ID + **/ + @ApiModelProperty(value = "用户ID", example = "1") + private String sysUserId; + + /** + * 用户账号 + **/ + @ApiModelProperty(value = "用户账号", example = "admin") + private String sysUserCode; + + /** + * 分组名称 + */ + @ApiModelProperty(value = "分组名称", example = "销售组") + private String groupName; + + /** + * 组长名称 + **/ + @ApiModelProperty(value = "组长名称", example = "张三") + private String leaderName; + + /** + * 排序 + */ + @ApiModelProperty(value = "排序", example = "1") + private Long sort; + + /** + * 员工总数量 + **/ + @ApiModelProperty(value = "员工总数", example = "10") + private Integer totalEmployeesNumber; + + /** + * 上架员工数量 + **/ + @ApiModelProperty(value = "上架员工数", example = "5") + private Integer listingEmployeesNumber; + + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + @ApiModelProperty(value = "添加时间", example = "2024-01-01 12:00:00") + private LocalDateTime addTime; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/module/vo/PlayPersonnelUserInfoQueryVo.java --- +package com.starry.admin.modules.personnel.module.vo; + +import com.starry.common.domain.BasePageEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @author admin + * @since 2024/6/15 下午9:42 + **/ +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel(value = "用户查询参数", description = "查询系统用户信息的条件参数") +public class PlayPersonnelUserInfoQueryVo extends BasePageEntity { + + /** + * 用户ID + */ + @ApiModelProperty(value = "系统用户ID", example = "1") + private String sysUserId; + + /** + * 用户名称 + */ + @ApiModelProperty(value = "用户账号", example = "admin", notes = "用户登录账号") + private String userCode; + + /** + * 角色类型[0:用户;1:店员;2:组长] + */ + @ApiModelProperty(value = "角色类型", example = "0", notes = "角色类型[0:用户;1:店员;2:组长]") + private String ruleType; + + /** + * 用户ID + */ + @ApiModelProperty(value = "用户ID", example = "1") + private String userId; + + @ApiModelProperty(value = "添加时间范围", example = "['2024-01-01 00:00:00','2024-12-31 23:59:59']", notes = "用户添加时间范围,包含开始和结束时间") + private List addTime; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/module/vo/PlayPersonnelUserInfoReturnVo.java --- +package com.starry.admin.modules.personnel.module.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author admin + * @since 2024/6/15 下午9:42 + **/ +@Data +@ApiModel(value = "用户返回数据", description = "系统用户信息的返回数据") +public class PlayPersonnelUserInfoReturnVo { + /** + * 店员ID + */ + @ApiModelProperty(value = "店员ID", example = "1") + private String clerkId; + + /** + * 店员昵称 + */ + @ApiModelProperty(value = "店员昵称", example = "小明") + private String clerkNickname; + + /** + * 店员头像 + */ + @ApiModelProperty(value = "店员头像", example = "https://example.com/avatar.jpg") + private String clerkAvatar; + + @ApiModelProperty(value = "用户ID", example = "1") + private String userId; + + @ApiModelProperty(value = "用户账号", example = "admin") + private String userCode; + + /** + * 创建时间 + */ + @ApiModelProperty(value = "创建时间", example = "2024-01-01 12:00:00") + private String addTime; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/module/vo/PlayPersonnelWaiterInfoEditAddInfoVo.java --- +package com.starry.admin.modules.personnel.module.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotBlank; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +/** + * 客户基本信息修改 + * + * @author admin + * @since 2024/6/14 14:45 + **/ +@Data +@ApiModel(value = "新增客服参数", description = "新增客服信息的请求参数") +public class PlayPersonnelWaiterInfoEditAddInfoVo { + + /** + * 分组名称 + */ + @NotBlank(message = "用户ID不能为空") + @ApiModelProperty(value = "用户ID", required = true, example = "1", notes = "系统用户ID") + private String sysUserId; + + /** + * 客服名称 + */ + @NotBlank(message = "客服名称不能为空") + @Length(min = 1, max = 100, message = "字符长度在1-100之间") + @ApiModelProperty(value = "客服名称", required = true, example = "张三", notes = "客服的名称,1-100字符") + private String waiterName; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/module/vo/PlayPersonnelWaiterInfoEditBaseInfoVo.java --- +package com.starry.admin.modules.personnel.module.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotBlank; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +/** + * 客户基本信息修改 + * + * @author admin + * @since 2024/6/14 14:45 + **/ +@Data +@ApiModel(value = "修改客服参数", description = "修改客服信息的请求参数") +public class PlayPersonnelWaiterInfoEditBaseInfoVo { + /** + * UUID + * + * @since 2024/6/14 16:08 + **/ + @NotBlank(message = "ID不能为空") + @ApiModelProperty(value = "客服ID", required = true, example = "1", notes = "需要修改的客服ID") + private String id; + + /** + * 分组名称 + */ + @NotBlank(message = "用户ID不能为空") + @ApiModelProperty(value = "用户ID", required = true, example = "1", notes = "系统用户ID") + private String sysUserId; + + /** + * 客服名称 + */ + @NotBlank(message = "客服名称不能为空") + @Length(min = 1, max = 100, message = "字符长度在1-100之间") + @ApiModelProperty(value = "客服名称", required = true, example = "张三", notes = "客服的名称,1-100字符") + private String waiterName; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/module/vo/PlayPersonnelWaiterInfoQueryVo.java --- +package com.starry.admin.modules.personnel.module.vo; + +import com.starry.common.domain.BasePageEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 客户管理信息 + * + * @author admin + * @since 2024/6/14 14:45 + **/ +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel(value = "客服查询参数", description = "查询客服信息的条件参数") +public class PlayPersonnelWaiterInfoQueryVo extends BasePageEntity { + + /** + * 分组名称 + */ + @ApiModelProperty(value = "客服名称", example = "张三", notes = "客服的名称,支持模糊查询") + private String waiterName; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/module/vo/PlayPersonnelWaiterInfoReturnVo.java --- +package com.starry.admin.modules.personnel.module.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 客户管理信息 + * + * @author admin + * @since 2024/6/14 14:45 + **/ +@Data +@ApiModel(value = "客服返回数据", description = "客服信息的返回数据") +public class PlayPersonnelWaiterInfoReturnVo { + + /** + * UUID + */ + @ApiModelProperty(value = "客服ID", example = "1") + private String id; + + /** + * 租户ID + */ + @ApiModelProperty(value = "租户ID", example = "1") + private String tenantId; + + /** + * 用户ID + **/ + @ApiModelProperty(value = "用户ID", example = "1") + private String sysUserId; + + /** + * 用户账号 + **/ + @ApiModelProperty(value = "用户账号", example = "admin") + private String sysUserCode; + + /** + * 客户名称 + */ + @ApiModelProperty(value = "客服名称", example = "张三") + private String waiterName; + + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + @ApiModelProperty(value = "添加时间", example = "2024-01-01 12:00:00") + private LocalDateTime addTime; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/service/IPlayBalanceDetailsInfoService.java --- +package com.starry.admin.modules.personnel.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.personnel.module.entity.PlayBalanceDetailsInfoEntity; +import com.starry.admin.modules.personnel.module.vo.PlayBalanceDetailsQueryVo; +import com.starry.admin.modules.personnel.module.vo.PlayBalanceDetailsReturnVo; +import java.math.BigDecimal; + +/** + * 余额明细Service接口 + * + * @author admin + * @since 2024-04-30 + */ +public interface IPlayBalanceDetailsInfoService extends IService { + + /** + * 查询余额明细 + * + * @param id + * 余额明细主键 + * @return 余额明细 + */ + PlayBalanceDetailsInfoEntity selectPlayBalanceDetailsInfoById(String id); + + /** + * 查询余额明细列表 + * + * @param vo + * 余额明细查询对象 + * @return 余额明细集合 + */ + IPage selectByPage(PlayBalanceDetailsQueryVo vo); + + /** + * 查询余额明细列表 + * + * @param playBalanceDetailsInfo + * 余额明细 + * @return 余额明细集合 + */ + IPage selectPlayBalanceDetailsInfoByPage( + PlayBalanceDetailsInfoEntity playBalanceDetailsInfo); + + /** + * 新增余额明细信息 + * + * @param userType + * 用户类型[0:陪聊;1:顾客] + * @param userId + * 用户ID + * @param balanceBeforeOperation + * 操作前余额 + * @param balanceAfterOperation + * 操作后余额 + * @param operationType + * 操作类型(0:充值;1:消费,2:服务;3:退款) + * @param operationAction + * 操作动作 + * @param balanceMoney + * 操作金额 + * @param giftAmount + * 赠送金额 + * @param orderId + * 订单ID + */ + void insertBalanceDetailsInfo(String userType, String userId, BigDecimal balanceBeforeOperation, + BigDecimal balanceAfterOperation, String operationType, String operationAction, BigDecimal balanceMoney, + BigDecimal giftAmount, String orderId); + + /** + * 新增余额明细 + * + * @param playBalanceDetailsInfo + * 余额明细 + * @return 结果 + */ + boolean create(PlayBalanceDetailsInfoEntity playBalanceDetailsInfo); + + /** + * 修改余额明细 + * + * @param playBalanceDetailsInfo + * 余额明细 + * @return 结果 + */ + boolean update(PlayBalanceDetailsInfoEntity playBalanceDetailsInfo); + + /** + * 批量删除余额明细 + * + * @param ids + * 需要删除的余额明细主键集合 + * @return 结果 + */ + int deletePlayBalanceDetailsInfoByIds(String[] ids); + + /** + * 删除余额明细信息 + * + * @param id + * 余额明细主键 + * @return 结果 + */ + int deletePlayBalanceDetailsInfoById(String id); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/service/IPlayPersonnelAdminInfoService.java --- +package com.starry.admin.modules.personnel.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.personnel.module.entity.PlayPersonnelAdminInfoEntity; +import com.starry.admin.modules.personnel.module.vo.PlayPersonnelAdminInfoQueryVo; +import com.starry.admin.modules.personnel.module.vo.PlayPersonnelAdminInfoReturnVo; + +/** + * 管理员管理Service接口 + * + * @author admin + * @since 2024-06-14 + */ +public interface IPlayPersonnelAdminInfoService extends IService { + + /** + * 查询店员分组信息 + * + * @param userId + * 用户ID + * @return 店员分组信息 + */ + PlayPersonnelAdminInfoEntity selectByUserId(String userId); + + /** + * 查询管理员管理 + * + * @param id + * 管理员管理主键 + * @return 管理员管理 + */ + PlayPersonnelAdminInfoEntity selectPlayPersonnelAdminInfoById(String id); + + /** + * 查询管理员管理列表 + * + * @param vo + * 管理员管理 + * @return 管理员管理集合 + */ + IPage selectByPage(PlayPersonnelAdminInfoQueryVo vo); + + /** + * 新增管理员管理 + * + * @param playPersonnelAdminInfo + * 管理员管理 + * @return 结果 + */ + boolean create(PlayPersonnelAdminInfoEntity playPersonnelAdminInfo); + + /** + * 修改管理员管理 + * + * @param playPersonnelAdminInfo + * 管理员管理 + * @return 结果 + */ + boolean update(PlayPersonnelAdminInfoEntity playPersonnelAdminInfo); + + /** + * 批量删除管理员管理 + * + * @param ids + * 需要删除的管理员管理主键集合 + * @return 结果 + */ + int deletePlayPersonnelAdminInfoByIds(String[] ids); + + /** + * 删除管理员管理信息 + * + * @param id + * 管理员管理主键 + */ + void deletePlayPersonnelAdminInfoById(String id); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/service/IPlayPersonnelGroupInfoService.java --- +package com.starry.admin.modules.personnel.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.common.domain.LoginUser; +import com.starry.admin.modules.personnel.module.entity.PlayPersonnelGroupInfoEntity; +import com.starry.admin.modules.personnel.module.vo.PlayPersonnelGroupInfoQueryVo; +import com.starry.admin.modules.personnel.module.vo.PlayPersonnelGroupInfoReturnVo; +import java.util.List; + +/** + * 店员分组信息Service接口 + * + * @author admin + * @since 2024-05-31 + */ +public interface IPlayPersonnelGroupInfoService extends IService { + /** + * 查询店员分组信息 + * + * @param id + * 店员分组信息主键 + * @return 店员分组信息 + */ + PlayPersonnelGroupInfoEntity selectPlayClerkGroupInfoById(String id); + + /** + * 查询店员分组信息 + * + * @param userId + * 用户ID + * @return 店员分组信息 + */ + PlayPersonnelGroupInfoEntity selectByUserId(String userId); + + /** + * 查询店员分组信息列表 + * + * @return PlayPersonnelGroupInfoReturnVo + * @author admin + * @since 2024/6/14 15:46 + **/ + List selectAll(); + + /** + * 分页查询店员分组信息列表 + * + * @param vo + * 查询店员分组信息查询对象 + * @return PlayPersonnelGroupInfoReturnVo + * @author admin + * @since 2024/6/14 15:46 + **/ + IPage selectByPage(PlayPersonnelGroupInfoQueryVo vo); + + /** + * 新增店员分组信息 + * + * @param playClerkGroupInfo + * 店员分组信息 + * @return 结果 + */ + boolean create(PlayPersonnelGroupInfoEntity playClerkGroupInfo); + + /** + * 修改店员分组信息 + * + * @param playClerkGroupInfo + * 店员分组信息 + * @return 结果 + */ + boolean update(PlayPersonnelGroupInfoEntity playClerkGroupInfo); + + /** + * 批量删除店员分组信息 + * + * @param ids + * 需要删除的店员分组信息主键集合 + * @return 结果 + */ + int deletePlayClerkGroupInfoByIds(String[] ids); + + /** + * 删除店员分组信息信息 + * + * @param id + * 店员分组信息主键 + */ + void deletePlayClerkGroupInfoById(String id); + + /** + * 筛选所有的组员 + * + * @param loginUser + * 登录用户 + * @param clerkNickName + * @return 组员ID列表 + */ + List getValidClerkIdList(LoginUser loginUser, String clerkNickName); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/service/IPlayPersonnelWaiterInfoService.java --- +package com.starry.admin.modules.personnel.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.personnel.module.entity.PlayPersonnelWaiterInfoEntity; +import com.starry.admin.modules.personnel.module.vo.PlayPersonnelWaiterInfoQueryVo; +import com.starry.admin.modules.personnel.module.vo.PlayPersonnelWaiterInfoReturnVo; + +/** + * 客服信息Service接口 + * + * @author admin + * @since 2024-06-14 + */ +public interface IPlayPersonnelWaiterInfoService extends IService { + + /** + * 查询店员客服信息 + * + * @param userId + * 用户ID + * @return 店员分组信息 + */ + PlayPersonnelWaiterInfoEntity selectByUserId(String userId); + + /** + * 查询客服信息 + * + * @param id + * 客服信息主键 + * @return 客服信息 + */ + PlayPersonnelWaiterInfoEntity selectPlayClerkWaiterInfoById(String id); + + /** + * 查询客服信息列表 + * + * @param vo + * 客服信息 + * @return 客服信息集合 + */ + IPage selectByPage(PlayPersonnelWaiterInfoQueryVo vo); + + /** + * 新增客服信息 + * + * @param playClerkWaiterInfo + * 客服信息 + * @return 结果 + */ + boolean create(PlayPersonnelWaiterInfoEntity playClerkWaiterInfo); + + /** + * 修改客服信息 + * + * @param playClerkWaiterInfo + * 客服信息 + * @return 结果 + */ + boolean update(PlayPersonnelWaiterInfoEntity playClerkWaiterInfo); + + /** + * 批量删除客服信息 + * + * @param ids + * 需要删除的客服信息主键集合 + * @return 结果 + */ + int deletePlayClerkWaiterInfoByIds(String[] ids); + + /** + * 删除客服信息信息 + * + * @param id + * 客服信息主键 + */ + void deletePlayClerkWaiterInfoById(String id); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/service/impl/PlayBalanceDetailsInfoServiceImpl.java --- +package com.starry.admin.modules.personnel.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.github.yulichang.wrapper.MPJLambdaWrapper; +import com.starry.admin.modules.custom.module.entity.PlayCustomUserInfoEntity; +import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity; +import com.starry.admin.modules.order.service.IPlayOrderInfoService; +import com.starry.admin.modules.personnel.mapper.PlayBalanceDetailsInfoMapper; +import com.starry.admin.modules.personnel.module.entity.PlayBalanceDetailsInfoEntity; +import com.starry.admin.modules.personnel.module.vo.PlayBalanceDetailsQueryVo; +import com.starry.admin.modules.personnel.module.vo.PlayBalanceDetailsReturnVo; +import com.starry.admin.modules.personnel.service.IPlayBalanceDetailsInfoService; +import com.starry.common.utils.IdUtils; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.Arrays; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 余额明细Service业务层处理 + * + * @author admin + * @since 2024-04-30 + */ +@Service +public class PlayBalanceDetailsInfoServiceImpl + extends + ServiceImpl + implements + IPlayBalanceDetailsInfoService { + @Resource + private PlayBalanceDetailsInfoMapper playBalanceDetailsInfoMapper; + + @Resource + private IPlayOrderInfoService playOrderInfoService; + + /** + * 查询余额明细 + * + * @param id + * 余额明细主键 + * @return 余额明细 + */ + @Override + public PlayBalanceDetailsInfoEntity selectPlayBalanceDetailsInfoById(String id) { + return this.baseMapper.selectById(id); + } + + @Override + public IPage selectByPage(PlayBalanceDetailsQueryVo vo) { + MPJLambdaWrapper lambdaQueryWrapper = new MPJLambdaWrapper() + // 查询主表全部字段 + .selectAll(PlayBalanceDetailsInfoEntity.class) + // 查询顾客表 + .selectAs(PlayCustomUserInfoEntity::getId, "customId") + .selectAs(PlayCustomUserInfoEntity::getNickname, "customNickname") + .selectAs(PlayCustomUserInfoEntity::getAvatar, "customAvatar") + // 查询订单表 + // .selectAs(PlayOrderInfoEntity::getId, + // "orderId").selectAs(PlayOrderInfoEntity::getOrderNo, + // "orderNo").selectAs(PlayOrderInfoEntity::getPayMethod,"payMethod") + .selectAll(PlayOrderInfoEntity.class) + .leftJoin(PlayOrderInfoEntity.class, PlayOrderInfoEntity::getId, + PlayBalanceDetailsInfoEntity::getOrderId) + .leftJoin(PlayCustomUserInfoEntity.class, PlayCustomUserInfoEntity::getId, + PlayBalanceDetailsInfoEntity::getUserId); + + if (StrUtil.isNotBlank(vo.getPayMethod())) { + lambdaQueryWrapper.eq(PlayOrderInfoEntity::getPayMethod, vo.getPayMethod()); + } + if (StrUtil.isNotBlank(vo.getOperationType())) { + lambdaQueryWrapper.eq(PlayBalanceDetailsInfoEntity::getOperationType, vo.getOperationType()); + } + if (StrUtil.isNotBlank(vo.getUserType())) { + lambdaQueryWrapper.eq(PlayBalanceDetailsInfoEntity::getUserType, vo.getUserType()); + } + if (StrUtil.isNotBlank(vo.getNickname())) { + lambdaQueryWrapper.like(PlayCustomUserInfoEntity::getNickname, vo.getNickname()); + } + if (StrUtil.isNotBlank(vo.getUserId())) { + lambdaQueryWrapper.like(PlayBalanceDetailsInfoEntity::getUserId, vo.getUserId()); + } + + if (!vo.getOperationTime().isEmpty()) { + lambdaQueryWrapper.between(PlayBalanceDetailsInfoEntity::getOperationTime, vo.getOperationTime().get(0), + vo.getOperationTime().get(1)); + } + lambdaQueryWrapper.orderByDesc(PlayBalanceDetailsInfoEntity::getOperationTime); + return this.baseMapper.selectJoinPage(new Page<>(vo.getPageNum(), vo.getPageSize()), + PlayBalanceDetailsReturnVo.class, lambdaQueryWrapper); + + } + + /** + * 查询余额明细列表 + * + * @param playBalanceDetailsInfo + * 余额明细 + * @return 余额明细 + */ + @Override + public IPage selectPlayBalanceDetailsInfoByPage( + PlayBalanceDetailsInfoEntity playBalanceDetailsInfo) { + Page page = new Page<>(1, 10); + return this.baseMapper.selectPage(page, new LambdaQueryWrapper<>()); + } + + @Override + public void insertBalanceDetailsInfo(String userType, String userId, BigDecimal balanceBeforeOperation, + BigDecimal balanceAfterOperation, String operationType, String operationAction, BigDecimal balanceMoney, + BigDecimal giftAmount, String orderId) { + PlayOrderInfoEntity orderInfo = playOrderInfoService.selectOrderInfoById(orderId); + PlayBalanceDetailsInfoEntity entity = new PlayBalanceDetailsInfoEntity(); + entity.setId(IdUtils.getUuid()); + entity.setUserType(userType); + entity.setUserId(userId); + entity.setBalanceBeforeOperation(balanceBeforeOperation); + entity.setBalanceAfterOperation(balanceAfterOperation); + entity.setOperationType(operationType); + entity.setBalanceMoney(balanceMoney); + entity.setGiftAmount(giftAmount); + entity.setPaymentAmount(orderInfo == null ? balanceMoney : orderInfo.getFinalAmount()); + entity.setOperationTime(LocalDateTime.now()); + entity.setOrderId(orderId); + this.baseMapper.insert(entity); + } + + /** + * 新增余额明细 + * + * @param playBalanceDetailsInfo + * 余额明细 + * @return 结果 + */ + @Override + public boolean create(PlayBalanceDetailsInfoEntity playBalanceDetailsInfo) { + if (StrUtil.isBlankIfStr(playBalanceDetailsInfo.getId())) { + playBalanceDetailsInfo.setId(IdUtils.getUuid()); + } + return save(playBalanceDetailsInfo); + } + + /** + * 修改余额明细 + * + * @param playBalanceDetailsInfo + * 余额明细 + * @return 结果 + */ + @Override + public boolean update(PlayBalanceDetailsInfoEntity playBalanceDetailsInfo) { + return updateById(playBalanceDetailsInfo); + } + + /** + * 批量删除余额明细 + * + * @param ids + * 需要删除的余额明细主键 + * @return 结果 + */ + @Override + public int deletePlayBalanceDetailsInfoByIds(String[] ids) { + return playBalanceDetailsInfoMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除余额明细信息 + * + * @param id + * 余额明细主键 + * @return 结果 + */ + @Override + public int deletePlayBalanceDetailsInfoById(String id) { + return playBalanceDetailsInfoMapper.deleteById(id); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/service/impl/PlayPersonnelAdminInfoServiceImpl.java --- +package com.starry.admin.modules.personnel.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.github.yulichang.wrapper.MPJLambdaWrapper; +import com.starry.admin.modules.personnel.mapper.PlayPersonnelAdminInfoMapper; +import com.starry.admin.modules.personnel.module.entity.PlayPersonnelAdminInfoEntity; +import com.starry.admin.modules.personnel.module.vo.PlayPersonnelAdminInfoQueryVo; +import com.starry.admin.modules.personnel.module.vo.PlayPersonnelAdminInfoReturnVo; +import com.starry.admin.modules.personnel.service.IPlayPersonnelAdminInfoService; +import com.starry.common.utils.IdUtils; +import java.util.Arrays; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 管理员管理Service业务层处理 + * + * @author admin + * @since 2024-06-14 + */ +@Service +public class PlayPersonnelAdminInfoServiceImpl + extends + ServiceImpl + implements + IPlayPersonnelAdminInfoService { + @Resource + private PlayPersonnelAdminInfoMapper playPersonnelAdminInfoMapper; + + @Override + public PlayPersonnelAdminInfoEntity selectByUserId(String userId) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(PlayPersonnelAdminInfoEntity::getSysUserId, userId); + return this.baseMapper.selectOne(queryWrapper); + } + + /** + * 查询管理员管理 + * + * @param id + * 管理员管理主键 + * @return 管理员管理 + */ + @Override + public PlayPersonnelAdminInfoEntity selectPlayPersonnelAdminInfoById(String id) { + return this.baseMapper.selectById(id); + } + + @Override + public IPage selectByPage(PlayPersonnelAdminInfoQueryVo vo) { + MPJLambdaWrapper lambdaWrapper = new MPJLambdaWrapper<>(); + if (StrUtil.isNotBlank(vo.getAdminName())) { + lambdaWrapper.eq(PlayPersonnelAdminInfoEntity::getAdminName, vo.getAdminName()); + } + return this.baseMapper.selectJoinPage(new Page<>(vo.getPageNum(), vo.getPageSize()), + PlayPersonnelAdminInfoReturnVo.class, lambdaWrapper); + } + + /** + * 新增管理员管理 + * + * @param playPersonnelAdminInfo + * 管理员管理 + * @return 结果 + */ + @Override + public boolean create(PlayPersonnelAdminInfoEntity playPersonnelAdminInfo) { + if (StrUtil.isBlankIfStr(playPersonnelAdminInfo.getId())) { + playPersonnelAdminInfo.setId(IdUtils.getUuid()); + } + return save(playPersonnelAdminInfo); + } + + /** + * 修改管理员管理 + * + * @param playPersonnelAdminInfo + * 管理员管理 + * @return 结果 + */ + @Override + public boolean update(PlayPersonnelAdminInfoEntity playPersonnelAdminInfo) { + return updateById(playPersonnelAdminInfo); + } + + /** + * 批量删除管理员管理 + * + * @param ids + * 需要删除的管理员管理主键 + * @return 结果 + */ + @Override + public int deletePlayPersonnelAdminInfoByIds(String[] ids) { + return playPersonnelAdminInfoMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除管理员管理信息 + * + * @param id + * 管理员管理主键 + */ + @Override + public void deletePlayPersonnelAdminInfoById(String id) { + playPersonnelAdminInfoMapper.deleteById(id); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/service/impl/PlayPersonnelGroupInfoServiceImpl.java --- +package com.starry.admin.modules.personnel.service.impl; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.github.yulichang.wrapper.MPJLambdaWrapper; +import com.starry.admin.common.domain.LoginUser; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity; +import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService; +import com.starry.admin.modules.personnel.mapper.PlayPersonnelGroupInfoMapper; +import com.starry.admin.modules.personnel.module.entity.PlayPersonnelGroupInfoEntity; +import com.starry.admin.modules.personnel.module.vo.PlayPersonnelGroupInfoQueryVo; +import com.starry.admin.modules.personnel.module.vo.PlayPersonnelGroupInfoReturnVo; +import com.starry.admin.modules.personnel.service.IPlayPersonnelGroupInfoService; +import com.starry.common.utils.IdUtils; +import com.starry.common.utils.StringUtils; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 店员分组信息Service业务层处理 + * + * @author admin + * @since 2024-05-31 + */ +@Service +public class PlayPersonnelGroupInfoServiceImpl + extends + ServiceImpl + implements + IPlayPersonnelGroupInfoService { + @Resource + private PlayPersonnelGroupInfoMapper playClerkGroupInfoMapper; + @Resource + private IPlayClerkUserInfoService clerkUserInfoService; + + /** + * 查询店员分组信息 + * + * @param id + * 店员分组信息主键 + * @return 店员分组信息 + */ + @Override + public PlayPersonnelGroupInfoEntity selectPlayClerkGroupInfoById(String id) { + return this.baseMapper.selectById(id); + } + + @Override + public PlayPersonnelGroupInfoEntity selectByUserId(String userId) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(PlayPersonnelGroupInfoEntity::getSysUserId, userId); + return this.baseMapper.selectOne(queryWrapper); + } + + @Override + public List selectAll() { + return this.baseMapper.selectList(new LambdaQueryWrapper<>()); + } + + @Override + public IPage selectByPage(PlayPersonnelGroupInfoQueryVo vo) { + MPJLambdaWrapper lambdaQueryWrapper = new MPJLambdaWrapper<>(); + if (StrUtil.isNotBlank(vo.getLeaderName())) { + lambdaQueryWrapper.eq(PlayPersonnelGroupInfoEntity::getLeaderName, vo.getLeaderName()); + } + return this.baseMapper.selectJoinPage(new Page<>(vo.getPageNum(), vo.getPageSize()), + PlayPersonnelGroupInfoReturnVo.class, lambdaQueryWrapper); + } + + /** + * 新增店员分组信息 + * + * @param playClerkGroupInfo + * 店员分组信息 + * @return 结果 + */ + @Override + public boolean create(PlayPersonnelGroupInfoEntity playClerkGroupInfo) { + if (StrUtil.isBlankIfStr(playClerkGroupInfo.getId())) { + playClerkGroupInfo.setId(IdUtils.getUuid()); + } + return save(playClerkGroupInfo); + } + + /** + * 修改店员分组信息 + * + * @param playClerkGroupInfo + * 店员分组信息 + * @return 结果 + */ + @Override + public boolean update(PlayPersonnelGroupInfoEntity playClerkGroupInfo) { + return updateById(playClerkGroupInfo); + } + + /** + * 批量删除店员分组信息 + * + * @param ids + * 需要删除的店员分组信息主键 + * @return 结果 + */ + @Override + public int deletePlayClerkGroupInfoByIds(String[] ids) { + return playClerkGroupInfoMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除店员分组信息信息 + * + * @param id + * 店员分组信息主键 + */ + @Override + public void deletePlayClerkGroupInfoById(String id) { + playClerkGroupInfoMapper.deleteById(id); + } + + @Override + public List getValidClerkIdList(LoginUser loginUser, String clerkNickName) { + List idList; + PlayPersonnelGroupInfoEntity groupInfoEntity = this.selectByUserId(loginUser.getUserId()); + if (Objects.nonNull(groupInfoEntity)) { + List list = clerkUserInfoService + .list(Wrappers.lambdaQuery(PlayClerkUserInfoEntity.class) + .eq(PlayClerkUserInfoEntity::getGroupId, groupInfoEntity.getId()) + .select(PlayClerkUserInfoEntity::getId)); + idList = list.stream().map(PlayClerkUserInfoEntity::getId).collect(Collectors.toList()); + PlayClerkUserInfoEntity entity = clerkUserInfoService + .getOne(Wrappers.lambdaQuery(PlayClerkUserInfoEntity.class) + .eq(PlayClerkUserInfoEntity::getSysUserId, loginUser.getUserId()), false); + if (Objects.nonNull(entity)) { + idList.add(entity.getId()); + } + } else { + // 返回所有的clerkId + idList = clerkUserInfoService + .list(Wrappers.lambdaQuery(PlayClerkUserInfoEntity.class).select(PlayClerkUserInfoEntity::getId) + .eq(PlayClerkUserInfoEntity::getClerkState, "1")) + .stream().map(PlayClerkUserInfoEntity::getId).collect(Collectors.toList()); + } + + if (CollectionUtil.isEmpty(idList)) { + idList = Collections.singletonList("-999"); + } + // 加入nickName的筛选 + if (StringUtils.isNotEmpty(clerkNickName)) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(PlayClerkUserInfoEntity.class) + .in(PlayClerkUserInfoEntity::getId, idList) + .like(PlayClerkUserInfoEntity::getNickname, clerkNickName).select(PlayClerkUserInfoEntity::getId); + idList = clerkUserInfoService.list(wrapper).stream().map(PlayClerkUserInfoEntity::getId) + .collect(Collectors.toList()); + } + if (CollectionUtil.isEmpty(idList)) { + idList = Collections.singletonList("-999"); + } + return idList; + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/personnel/service/impl/PlayPersonnelWaiterInfoServiceImpl.java --- +package com.starry.admin.modules.personnel.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.github.yulichang.wrapper.MPJLambdaWrapper; +import com.starry.admin.modules.personnel.mapper.PlayPersonnelWaiterInfoMapper; +import com.starry.admin.modules.personnel.module.entity.PlayPersonnelWaiterInfoEntity; +import com.starry.admin.modules.personnel.module.vo.PlayPersonnelWaiterInfoQueryVo; +import com.starry.admin.modules.personnel.module.vo.PlayPersonnelWaiterInfoReturnVo; +import com.starry.admin.modules.personnel.service.IPlayPersonnelWaiterInfoService; +import com.starry.common.utils.IdUtils; +import java.util.Arrays; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 客服信息Service业务层处理 + * + * @author admin + * @since 2024-06-14 + */ +@Service +public class PlayPersonnelWaiterInfoServiceImpl + extends + ServiceImpl + implements + IPlayPersonnelWaiterInfoService { + @Resource + private PlayPersonnelWaiterInfoMapper playClerkWaiterInfoMapper; + + @Override + public PlayPersonnelWaiterInfoEntity selectByUserId(String userId) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(PlayPersonnelWaiterInfoEntity::getSysUserId, userId); + return this.baseMapper.selectOne(queryWrapper); + } + + /** + * 查询客服信息 + * + * @param id + * 客服信息主键 + * @return 客服信息 + */ + @Override + public PlayPersonnelWaiterInfoEntity selectPlayClerkWaiterInfoById(String id) { + return this.baseMapper.selectById(id); + } + + @Override + public IPage selectByPage(PlayPersonnelWaiterInfoQueryVo vo) { + MPJLambdaWrapper lambdaWrapper = new MPJLambdaWrapper<>(); + if (StrUtil.isNotBlank(vo.getWaiterName())) { + lambdaWrapper.eq(PlayPersonnelWaiterInfoEntity::getWaiterName, vo.getWaiterName()); + } + return this.baseMapper.selectJoinPage(new Page<>(vo.getPageNum(), vo.getPageSize()), + PlayPersonnelWaiterInfoReturnVo.class, lambdaWrapper); + } + + /** + * 新增客服信息 + * + * @param playClerkWaiterInfo + * 客服信息 + * @return 结果 + */ + @Override + public boolean create(PlayPersonnelWaiterInfoEntity playClerkWaiterInfo) { + if (StrUtil.isBlankIfStr(playClerkWaiterInfo.getId())) { + playClerkWaiterInfo.setId(IdUtils.getUuid()); + } + return save(playClerkWaiterInfo); + } + + /** + * 修改客服信息 + * + * @param playClerkWaiterInfo + * 客服信息 + * @return 结果 + */ + @Override + public boolean update(PlayPersonnelWaiterInfoEntity playClerkWaiterInfo) { + return updateById(playClerkWaiterInfo); + } + + /** + * 批量删除客服信息 + * + * @param ids + * 需要删除的客服信息主键 + * @return 结果 + */ + @Override + public int deletePlayClerkWaiterInfoByIds(String[] ids) { + return playClerkWaiterInfoMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除客服信息信息 + * + * @param id + * 客服信息主键 + */ + @Override + public void deletePlayClerkWaiterInfoById(String id) { + playClerkWaiterInfoMapper.deleteById(id); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/controller/PlayClerkGiftInfoController.java --- +package com.starry.admin.modules.shop.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.modules.shop.module.entity.PlayClerkGiftInfoEntity; +import com.starry.admin.modules.shop.service.IPlayClerkGiftInfoService; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import javax.annotation.Resource; +import org.springframework.web.bind.annotation.*; + +/** + * 店员和礼物关系Controller + * + * @author admin + * @since 2024-05-25 + */ +@Api(tags = "店员礼物关联管理", description = "店员和礼物关系管理相关接口,包括查询、新增、修改和删除等操作") +@RestController +@RequestMapping("/play/clerkGift") +public class PlayClerkGiftInfoController { + @Resource + private IPlayClerkGiftInfoService playClerkGiftInfoService; + + /** + * 查询店员和礼物关系列表 + */ + @ApiOperation(value = "查询店员礼物关联列表", notes = "分页查询店员和礼物关系列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayClerkGiftInfoEntity.class, responseContainer = "Page")}) + @GetMapping("/list") + public R list(@ApiParam(value = "查询条件") PlayClerkGiftInfoEntity playClerkGiftInfo) { + IPage list = playClerkGiftInfoService.selectPlayClerkGiftInfoByPage(playClerkGiftInfo); + return R.ok(list); + } + + /** + * 获取店员和礼物关系详细信息 + */ + @ApiOperation(value = "获取关联详情", notes = "根据ID获取店员和礼物关系详细信息") + @ApiImplicitParam(name = "id", value = "关联ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = PlayClerkGiftInfoEntity.class)}) + @GetMapping(value = "/{id}") + public R getInfo(@PathVariable("id") String id) { + return R.ok(playClerkGiftInfoService.selectPlayClerkGiftInfoById(id)); + } + + /** + * 新增店员和礼物关系 + */ + @ApiOperation(value = "新增关联信息", notes = "新增店员和礼物关系信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "添加失败,包含详细错误信息")}) + @Log(title = "店员和礼物关系", businessType = BusinessType.INSERT) + @PostMapping("/create") + public R create(@ApiParam(value = "关联信息", required = true) @RequestBody PlayClerkGiftInfoEntity playClerkGiftInfo) { + boolean success = playClerkGiftInfoService.create(playClerkGiftInfo); + if (success) { + return R.ok(); + } + return R.error("添加失败"); + } + + /** + * 修改店员和礼物关系 + */ + @ApiOperation(value = "修改关联信息", notes = "修改店员和礼物关系信息") + @ApiImplicitParam(name = "id", value = "关联ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败,包含详细错误信息")}) + @Log(title = "店员和礼物关系", businessType = BusinessType.UPDATE) + @PostMapping(value = "/update/{id}") + public R update(@PathVariable String id, + @ApiParam(value = "关联信息", required = true) @RequestBody PlayClerkGiftInfoEntity playClerkGiftInfo) { + playClerkGiftInfo.setId(id); + boolean success = playClerkGiftInfoService.update(playClerkGiftInfo); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + /** + * 删除店员和礼物关系 + */ + @ApiOperation(value = "删除关联信息", notes = "根据ID批量删除店员和礼物关系信息") + @ApiImplicitParam(name = "ids", value = "关联ID数组", required = true, paramType = "path", dataType = "String[]", example = "1,2,3") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @Log(title = "店员和礼物关系", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@PathVariable String[] ids) { + return R.ok(playClerkGiftInfoService.deletePlayClerkGiftInfoByIds(ids)); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/controller/PlayCommodityInfoController.java --- +package com.starry.admin.modules.shop.controller; + +import cn.hutool.core.bean.BeanUtil; +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.clerk.module.entity.PlayClerkLevelInfoEntity; +import com.starry.admin.modules.clerk.service.IPlayClerkLevelInfoService; +import com.starry.admin.modules.shop.module.entity.PlayCommodityAndLevelInfoEntity; +import com.starry.admin.modules.shop.module.entity.PlayCommodityInfoEntity; +import com.starry.admin.modules.shop.module.vo.PlayCommodityInfoAddVo; +import com.starry.admin.modules.shop.module.vo.PlayCommodityInfoReturnVo; +import com.starry.admin.modules.shop.service.IPlayCommodityAndLevelInfoService; +import com.starry.admin.modules.shop.service.IPlayCommodityInfoService; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import com.starry.common.utils.ConvertUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.annotation.Resource; +import org.springframework.web.bind.annotation.*; + +/** + * 服务项目Controller + * + * @author admin + * @since 2024-03-31 + */ +@Api(tags = "服务项目管理", description = "服务项目信息管理相关接口,包括查询、新增、修改和删除等操作") +@RestController +@RequestMapping("/shop/commodity") +public class PlayCommodityInfoController { + @Resource + private IPlayCommodityInfoService playCommodityInfoService; + + @Resource + private IPlayClerkLevelInfoService playClerkLevelInfoService; + + @Resource + private IPlayCommodityAndLevelInfoService playCommodityAndLevelInfoService; + + @ApiOperation(value = "获取表头信息", notes = "获取店员等级表头信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @GetMapping("/getTableName") + public R getTableName() { + List> result = new ArrayList<>(); + List levelInfoEntities = playClerkLevelInfoService.selectAll(); + for (PlayClerkLevelInfoEntity levelInfoEntity : levelInfoEntities) { + HashMap item = new HashMap<>(); + item.put("prop", levelInfoEntity.getId()); + item.put("name", levelInfoEntity.getName()); + result.add(item); + } + return R.ok(result); + } + + /** + * 查询服务项目类型 + */ + @ApiOperation(value = "查询所有服务项目", notes = "查询所有服务项目类型及其子项目") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @GetMapping("/listAll") + public R queryCommodityType() { + List> result = new ArrayList<>(); + List list = playCommodityInfoService.selectByType(); + for (PlayCommodityInfoEntity entity : list) { + List> itemCommodityInfo = new ArrayList<>(); + Map map = BeanUtil.beanToMap(entity); + List commodityInfoEntities = ConvertUtil.entityToVoList( + playCommodityInfoService.selectByPId(entity.getId()), PlayCommodityInfoReturnVo.class); + for (PlayCommodityInfoReturnVo commodityInfoEntity : commodityInfoEntities) { + Map item = BeanUtil.beanToMap(commodityInfoEntity); + for (PlayClerkLevelInfoEntity playClerkLevelInfoEntity : playClerkLevelInfoService.selectAll()) { + PlayCommodityAndLevelInfoEntity entity1 = playCommodityAndLevelInfoService + .queryById(commodityInfoEntity.getId(), playClerkLevelInfoEntity.getId()); + item.put(playClerkLevelInfoEntity.getId(), entity1 == null ? "未设置价格" : entity1.getPrice()); + } + itemCommodityInfo.add(item); + } + map.put("children", itemCommodityInfo); + result.add(map); + } + return R.ok(result); + } + + /** + * 修改服务项目类型 + */ + @ApiOperation(value = "更新服务项目价格", notes = "根据不同店员等级修改服务项目价格") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "更新失败,包含详细错误信息")}) + @PostMapping("/updateInfo") + public R updateInfo(@ApiParam(value = "价格信息JSON", required = true) @RequestBody String s) { + JSONObject jsonObject = JSON.parseObject(s); + if (!jsonObject.containsKey("id")) { + throw new CustomException("请求参数错误,id不能为空"); + } + System.out.println(s); + for (PlayClerkLevelInfoEntity playClerkLevelInfoEntity : playClerkLevelInfoService.selectAll()) { + if (!jsonObject.containsKey(playClerkLevelInfoEntity.getId())) { + throw new CustomException("请求参数错误"); + } + double price = 0.0; + try { + price = Double.parseDouble(jsonObject.getString(playClerkLevelInfoEntity.getId())); + } catch (RuntimeException e) { + throw new CustomException("请求参数错误,价格格式为空"); + } + PlayCommodityAndLevelInfoEntity entity = playCommodityAndLevelInfoService + .queryById(jsonObject.getString("id"), playClerkLevelInfoEntity.getId()); + if (entity == null) { + entity = new PlayCommodityAndLevelInfoEntity(); + entity.setCommodityId(jsonObject.getString("id")); + entity.setLevelId(playClerkLevelInfoEntity.getId()); + } + entity.setPrice(new BigDecimal(price)); + this.playCommodityAndLevelInfoService.saveOrUpdate(entity); + } + return R.ok("成功"); + } + + /** + * 获取服务项目详细信息 + */ + @ApiOperation(value = "获取服务项目详情", notes = "根据ID获取服务项目详细信息") + @ApiImplicitParam(name = "id", value = "服务项目ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = PlayCommodityInfoEntity.class)}) + @GetMapping(value = "/{id}") + public R getInfo(@PathVariable("id") String id) { + return R.ok(playCommodityInfoService.selectPlayCommodityInfoById(id)); + } + + /** + * 新增服务项目 + */ + @ApiOperation(value = "新增服务项目", notes = "新增服务项目信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "添加失败,包含详细错误信息")}) + @Log(title = "服务项目", businessType = BusinessType.INSERT) + @PostMapping("/create") + public R create(@ApiParam(value = "服务项目信息", required = true) @RequestBody PlayCommodityInfoAddVo vo) { + PlayCommodityInfoEntity entity = ConvertUtil.entityToVo(vo, PlayCommodityInfoEntity.class); + boolean success = playCommodityInfoService.create(entity); + if (success) { + return R.ok(); + } + return R.error("添加失败"); + } + + /** + * 修改服务项目 + */ + @ApiOperation(value = "修改服务项目", notes = "修改服务项目信息") + @ApiImplicitParam(name = "id", value = "服务项目ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败,包含详细错误信息")}) + @Log(title = "服务项目", businessType = BusinessType.UPDATE) + @PostMapping(value = "/update/{id}") + public R update(@PathVariable String id, + @ApiParam(value = "服务项目信息", required = true) @RequestBody PlayCommodityInfoEntity playCommodityInfo) { + playCommodityInfo.setId(id); + boolean success = playCommodityInfoService.update(playCommodityInfo); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + /** + * 删除服务项目 + */ + @ApiOperation(value = "删除服务项目", notes = "根据ID批量删除服务项目信息") + @ApiImplicitParam(name = "ids", value = "服务项目ID数组", required = true, paramType = "path", dataType = "String[]", example = "1,2,3") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @Log(title = "服务项目", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@PathVariable String[] ids) { + return R.ok(playCommodityInfoService.deletePlayCommodityInfoByIds(ids)); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/controller/PlayCouponDetailsController.java --- +package com.starry.admin.modules.shop.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.modules.shop.module.entity.PlayCouponDetailsEntity; +import com.starry.admin.modules.shop.module.vo.PlayCouponDetailsQueryVo; +import com.starry.admin.modules.shop.module.vo.PlayCouponDetailsReturnVo; +import com.starry.admin.modules.shop.module.vo.PlayCouponDetailsUpdateUseStateVo; +import com.starry.admin.modules.shop.service.IPlayCouponDetailsService; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 优惠券详情Controller + * + * @author admin + * @since 2024-07-04 + */ +@Api(tags = "优惠券记录管理", description = "优惠券使用记录管理相关接口,包括查询、新增、修改和删除等操作") +@RestController +@RequestMapping("/shop/couponRecord") +public class PlayCouponDetailsController { + + @Resource + private IPlayCouponDetailsService playCouponDetailsService; + + /** + * 查询优惠券详情列表 + */ + @ApiOperation(value = "分页查询优惠券记录", notes = "分页查询优惠券使用记录列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayCouponDetailsReturnVo.class, responseContainer = "Page")}) + // @PreAuthorize("@customSs.hasPermission('shop:couponDetails:list')") + @PostMapping("/listByPage") + public R listByPage( + @ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayCouponDetailsQueryVo vo) { + IPage list = playCouponDetailsService.selectByPage(vo); + return R.ok(list); + } + + /** + * 获取优惠券详情详细信息 + */ + @ApiOperation(value = "获取优惠券记录详情", notes = "根据ID获取优惠券使用记录详细信息") + @ApiImplicitParam(name = "id", value = "记录ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = PlayCouponDetailsEntity.class)}) + // @PreAuthorize("@customSs.hasPermission('shop:couponDetails:query')") + @GetMapping(value = "/{id}") + public R getInfo(@PathVariable("id") String id) { + return R.ok(playCouponDetailsService.selectPlayCouponDetailsById(id)); + } + + /** + * 新增优惠券详情 + */ + @ApiOperation(value = "新增优惠券记录", notes = "新增优惠券使用记录") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "添加失败,包含详细错误信息")}) + // @PreAuthorize("@customSs.hasPermission('shop:couponDetails:create')") + @Log(title = "优惠券详情", businessType = BusinessType.INSERT) + @PostMapping("/create") + public R create( + @ApiParam(value = "优惠券记录信息", required = true) @RequestBody PlayCouponDetailsEntity playCouponDetails) { + boolean success = playCouponDetailsService.create(playCouponDetails); + if (success) { + return R.ok(); + } + return R.error("添加失败"); + } + + /** + * 更新优惠券使用状态 + * + * @param vo + * 优惠券实体信息 + * @since 2024/7/4 17:15 + **/ + @ApiOperation(value = "更新优惠券使用状态", notes = "批量更新优惠券使用状态") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "更新失败,包含详细错误信息")}) + @PostMapping("/updateUseState") + public R update(@ApiParam(value = "更新状态信息", required = true) PlayCouponDetailsUpdateUseStateVo vo) { + for (String couponId : vo.getCouponIds()) { + playCouponDetailsService.selectPlayCouponDetailsById(couponId); + PlayCouponDetailsEntity entity = new PlayCouponDetailsEntity(); + entity.setId(couponId); + entity.setUseState(vo.getUseState()); + playCouponDetailsService.update(entity); + } + return R.ok(); + } + + /** + * 修改优惠券详情 + */ + @ApiOperation(value = "修改优惠券记录", notes = "修改优惠券使用记录信息") + @ApiImplicitParam(name = "id", value = "记录ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败,包含详细错误信息")}) + // @PreAuthorize("@customSs.hasPermission('shop:couponDetails:edit')") + @Log(title = "优惠券详情", businessType = BusinessType.UPDATE) + @PostMapping(value = "/update/{id}") + public R update(@PathVariable String id, + @ApiParam(value = "优惠券记录信息", required = true) @RequestBody PlayCouponDetailsEntity playCouponDetails) { + playCouponDetails.setId(id); + boolean success = playCouponDetailsService.update(playCouponDetails); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + /** + * 删除优惠券详情 + */ + @ApiOperation(value = "删除优惠券记录", notes = "批量删除优惠券使用记录(逻辑删除)") + @ApiImplicitParam(name = "ids", value = "记录ID数组", required = true, paramType = "path", dataType = "String[]", example = "1,2,3") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + // @PreAuthorize("@customSs.hasPermission('shop:couponDetails:remove')") + @Log(title = "优惠券详情", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@PathVariable String[] ids) { + for (String id : ids) { + PlayCouponDetailsEntity entity = new PlayCouponDetailsEntity(); + entity.setId(id); + entity.setUseState("3"); + playCouponDetailsService.update(entity); + } + return R.ok(); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/controller/PlayCouponInfoController.java --- +package com.starry.admin.modules.shop.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.custom.module.entity.PlayCustomUserInfoEntity; +import com.starry.admin.modules.custom.service.IPlayCustomUserInfoService; +import com.starry.admin.modules.shop.module.entity.PlayCouponInfoEntity; +import com.starry.admin.modules.shop.module.vo.*; +import com.starry.admin.modules.shop.service.IPlayCouponDetailsService; +import com.starry.admin.modules.shop.service.IPlayCouponInfoService; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import com.starry.common.utils.ConvertUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 优惠券信息Controller + * + * @author admin + * @since 2024-07-04 + */ +@Api(tags = "优惠券管理", description = "优惠券信息管理相关接口,包括查询、新增、修改、发放和删除等操作") +@RestController +@RequestMapping("/shop/coupon") +public class PlayCouponInfoController { + @Resource + private IPlayCouponInfoService playCouponInfoService; + + @Resource + private IPlayCouponDetailsService playCouponDetailsService; + + @Resource + private IPlayCustomUserInfoService playCustomUserInfoService; + + /** + * 查询优惠券信息列表 + */ + @ApiOperation(value = "分页查询优惠券列表", notes = "分页查询优惠券信息列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayCouponInfoReturnVo.class, responseContainer = "Page")}) + // @PreAuthorize("@customSs.hasPermission('shop:coupon:list')") + @PostMapping("/listByPage") + public R list(@ApiParam(value = "查询条件") PlayCouponInfoQueryVo vo) { + IPage list = playCouponInfoService.selectByPage(vo); + return R.ok(list); + } + + /** + * 修改优惠券上下架状态 + * + * @param vo + * 优惠券上下架对象 + */ + @ApiOperation(value = "更新优惠券上下架状态", notes = "修改优惠券上下架状态") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "更新失败,包含详细错误信息")}) + @PostMapping("/updateOnLineState") + public R updateOnLineState( + @ApiParam(value = "状态更新信息", required = true) @Validated @RequestBody PlayCouponInfoOnLineStateUpdateVo vo) { + playCouponInfoService.selectPlayCouponInfoById(vo.getId()); + PlayCouponInfoEntity entity = new PlayCouponInfoEntity(); + entity.setId(vo.getId()); + entity.setCouponOnLineState(vo.getCouponOnLineState()); + playCouponInfoService.update(entity); + return R.ok(); + } + + /** + * 发放优惠券 + * + * @param vo + * 优惠券发放对象 + */ + @ApiOperation(value = "发放优惠券", notes = "向指定用户发放优惠券") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "发放失败,包含详细错误信息")}) + @PostMapping("/sendCoupon") + public R sendCoupon(@ApiParam(value = "优惠券发放信息", required = true) @Validated @RequestBody PlayCouponInfoSendVo vo) { + PlayCustomUserInfoEntity customUserInfo = playCustomUserInfoService.selectById(vo.getCustomId()); + playCouponDetailsService.create(customUserInfo.getId(), customUserInfo.getNickname(), + customUserInfo.getLevelId(), vo.getId(), "2", "1"); + return R.ok(); + } + + /** + * 获取优惠券信息详细信息 + */ + @ApiOperation(value = "获取优惠券详情", notes = "根据ID获取优惠券详细信息") + @ApiImplicitParam(name = "id", value = "优惠券ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = PlayCouponInfoEntity.class)}) + // @PreAuthorize("@customSs.hasPermission('shop:coupon:query')") + @GetMapping(value = "/{id}") + public R getInfo(@PathVariable("id") String id) { + return R.ok(playCouponInfoService.selectPlayCouponInfoById(id)); + } + + /** + * 新增优惠券信息 + */ + @ApiOperation(value = "新增优惠券", notes = "新增优惠券信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "添加失败,包含详细错误信息")}) + // @PreAuthorize("@customSs.hasPermission('shop:coupon:create')") + @Log(title = "优惠券信息", businessType = BusinessType.INSERT) + @PostMapping("/create") + public R create(@ApiParam(value = "优惠券信息", required = true) @Validated @RequestBody PlayCouponInfoAddVo vo) { + PlayCouponInfoEntity entity = ConvertUtil.entityToVo(vo, PlayCouponInfoEntity.class); + if ("1".equals(vo.getValidityPeriodType())) { + if (vo.getProductiveTime() == null || vo.getProductiveTime().size() != 2) { + throw new CustomException("用券时间输入错误"); + } + LocalDateTime startTime = LocalDateTime.parse(vo.getProductiveTime().get(0), + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + LocalDateTime endTime = LocalDateTime.parse(vo.getProductiveTime().get(1), + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + if (endTime.isBefore(startTime)) { + throw new CustomException("用券时间输入错误,结束时间大于开始时间"); + } + entity.setProductiveTime(startTime); + entity.setExpirationTime(endTime); + } + if ("2".equals(vo.getValidityPeriodType()) && vo.getEffectiveDay() <= 0) { + throw new CustomException("用券时间输入错误,有效天数不能为0"); + } + String discountContent = ""; + if (BigDecimal.ZERO.compareTo(vo.getUseMinAmount()) == 0) { + discountContent = "无门槛"; + } else { + discountContent = "满" + vo.getUseMinAmount() + "船票"; + } + if ("0".equals(vo.getDiscountType())) { + discountContent += ("减" + vo.getDiscountAmount() + "船票"); + } else { + discountContent += ("打" + vo.getDiscountAmount() + "折"); + } + entity.setDiscountContent(discountContent); + entity.setCouponOnLineState("1"); + boolean success = playCouponInfoService.create(entity); + if (success) { + return R.ok(); + } + return R.error("添加失败"); + } + + /** + * 修改优惠券信息 + */ + @ApiOperation(value = "修改优惠券", notes = "修改优惠券信息") + @ApiImplicitParam(name = "id", value = "优惠券ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败,包含详细错误信息")}) + // @PreAuthorize("@customSs.hasPermission('shop:coupon:edit')") + @Log(title = "优惠券信息", businessType = BusinessType.UPDATE) + @PostMapping(value = "/update/{id}") + public R update(@PathVariable String id, + @ApiParam(value = "优惠券信息", required = true) @RequestBody PlayCouponInfoEntity playCouponInfo) { + playCouponInfo.setId(id); + boolean success = playCouponInfoService.update(playCouponInfo); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + /** + * 删除优惠券信息 + */ + @ApiOperation(value = "删除优惠券", notes = "根据ID批量删除优惠券信息") + @ApiImplicitParam(name = "ids", value = "优惠券ID数组", required = true, paramType = "path", dataType = "String[]", example = "1,2,3") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + // @PreAuthorize("@customSs.hasPermission('shop:coupon:remove')") + @Log(title = "优惠券信息", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@PathVariable String[] ids) { + return R.ok(playCouponInfoService.deletePlayCouponInfoByIds(ids)); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/controller/PlayGiftInfoController.java --- +package com.starry.admin.modules.shop.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.modules.shop.module.entity.PlayGiftInfoEntity; +import com.starry.admin.modules.shop.service.IPlayGiftInfoService; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import javax.annotation.Resource; +import org.springframework.web.bind.annotation.*; + +/** + * 礼物Controller + * + * @author admin + * @since 2024-04-25 + */ +@Api(tags = "礼物管理", description = "礼物信息管理相关接口,包括查询、新增、修改和删除等操作") +@RestController +@RequestMapping("/play/giff") +public class PlayGiftInfoController { + @Resource + private IPlayGiftInfoService playGiftInfoService; + + /** + * 查询礼物列表 + */ + @ApiOperation(value = "查询礼物列表", notes = "分页查询礼物信息列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayGiftInfoEntity.class, responseContainer = "Page")}) + @GetMapping("/list") + public R list(@ApiParam(value = "查询条件") PlayGiftInfoEntity playGiftInfo) { + IPage list = playGiftInfoService.selectPlayGiftInfoByPage(playGiftInfo); + return R.ok(list); + } + + /** + * 获取礼物详细信息 + */ + @ApiOperation(value = "获取礼物详情", notes = "根据ID获取礼物详细信息") + @ApiImplicitParam(name = "id", value = "礼物ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = PlayGiftInfoEntity.class)}) + @GetMapping(value = "/{id}") + public R getInfo(@PathVariable("id") String id) { + return R.ok(playGiftInfoService.selectPlayGiftInfoById(id)); + } + + /** + * 新增礼物 + */ + @ApiOperation(value = "新增礼物", notes = "新增礼物信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "添加失败,包含详细错误信息")}) + @Log(title = "礼物", businessType = BusinessType.INSERT) + @PostMapping("/create") + public R create(@ApiParam(value = "礼物信息", required = true) @RequestBody PlayGiftInfoEntity playGiftInfo) { + boolean success = playGiftInfoService.create(playGiftInfo); + if (success) { + return R.ok(); + } + return R.error("添加失败"); + } + + /** + * 修改礼物 + */ + @ApiOperation(value = "修改礼物", notes = "修改礼物信息") + @ApiImplicitParam(name = "id", value = "礼物ID", required = true, paramType = "path", dataType = "String", example = "1") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败,包含详细错误信息")}) + @Log(title = "礼物", businessType = BusinessType.UPDATE) + @PostMapping(value = "/update/{id}") + public R update(@PathVariable String id, + @ApiParam(value = "礼物信息", required = true) @RequestBody PlayGiftInfoEntity playGiftInfo) { + playGiftInfo.setId(id); + boolean success = playGiftInfoService.update(playGiftInfo); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + /** + * 删除礼物 + */ + @ApiOperation(value = "删除礼物", notes = "根据ID批量删除礼物信息") + @ApiImplicitParam(name = "ids", value = "礼物ID数组", required = true, paramType = "path", dataType = "String[]", example = "1,2,3") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @Log(title = "礼物", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@PathVariable String[] ids) { + return R.ok(playGiftInfoService.deletePlayGiftInfoByIds(ids)); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/controller/PlayShopArticleInfoController.java --- +package com.starry.admin.modules.shop.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.shop.module.entity.PlayShopArticleInfoEntity; +import com.starry.admin.modules.shop.module.vo.PlayShopArticleInfoAddVo; +import com.starry.admin.modules.shop.module.vo.PlayShopArticleInfoQueryVo; +import com.starry.admin.modules.shop.module.vo.PlayShopArticleInfoUpdateVo; +import com.starry.admin.modules.shop.service.IPlayShopArticleInfoService; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import com.starry.common.utils.ConvertUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.util.Date; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 店铺文章信息Controller + * + * @author admin + * @since 2024-06-05 + */ +@Api(tags = "店铺文章管理", description = "店铺文章信息管理相关接口,包括查询、新增、修改和删除等操作") +@RestController +@RequestMapping("/shop/articleInfo") +public class PlayShopArticleInfoController { + + @Resource + private IPlayShopArticleInfoService playShopArticleInfoService; + + /** + * 查询店铺文章信息列表 + */ + @ApiOperation(value = "分页查询文章列表", notes = "分页查询店铺文章信息列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayShopArticleInfoEntity.class, responseContainer = "Page")}) + // @PreAuthorize("@customSs.hasPermission('shop:articleInfo:list')") + @PostMapping("/listByPage") + public R listByPage( + @ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayShopArticleInfoQueryVo vo) { + IPage list = playShopArticleInfoService.selectByPage(vo); + return R.ok(list); + } + + /** + * 新增店铺文章信息 + */ + @ApiOperation(value = "新增或修改文章", notes = "新增或修改店铺文章信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "添加失败,包含详细错误信息")}) + // @PreAuthorize("@customSs.hasPermission('shop:articleInfo:add')") + @PostMapping("/create") + public R create(@ApiParam(value = "文章信息", required = true) @Validated @RequestBody PlayShopArticleInfoAddVo vo) { + PlayShopArticleInfoEntity entity = ConvertUtil.entityToVo(vo, PlayShopArticleInfoEntity.class); + PlayShopArticleInfoEntity entity1 = playShopArticleInfoService.selectByType(entity.getArticleType()); + if (entity.getId() == null) { + if (entity1 != null) { + throw new CustomException("同类型的文章只能存在一个"); + } + playShopArticleInfoService.create(entity); + } else { + if (entity1 != null && !entity1.getId().equals(entity.getId())) { + throw new CustomException("同类型的文章只能存在一个"); + } + entity.setUpdatedTime(new Date()); + playShopArticleInfoService.update(entity); + } + + return R.ok(); + } + + /** + * 修改店铺文章信息 + */ + @ApiOperation(value = "更新文章状态", notes = "修改店铺文章状态") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败,包含详细错误信息")}) + // @PreAuthorize("@customSs.hasPermission('shop:articleInfo:update')") + @PostMapping("/handleUpdateState") + public R listByPage( + @ApiParam(value = "更新信息", required = true) @Validated @RequestBody PlayShopArticleInfoUpdateVo vo) { + PlayShopArticleInfoEntity entity = ConvertUtil.entityToVo(vo, PlayShopArticleInfoEntity.class); + playShopArticleInfoService.update(entity); + return R.ok(); + } + + /** + * 删除店铺文章信息 + */ + @ApiOperation(value = "删除文章", notes = "根据ID批量删除店铺文章信息") + @ApiImplicitParam(name = "ids", value = "文章ID数组", required = true, paramType = "path", dataType = "String[]", example = "1,2,3") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + // @PreAuthorize("@customSs.hasPermission('shop:articleInfo:delete')") + @Log(title = "店铺文章信息", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@PathVariable String[] ids) { + return R.ok(playShopArticleInfoService.deleteByIds(ids)); + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/controller/PlayShopCarouselInfoController.java --- +package com.starry.admin.modules.shop.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.common.oss.service.IOssFileService; +import com.starry.admin.modules.shop.module.entity.PlayShopCarouselInfoEntity; +import com.starry.admin.modules.shop.module.vo.PlayShopCarouselInfoAddVo; +import com.starry.admin.modules.shop.module.vo.PlayShopCarouselInfoQueryVo; +import com.starry.admin.modules.shop.module.vo.PlayShopCarouselInfoUpdateStateVo; +import com.starry.admin.modules.shop.service.IPlayShopCarouselInfoService; +import com.starry.admin.utils.SecurityUtils; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import com.starry.common.utils.ConvertUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.io.IOException; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +/** + * 店铺首页轮播Controller + * + * @author admin + * @since 2024-06-05 + */ +@Api(tags = "店铺轮播图管理", description = "店铺首页轮播图信息管理相关接口,包括查询、新增、修改和删除等操作") +@RestController +@RequestMapping("/shop/carousel") +public class PlayShopCarouselInfoController { + @Resource + private IPlayShopCarouselInfoService playCarouselInfoService; + + @Resource + private IOssFileService ossFileService; + + /** + * 查询店铺首页轮播列表 + */ + @ApiOperation(value = "分页查询轮播图列表", notes = "分页查询店铺首页轮播图信息列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayShopCarouselInfoEntity.class, responseContainer = "Page")}) + // @PreAuthorize("@customSs.hasPermission('shop:carousel:list')") + @PostMapping("/listByPage") + public R listByPage( + @ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayShopCarouselInfoQueryVo vo) { + IPage list = playCarouselInfoService.selectByPage(vo); + return R.ok(list); + } + + @ApiOperation(value = "上传轮播图文件", notes = "上传店铺首页轮播图文件") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功,返回文件地址"), + @ApiResponse(code = 500, message = "上传失败,包含详细错误信息")}) + // @PreAuthorize("@customSs.hasPermission('shop:carousel:add')") + @PostMapping("/uploadFile") + public R uploadFile(@ApiParam(value = "轮播图文件", required = true) @RequestParam("file") MultipartFile file) + throws IOException { + String fileAddress = ossFileService.upload(file.getInputStream(), SecurityUtils.getTenantId(), + file.getOriginalFilename()); + return R.ok(fileAddress); + } + + /** + * 新增页轮播列表 + */ + @ApiOperation(value = "新增轮播图", notes = "新增店铺首页轮播图信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "添加失败,包含详细错误信息")}) + // @PreAuthorize("@customSs.hasPermission('shop:carousel:add')") + @PostMapping("/create") + public R create(@ApiParam(value = "轮播图信息", required = true) @Validated @RequestBody PlayShopCarouselInfoAddVo vo) { + PlayShopCarouselInfoEntity entity = ConvertUtil.entityToVo(vo, PlayShopCarouselInfoEntity.class); + playCarouselInfoService.create(entity); + return R.ok(); + } + + /** + * 修改页轮播状态 + */ + @ApiOperation(value = "更新轮播图状态", notes = "修改店铺首页轮播图状态") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败,包含详细错误信息")}) + // @PreAuthorize("@customSs.hasPermission('shop:carousel:update')") + @PostMapping("/handleUpdateState") + public R listByPage( + @ApiParam(value = "更新信息", required = true) @Validated @RequestBody PlayShopCarouselInfoUpdateStateVo vo) { + PlayShopCarouselInfoEntity entity = ConvertUtil.entityToVo(vo, PlayShopCarouselInfoEntity.class); + playCarouselInfoService.update(entity); + return R.ok(); + } + + /** + * 删除店铺首页轮播 + */ + @ApiOperation(value = "删除轮播图", notes = "根据ID批量删除店铺首页轮播图信息") + @ApiImplicitParam(name = "ids", value = "轮播图ID数组", required = true, paramType = "path", dataType = "String[]", example = "1,2,3") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + // @PreAuthorize("@customSs.hasPermission('shop:carousel:delete')") + @Log(title = "店铺首页轮播", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@PathVariable String[] ids) { + return R.ok(playCarouselInfoService.deletePlayCarouselInfoByIds(ids)); + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/controller/ShopUiSettingController.java --- +package com.starry.admin.modules.shop.controller; + +import com.starry.admin.modules.shop.module.entity.ShopUiSettingEntity; +import com.starry.admin.modules.shop.service.IShopUiSettingService; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import javax.annotation.Resource; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 店铺设置Controller + * + * @author admin + * @since 2025-06-11 + */ +@Api(tags = "店铺UI设置", description = "店铺UI设置相关接口,包括查询和修改操作") +@RestController +@RequestMapping("/play/setting") +public class ShopUiSettingController { + @Resource + private IShopUiSettingService shopUiSettingService; + + /** + * 获取店铺设置详细信息 + */ + @ApiOperation(value = "获取店铺设置信息", notes = "获取店铺UI设置详细信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = ShopUiSettingEntity.class)}) + @GetMapping(value = "/info") + public R getInfo() { + return R.ok(shopUiSettingService.selectShopUiSettingInfo()); + } + + /** + * 修改店铺设置 + */ + @ApiOperation(value = "修改店铺设置", notes = "修改店铺UI设置信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败,包含详细错误信息")}) + @PostMapping(value = "/update") + public R update(@ApiParam(value = "店铺UI设置信息", required = true) @RequestBody ShopUiSettingEntity shopUiSetting) { + boolean success = shopUiSettingService.update(shopUiSetting); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/mapper/PlayClerkGiftInfoMapper.java --- +package com.starry.admin.modules.shop.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.starry.admin.modules.shop.module.entity.PlayClerkGiftInfoEntity; + +/** + * 店员和礼物关系Mapper接口 + * + * @author admin + * @since 2024-05-25 + */ +public interface PlayClerkGiftInfoMapper extends BaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/mapper/PlayCommodityAndLevelInfoMapper.java --- +package com.starry.admin.modules.shop.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.starry.admin.modules.shop.module.entity.PlayCommodityAndLevelInfoEntity; + +/** + * 服务项目和店员等级数据Mapper接口 + * + * @author admin + * @since 2024-08-16 + */ +public interface PlayCommodityAndLevelInfoMapper extends BaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/mapper/PlayCommodityInfoMapper.java --- +package com.starry.admin.modules.shop.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.starry.admin.modules.shop.module.entity.PlayCommodityInfoEntity; +import com.starry.admin.modules.shop.module.vo.PlayCommodityInfoVo; +import org.apache.ibatis.annotations.Select; + +/** + * 服务项目Mapper接口 + * + * @author admin + * @since 2024-03-31 + */ +public interface PlayCommodityInfoMapper extends MPJBaseMapper { + + // /** + // * 查询服务项目信息 + // * + // * @param id UUID + // * @return 项目信息 + // */ + // @Select("select t.id as commodityId,t.price as commodityPrice,t.item_name as + // serviceDuration,t1.item_name as commodityName from play_commodity_info t left + // join play_commodity_info t1 on t.p_id = t1.id where t.id = #{id} limit 1") + // PlayCommodityInfoVo queryCommodityInfo(String id); + + /** + * 查询服务项目信息 + * + * @param id + * UUID + * @return 项目信息 + */ + @Select("select t.id as commodityId,t3.price as commodityPrice,t.item_name as serviceDuration,t1.item_name as commodityName from play_commodity_info t left join play_commodity_info t1 on t.p_id = t1.id left join play_commodity_and_level_info t3 ON t3.commodity_id = t.id where t3.price is not null and t.id = #{id} and t3.level_id = #{levelId} limit 1") + PlayCommodityInfoVo queryCommodityInfo(String id, String levelId); + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/mapper/PlayCouponDetailsMapper.java --- +package com.starry.admin.modules.shop.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.starry.admin.modules.shop.module.entity.PlayCouponDetailsEntity; + +/** + * 优惠券详情Mapper接口 + * + * @author admin + * @since 2024-07-04 + */ +public interface PlayCouponDetailsMapper extends MPJBaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/mapper/PlayCouponInfoMapper.java --- +package com.starry.admin.modules.shop.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.starry.admin.modules.shop.module.entity.PlayCouponInfoEntity; + +/** + * 优惠券信息Mapper接口 + * + * @author admin + * @since 2024-07-04 + */ +public interface PlayCouponInfoMapper extends MPJBaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/mapper/PlayGiftInfoMapper.java --- +package com.starry.admin.modules.shop.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.starry.admin.modules.shop.module.entity.PlayGiftInfoEntity; + +/** + * 礼物Mapper接口 + * + * @author admin + * @since 2024-04-25 + */ +public interface PlayGiftInfoMapper extends MPJBaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/mapper/PlayShopArticleInfoMapper.java --- +package com.starry.admin.modules.shop.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.starry.admin.modules.shop.module.entity.PlayShopArticleInfoEntity; + +/** + * 店铺文章信息Mapper接口 + * + * @author admin + * @since 2024-06-05 + */ +public interface PlayShopArticleInfoMapper extends BaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/mapper/PlayShopCarouselInfoMapper.java --- +package com.starry.admin.modules.shop.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.starry.admin.modules.shop.module.entity.PlayShopCarouselInfoEntity; + +/** + * 店铺首页轮播Mapper接口 + * + * @author admin + * @since 2024-06-05 + */ +public interface PlayShopCarouselInfoMapper extends BaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/mapper/ShopUiSettingMapper.java --- +package com.starry.admin.modules.shop.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.starry.admin.modules.shop.module.entity.ShopUiSettingEntity; + +/** + * 店铺设置Mapper接口 + * + * @author admin + * @since 2025-06-11 + */ +public interface ShopUiSettingMapper extends BaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/module/constant/GiftConstant.java --- +package com.starry.admin.modules.shop.module.constant; + +/** + * 礼物常量 + * + * @author admin + * @since 2024/5/8 9:50 + **/ +public class GiftConstant { + + /** + * 礼物单词最大赠送数量 + * + * @since 2024/5/8 9:51 + **/ + public final static int MAXIMUM_SINGLE_GIFT_QUANTITY = 1000; + + /** + * 礼物单词最大赠送数量 + * + * @since 2024/5/8 9:51 + **/ + public final static int MINIMUM_SINGLE_GIFT_QUANTITY = 1; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/module/entity/PlayClerkGiftInfoEntity.java --- +package com.starry.admin.modules.shop.module.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.common.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 店员和礼物关系对象 play_clerk_gift_info + * + * @author admin + * @since 2024-05-25 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("play_clerk_gift_info") +public class PlayClerkGiftInfoEntity extends BaseEntity { + + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 店员ID + */ + private String clerkId; + + /** + * 礼物ID + */ + private String giffId; + + /** + * 礼物数量 + */ + private Long giffNumber; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/module/entity/PlayCommodityAndLevelInfoEntity.java --- +package com.starry.admin.modules.shop.module.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.common.domain.BaseEntity; +import java.math.BigDecimal; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 服务项目和店员等级数据对象 play_commodity_and_level_info + * + * @author admin + * @since 2024-08-16 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("play_commodity_and_level_info") +public class PlayCommodityAndLevelInfoEntity extends BaseEntity { + + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 商品ID + */ + private String commodityId; + + /** + * 店员等级ID + */ + private String levelId; + + /** + * 服务单价 + */ + private BigDecimal price; + + /** + * 排序 + */ + private Long sort; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/module/entity/PlayCommodityInfoEntity.java --- +package com.starry.admin.modules.shop.module.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.common.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 服务项目对象 play_commodity_info + * + * @author admin + * @since 2024-03-31 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("play_commodity_info") +public class PlayCommodityInfoEntity extends BaseEntity { + + /** + * UUID + */ + private String id; + + /** + * Pid + **/ + private String pId; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 项目类型 + */ + private String itemType; + + /** + * 项目名称 + */ + private String itemName; + + /** + * 服务时长(文字描述信息,不参与订单计算) + */ + private String serviceDuration; + + /** + * 启用状态(0:停用,1:启用) + */ + private String enableStace; + + /** + * 排序 + **/ + private Integer sort; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/module/entity/PlayCouponDetailsEntity.java --- +package com.starry.admin.modules.shop.module.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.starry.common.domain.BaseEntity; +import java.time.LocalDateTime; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 优惠券详情对象 play_coupon_details + * + * @author admin + * @since 2024-07-04 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("play_coupon_details") +public class PlayCouponDetailsEntity extends BaseEntity { + + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 顾客ID + */ + private String customId; + + /** + * 顾客昵称 + */ + private String customNickname; + + /** + * 顾客等级ID + */ + private String customLevelId; + + /** + * 优惠券ID + */ + private String couponId; + + /** + * 获得渠道(1:自主领取;2:后台发放;3:退款返还;4:分享领取;5:抽奖获得) + */ + private String obtainingChannels; + + /** + * 优惠券使用状态(1:未使用;2:已使用;3:已回收) + */ + private String useState; + + /** + * + * /** 获得时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime obtainingTime; + + /** + * 使用时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime useTime; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/module/entity/PlayCouponInfoEntity.java --- +package com.starry.admin.modules.shop.module.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.starry.admin.common.conf.StringTypeHandler; +import com.starry.common.domain.BaseEntity; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 优惠券信息对象 play_coupon_info + * + * @author admin + * @since 2024-07-04 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName(value = "play_coupon_info", autoResultMap = true) +public class PlayCouponInfoEntity extends BaseEntity { + + /** + * UUID + */ + private String id; + + /** + * 优惠券名称 + **/ + private String couponName = "测试券"; + /** + * 租户ID + */ + private String tenantId; + + /** + * 有效期类型(0:永久有效;1:固定时间内有效;2:领取后几天内有效) + */ + private String validityPeriodType; + + /** + * 生效时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime productiveTime; + + /** + * 到期时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime expirationTime; + + /** + * 生效时长,validityPeriodType=2时有效 + **/ + private Integer effectiveDay; + + /** + * 使用优惠券最低消费金额 + **/ + private BigDecimal useMinAmount; + + /** + * 优惠类型(0:满减;1:折扣) + */ + private String discountType; + + /** + * 优惠内容,文字展示 + */ + private String discountContent; + + /** + * 折扣值 + */ + private BigDecimal discountAmount; + + /** + * 优惠金额是否由店铺承担(0:不是;1:是) + */ + private String attributionDiscounts; + + /** + * 下单类型(0:指定单,1:随机单。2:打赏单) + */ + @TableField(typeHandler = StringTypeHandler.class) + private List placeType; + + /** + * 店员范围(0:所有店员) + */ + private String clerkType; + + /** + * 优惠券总数 + */ + private Integer couponQuantity; + + /** + * 已发放数量 + */ + private Integer issuedQuantity; + + /** + * 剩余数量 + */ + private Integer remainingQuantity; + + /** + * 店员获得最大数量 + */ + private Integer clerkObtainedMaxQuantity; + + /** + * 领取条件类型(0:所有人可领取,1:指定条件领取) + */ + private String claimConditionType; + + /** + * 顾客等级选择状态(0:未选择,1:选择) + */ + private String customLevelCheckType; + + /** + * 店员等级 + */ + @TableField(typeHandler = StringTypeHandler.class) + private List customLevel; + + /** + * 用户关注公众号选择状态(0:未选择,1:选择) + */ + private String customFollowStatusCheckType; + + /** + * 顾客关注公众号状态(0:未关注,1:已关注) + */ + private String customFollowStatus; + + /** + * 顾客性别选择状态(0:未选择,1:选择) + */ + private String customSexCheckType; + /** + * 顾客性别(0:未知;1:男,2:女) + */ + @TableField(typeHandler = StringTypeHandler.class) + private List customSex; + + /** + * 仅限新用户领取(0:不是;1:是)(没有下过单的用户,下单后再退单也不算) + */ + private String newUser; + + /** + * 优惠券上架状态(0;下架;1:上架) + */ + private String couponOnLineState; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/module/entity/PlayGiftInfoEntity.java --- +package com.starry.admin.modules.shop.module.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.starry.common.domain.BaseEntity; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 礼物对象 play_gift_info + * + * @author admin + * @since 2024-04-25 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("play_gift_info") +public class PlayGiftInfoEntity extends BaseEntity { + + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 是否是历史礼物(0:不是,1:是) + */ + private String history; + + /** + * 礼物名称 + */ + private String name; + + /** + * 礼物类型(0:盲盒,1:普通礼物) + */ + private String type; + + /** + * 礼物图片地址 + */ + private String url; + + /** + * 单价 + */ + private BigDecimal price; + + /** + * 价格单位 + */ + private String unit; + + /** + * 状态(0:正常,1:下架) + */ + private String state; + + /** + * 上架时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime listingTime; + + /** + * 下架时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime delintingTime; + + /** + * 备注 + */ + private String remark; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/module/entity/PlayShopArticleInfoEntity.java --- +package com.starry.admin.modules.shop.module.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.common.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 店铺文章信息 + * + * @author admin + * @since 2024/7/18 11:00 + **/ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName(value = "play_shop_article_info", autoResultMap = true) +public class PlayShopArticleInfoEntity extends BaseEntity { + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 文章类型 + * + **/ + private String articleType; + + /** + * 文章标题 + * + **/ + private String articleTitle; + + /** + * 文章内容 + * + **/ + private String articleContent; + + /** + * 浏览量 + * + **/ + private Integer visitsNumber; + + /** + * 排序 + * + **/ + private Integer sort; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/module/entity/PlayShopCarouselInfoEntity.java --- +package com.starry.admin.modules.shop.module.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.starry.common.domain.BaseEntity; +import java.time.LocalDateTime; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 店铺首页轮播对象 play_carousel_info + * + * @author admin + * @since 2024-06-05 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("play_shop_carousel_info") +public class PlayShopCarouselInfoEntity extends BaseEntity { + + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 轮播图位置(0:首页) + */ + private String carouselIndex; + + /** + * 启用状态(0:未启用,1:已启用) + */ + private String enableState; + + /** + * 图片URL + */ + private String carouselUrl; + + /** + * 导航类型(0:无) + */ + private String navigationType; + + /** + * 排序 + */ + private Integer sort; + + /** + * 创建时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime addTime; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/module/entity/ShopUiSettingEntity.java --- +package com.starry.admin.modules.shop.module.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.common.domain.BaseEntity; +import java.util.Date; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 店铺设置对象 shop_ui_setting + * + * @author admin + * @since 2025-06-11 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("shop_ui_setting") +public class ShopUiSettingEntity extends BaseEntity { + + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 创建人的id + */ + private String createdBy; + + /** + * 创建时间 + */ + private Date createdTime; + + /** + * 修改人的id + */ + private String updatedBy; + + /** + * 修改时间 + */ + private Date updatedTime; + + /** + * 数据版本 + */ + private Long version; + + /** + * 配置内容 + */ + private String settingConfig; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/module/vo/PlayCommodityInfoAddVo.java --- +package com.starry.admin.modules.shop.module.vo; + +import javax.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 服务项目对象 play_commodity_info + * + * @author admin + * @since 2024-03-31 + */ +@Data +@EqualsAndHashCode(callSuper = false) +public class PlayCommodityInfoAddVo { + + /** + * 项目类型 + */ + @NotNull(message = "项目类型不能为空") + private String itemType; + + /** + * 项目名称 + */ + @NotNull(message = "项目名称不能为空") + private String itemName; + + /** + * 服务时长(文字描述信息,不参与订单计算) + */ + @NotNull(message = "服务时长不能为空") + private String serviceDuration; + + /** + * 服务单价 + */ + @NotNull(message = "单价不能为空") + private String price; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/module/vo/PlayCommodityInfoReturnVo.java --- +package com.starry.admin.modules.shop.module.vo; + +import lombok.Data; + +/** + * @author admin + * @since 2024/8/18 下午7:59 + **/ +@Data +public class PlayCommodityInfoReturnVo { + + /** + * UUID + */ + private String id; + + /** + * Pid + **/ + private String pId; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 项目类型 + */ + private String itemType; + + /** + * 项目名称 + */ + private String itemName; + + /** + * 服务时长(文字描述信息,不参与订单计算) + */ + private String serviceDuration; + + /** + * 启用状态(0:停用,1:启用) + */ + private String enableStace; + + /** + * 排序 + **/ + private Integer sort; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/module/vo/PlayCommodityInfoUpdateVo.java --- +package com.starry.admin.modules.shop.module.vo; + +import javax.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 服务项目对象 play_commodity_info + * + * @author admin + * @since 2024-03-31 + */ +@Data +@EqualsAndHashCode(callSuper = false) +public class PlayCommodityInfoUpdateVo { + + @NotNull(message = "ID不能为空") + private String id; + + /** + * 服务时长(文字描述信息,不参与订单计算) + */ + @NotNull(message = "服务时长不能为空") + private String serviceDuration; + + /** + * 服务单价 + */ + @NotNull(message = "单价不能为空") + private String price; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/module/vo/PlayCommodityInfoVo.java --- +package com.starry.admin.modules.shop.module.vo; + +import java.math.BigDecimal; +import lombok.Data; + +/** + * 商品信息查询返回对象 + * + * @author admin + * @since 2024/6/2 上午8:52 + **/ +@Data +public class PlayCommodityInfoVo { + + /** + * UUID + */ + private String commodityId; + + /** + * 单价 + */ + private BigDecimal commodityPrice; + + /** + * 名称 + */ + private String commodityName; + + /** + * 服务时长 + */ + private String serviceDuration; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/module/vo/PlayCouponDetailsQueryVo.java --- +package com.starry.admin.modules.shop.module.vo; + +import com.starry.common.domain.BasePageEntity; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 优惠券详情查询接口 + * + * @author admin + * @since 2024/7/4 16:53 + **/ +@EqualsAndHashCode(callSuper = true) +@Data +public class PlayCouponDetailsQueryVo extends BasePageEntity { + + /** + * 优惠券ID + **/ + private String couponId; + + /** + * 用户ID + **/ + private String customId; + + /** + * 获得渠道(1:自主领取;2:后台发放;3:退款返还;4:分享领取;5:抽奖获得) + */ + private String obtainingChannels; + + /** + * 使用状态(1:未使用;2:已使用;3:已回收) + */ + private String useState; + + /** + * 使用时间 + */ + private List useTime; + + /** + * 获得时间 + */ + private List obtainingTime; + + /** + * 用户等级 + */ + private String customLevelId; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/module/vo/PlayCouponDetailsReturnVo.java --- +package com.starry.admin.modules.shop.module.vo; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.starry.admin.common.conf.StringTypeHandler; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 优惠券详细信息返回列表 + * + * @author admin + * @since 2024/7/8 下午11:29 + **/ +@Data +public class PlayCouponDetailsReturnVo { + + /** + * UUID + */ + private String id; + + /** + * 顾客ID + */ + private String customId; + + /** + * 顾客昵称 + */ + private String customNickname; + + /** + * 顾客等级ID + */ + private String customLevelId; + + /** + * 优惠券ID + */ + private String couponId; + + /** + * 获得渠道(1:自主领取;2:后台发放;3:退款返还;4:分享领取;5:抽奖获得) + */ + private String obtainingChannels; + + /** + * 优惠券使用状态(1:未使用;2:已使用;3:已回收) + */ + private String useState; + + /** + * 生效时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime productiveTime; + + /** + * 到期时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime expirationTime; + + /** + * 获得时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime obtainingTime; + + /** + * 使用时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime useTime; + + /** + * 优惠券名称 + **/ + private String couponName; + + /** + * 有效期类型(0:永久有效;1:固定时间内有效;2:领取后几天内有效) + */ + private String validityPeriodType; + + /** + * 生效时长,validityPeriodType=2时有效 + **/ + private Integer effectiveDay; + + /** + * 使用优惠券最低消费金额 + **/ + private BigDecimal useMinAmount; + + /** + * 优惠类型(0:满减;1:折扣) + */ + private String discountType; + + /** + * 优惠内容,文字展示 + */ + private String discountContent; + + /** + * 折扣值 + */ + private BigDecimal discountAmount; + + /** + * 优惠金额是否由店铺承担(0:不是;1:是) + */ + private String attributionDiscounts; + + /** + * 下单类型(0:指定单,1:随机单。2:打赏单) + */ + @TableField(typeHandler = StringTypeHandler.class) + private List placeType; + + /** + * 店员范围(0:所有店员) + */ + private String clerkType; + + /** + * 优惠券总数 + */ + private Integer couponQuantity; + + /** + * 已发放数量 + */ + private Integer issuedQuantity; + + /** + * 剩余数量 + */ + private Integer remainingQuantity; + + /** + * 店员获得最大数量 + */ + private Integer clerkObtainedMaxQuantity; + + /** + * 领取条件类型(0:所有人可领取,1:指定条件领取) + */ + private String claimConditionType; + + /** + * 顾客等级选择状态(0:未选择,1:选择) + */ + private String customLevelCheckType; + + /** + * 店员等级 + */ + @TableField(typeHandler = StringTypeHandler.class) + private List customLevel; + + /** + * 用户关注公众号选择状态(0:未选择,1:选择) + */ + private String customFollowStatusCheckType; + + /** + * 顾客关注公众号状态(0:未关注,1:已关注) + */ + private String customFollowStatus; + + /** + * 顾客性别选择状态(0:未选择,1:选择) + */ + private String customSexCheckType; + /** + * 顾客性别(0:未知;1:男,2:女) + */ + @TableField(typeHandler = StringTypeHandler.class) + private List customSex; + + /** + * 仅限新用户领取(0:不是;1:是)(没有下过单的用户,下单后再退单也不算) + */ + private String newUser; + + /** + * 优惠券上架状态(0;下架;1:上架) + */ + private String couponOnLineState; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/module/vo/PlayCouponDetailsUpdateUseStateVo.java --- +package com.starry.admin.modules.shop.module.vo; + +import java.util.List; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; +import lombok.Data; + +/** + * 更新优惠券使用状态 + * + * @author admin + * @since 2024/7/4 16:53 + **/ +@Data +public class PlayCouponDetailsUpdateUseStateVo { + + /** + * 优惠券ID + **/ + @NotNull(message = "优惠券ID不能为空") + @Size(min = 1, message = "优惠券ID不能为空") + private List couponIds; + + /** + * 优惠券使用状态(1:未使用;2:已使用;3:已回收) + */ + @NotNull(message = "优惠券使用状态不能为空") + @Pattern(regexp = "[0|1]", message = "店员范围只能为0或者1") + private String useState; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/module/vo/PlayCouponInfoAddVo.java --- +package com.starry.admin.modules.shop.module.vo; + +import java.math.BigDecimal; +import java.util.List; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; +import lombok.Data; + +/** + * 优惠券信息新增实体 + * + * @author admin + * @since 2024/7/4 15:26 + **/ +@Data +public class PlayCouponInfoAddVo { + + /** + * 优惠券名称 + */ + @NotNull(message = "优惠券名称不能为空") + private String couponName; + + /** + * 有效期类型(0:永久有效;1:固定时间内有效;2:领取后几天内有效) + */ + @NotNull(message = "有效期类型不能为空") + @Pattern(regexp = "[012]", message = "有效期类型只能为0或1或2") + private String validityPeriodType; + + /** + * 生效时间 + */ + private List productiveTime; + + /** + * 生效时长,validityPeriodType=2时有效 + **/ + private Integer effectiveDay; + + /** + * 使用优惠券最近消费金额 + **/ + @NotNull(message = "使用优惠券最近消费金额不能为空") + private BigDecimal useMinAmount = BigDecimal.ZERO; + + /** + * 优惠类型(0:满减;1:折扣) + */ + @NotNull(message = "优惠类型不能为空") + @Pattern(regexp = "[01]", message = "优惠类型只能为0或1") + private String discountType; + + /** + * 优惠内容,文字展示 + */ + private String discountContent; + + /** + * 折扣值 + */ + @NotNull(message = "优惠金额不能为空") + private BigDecimal discountAmount; + + /** + * 优惠金额是否由店铺承担(0:不是;1:是) + */ + @NotNull(message = "优惠金额是否由店铺承担不能为空") + @Pattern(regexp = "[01]", message = "优惠金额是否由店铺承担只能为0或1") + private String attributionDiscounts; + + /** + * 下单类型(0:指定单,1:随机单。2:打赏单) + */ + @NotNull(message = "订单类型不能为空") + @Size(min = 1, message = "下单类型不能为空") + private List placeType; + + /** + * 店员范围(0:所有店员) + */ + @NotNull(message = "店员范围不能为空") + @Pattern(regexp = "[0]", message = "店员范围只能为0") + private String clerkType; + + /** + * 优惠券数量限制(0:不限制,1:限制) + */ + @NotNull(message = "优惠券总数不能为空") + @Pattern(regexp = "[01]", message = "优惠券数量限制只能为0或1") + private String couponQuantityType; + /** + * 优惠券总数(-1表示不限制数量) + */ + @NotNull(message = "优惠券总数不能为空") + private Integer couponQuantity; + + /** + * 已发放数量 + */ + private Integer issuedQuantity; + + /** + * 剩余数量 + */ + private Integer remainingQuantity; + + /** + * 店员获得最大数量是否限制 + */ + @NotNull(message = "店员获得最大数量是否限制不能为空") + @Pattern(regexp = "[01]", message = "店员获得最大数量是否限制只能为0或1") + private String clerkObtainedMaxQuantityType; + + /** + * 店员获得最大数量 + */ + @NotNull(message = " 店员获得最大数量不能为空") + private Integer clerkObtainedMaxQuantity; + + /** + * 领取条件类型(0:所有人可领取,1:指定条件领取) + */ + @NotNull(message = "领取条件类型不能为空") + @Pattern(regexp = "[0|1]", message = "店员范围只能为0或者1") + private String claimConditionType; + + /** + * 顾客等级选择状态(0:未选择,1:选择) + */ + private String customLevelCheckType; + + /** + * 店员等级 + */ + private List customLevel; + + /** + * 用户关注公众号选择状态(0:未选择,1:选择) + */ + private String customFollowStatusCheckType; + + /** + * 顾客关注公众号状态(0:未关注,1:已关注) + */ + private String customFollowStatus; + + /** + * 顾客性别关注状态(0:未选择,1:选择) + */ + private String customSexCheckType; + /** + * 顾客性别(0:未知;1:男,2:女) + */ + private List customSex; + + /** + * 仅限新用户领取选择状态(0:未选择,1:已选择) + */ + private String isNewUserCheckType; + + /** + * 仅限新用户领取(0:不是;1:是)(没有下过单的用户,下单后再退单也不算) + */ + private String newUser; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/module/vo/PlayCouponInfoOnLineStateUpdateVo.java --- +package com.starry.admin.modules.shop.module.vo; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; +import lombok.Data; + +/** + * 优惠券信息上架信息查询 + * + * @author admin + * @since 2024/7/4 15:26 + **/ +@Data +public class PlayCouponInfoOnLineStateUpdateVo { + + /** + * 优惠券ID + */ + @NotNull(message = "优惠券ID不能为空") + private String id; + + /** + * 上下架状态不能为空 + */ + @NotNull(message = "上下架状态不能为空不能为空") + @Pattern(regexp = "[0|1]", message = "上下架状态不能必须为0或1") + private String couponOnLineState; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/module/vo/PlayCouponInfoQueryVo.java --- +package com.starry.admin.modules.shop.module.vo; + +import com.starry.common.domain.BasePageEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 优惠券信息查询实体 + * + * @author admin + * @since 2024/7/4 15:26 + **/ +@EqualsAndHashCode(callSuper = true) +@Data +public class PlayCouponInfoQueryVo extends BasePageEntity { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/module/vo/PlayCouponInfoReturnVo.java --- +package com.starry.admin.modules.shop.module.vo; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.starry.admin.common.conf.StringTypeHandler; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 优惠券信息查询返回 + * + * @author admin + * @since 2024/7/4 15:26 + **/ +@Data +public class PlayCouponInfoReturnVo { + + /** + * UUID + */ + private String id; + + /** + * 优惠券名称 + **/ + private String couponName; + + /** + * 有效期类型(0:永久有效;1:固定时间内有效;2:领取后几天内有效) + */ + private String validityPeriodType; + + /** + * 生效时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private LocalDateTime productiveTime; + + /** + * 到期时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private LocalDateTime expirationTime; + + /** + * 生效时长,validityPeriodType=2时有效 + **/ + private Integer effectiveDay; + + /** + * 使用优惠券最近消费金额 + **/ + private BigDecimal useMinAmount; + + /** + * 优惠类型(0:满减;1:折扣) + */ + private String discountType; + + /** + * 优惠内容,文字展示 + */ + private String discountContent; + + /** + * 折扣值 + */ + private BigDecimal discountAmount; + + /** + * 优惠金额是否由店铺承担(0:不是;1:是) + */ + private String attributionDiscounts; + + /** + * 下单类型(0:指定单,1:随机单。2:打赏单) + */ + @TableField(typeHandler = StringTypeHandler.class) + private List placeType; + + /** + * 店员范围(0:所有店员) + */ + private String clerkType; + + /** + * 优惠券总数 + */ + private Integer couponQuantity; + + /** + * 已发放数量 + */ + private Integer issuedQuantity; + + /** + * 剩余数量 + */ + private Integer remainingQuantity; + + /** + * 店员获得最大数量 + */ + private Integer clerkObtainedMaxQuantity; + + /** + * 领取条件类型(0:所有人可领取,1:指定条件领取) + */ + private String claimConditionType; + + /** + * 顾客等级选择状态(0:未选择,1:选择) + */ + private String customLevelCheckType; + + /** + * 店员等级 + */ + @TableField(typeHandler = StringTypeHandler.class) + private List customLevel; + + /** + * 用户关注公众号选择状态(0:未选择,1:选择) + */ + private String customFollowStatusCheckType; + + /** + * 顾客关注公众号状态(0:未关注,1:已关注) + */ + private String customFollowStatus; + + /** + * 顾客性别选择状态(0:未选择,1:选择) + */ + private String customSexCheckType; + /** + * 顾客性别(0:未知;1:男,2:女) + */ + @TableField(typeHandler = StringTypeHandler.class) + private List customSex; + + /** + * 仅限新用户领取(0:不是;1:是)(没有下过单的用户,下单后再退单也不算) + */ + private String newUser; + + /** + * 优惠券上架状态(0;下架;1:上架) + */ + private String couponOnLineState; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/module/vo/PlayCouponInfoSendVo.java --- +package com.starry.admin.modules.shop.module.vo; + +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import lombok.Data; + +/** + * 优惠券信息上架信息查询 + * + * @author admin + * @since 2024/7/4 15:26 + **/ +@Data +public class PlayCouponInfoSendVo { + + /** + * 优惠券ID + */ + @NotNull(message = "优惠券ID不能为空") + private String id; + + /** + * 用户ID + */ + @NotNull(message = "用户ID不能为空") + private String customId; + + /** + * 优惠券数量不能为空 + */ + @Max(value = 1, message = "优惠券数量必须小于1") + @Min(value = 1, message = "优惠券数量必须大于1") + private Integer sendNumber; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/module/vo/PlayShopArticleInfoAddVo.java --- +package com.starry.admin.modules.shop.module.vo; + +import javax.validation.constraints.NotNull; +import lombok.Data; + +/** + * 店铺文章信息新增 + * + * @author admin + * @since 2024/6/5 上午10:36 + **/ +@Data +public class PlayShopArticleInfoAddVo { + + private String id; + /** + * 文章类型 + **/ + @NotNull(message = "文章类型不能为空") + private String articleType; + + /** + * 文章标题 + **/ + @NotNull(message = "文章标题不能为空") + private String articleTitle; + + /** + * 文章内容 + **/ + @NotNull(message = "文章内容不能为空") + private String articleContent; + + /** + * 浏览量 + **/ + private Integer visitsNumber = 0; + + /** + * 排序 + */ + private Integer sort = 0; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/module/vo/PlayShopArticleInfoQueryVo.java --- +package com.starry.admin.modules.shop.module.vo; + +import com.starry.common.domain.BasePageEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 店铺文章查询对象 + * + * @author admin + * @since 2024/6/5 上午10:36 + **/ +@EqualsAndHashCode(callSuper = true) +@Data +public class PlayShopArticleInfoQueryVo extends BasePageEntity { + /** + * 文章ID + **/ + private String id; + + /** + * 文章类型 + */ + private String articleType; + + /** + * 文章标题 + */ + private String articleTitle; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/module/vo/PlayShopArticleInfoUpdateVo.java --- +package com.starry.admin.modules.shop.module.vo; + +import javax.validation.constraints.NotNull; +import lombok.Data; + +/** + * 店铺文章修改实体 + * + * @author admin + * @since 2024/6/5 上午10:36 + **/ +@Data +public class PlayShopArticleInfoUpdateVo { + + @NotNull(message = "ID不能为空") + private String id; + + /** + * 文章类型 + * + **/ + private String articleType; + + /** + * 文章标题 + * + **/ + private String articleTitle; + + /** + * 文章内容 + * + **/ + private String articleContent; + + /** + * 浏览量 + * + **/ + private Integer visitsNumber; + + /** + * 排序 + * + **/ + private Integer sort; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/module/vo/PlayShopCarouselInfoAddVo.java --- +package com.starry.admin.modules.shop.module.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import java.time.LocalDateTime; +import javax.validation.constraints.NotNull; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * @author admin + * @since 2024/6/5 上午10:36 + **/ +@Data +public class PlayShopCarouselInfoAddVo { + + /** + * 轮播图位置(0:首页) + */ + @NotNull(message = "轮播图位置不能为空") + private String carouselIndex; + + /** + * 启用状态(0:未启用,1:已启用) + */ + @NotNull(message = "启用状态不能为空") + private String enableState; + + /** + * 图片URL + */ + @NotNull(message = "图片URL不能为空") + private String carouselUrl; + + /** + * 排序 + */ + private Integer sort; + + /** + * 创建时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime addTime = LocalDateTime.now(); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/module/vo/PlayShopCarouselInfoQueryVo.java --- +package com.starry.admin.modules.shop.module.vo; + +import com.starry.common.domain.BasePageEntity; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @author admin + * @since 2024/6/5 上午10:36 + **/ +@EqualsAndHashCode(callSuper = true) +@Data +public class PlayShopCarouselInfoQueryVo extends BasePageEntity { + + /** + * 轮播图位置(0:首页) + */ + private String carouselIndex; + + /** + * 启用状态(0:未启用,1:已启用) + */ + private String enableState; + + /** + * 创建时间 + */ + private List addTime; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/module/vo/PlayShopCarouselInfoReturnVo.java --- +package com.starry.admin.modules.shop.module.vo; + +import com.starry.common.domain.BasePageEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @author admin + * @since 2024/6/5 上午10:36 + **/ +@EqualsAndHashCode(callSuper = true) +@Data +public class PlayShopCarouselInfoReturnVo extends BasePageEntity { +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/module/vo/PlayShopCarouselInfoUpdateStateVo.java --- +package com.starry.admin.modules.shop.module.vo; + +import javax.validation.constraints.NotNull; +import lombok.Data; + +/** + * @author admin + * @since 2024/6/5 上午10:36 + **/ +@Data +public class PlayShopCarouselInfoUpdateStateVo { + + @NotNull(message = "ID不能为空") + private String id; + + /** + * 启用状态(0:未启用,1:已启用) + */ + @NotNull(message = "enableState不能为空") + private String enableState; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/service/IPlayClerkGiftInfoService.java --- +package com.starry.admin.modules.shop.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.shop.module.entity.PlayClerkGiftInfoEntity; +import java.util.List; + +/** + * 店员和礼物关系Service接口 + * + * @author admin + * @since 2024-05-25 + */ +public interface IPlayClerkGiftInfoService extends IService { + + /** + * 根据顾客ID和礼物ID,查询当前礼物活点亮情况 + * + * @param giftId + * 礼物ID + * @param clerkId + * 店员ID + * @return 物活点亮情况 + */ + PlayClerkGiftInfoEntity selectByGiftIdAndClerkId(String giftId, String clerkId); + + /** + * 根据店员ID查询店员活动礼物列表 + * + * @param clerkId + * 店员ID + * @return 店员活动礼物列表 + */ + + List selectBtyClerkId(String clerkId); + + /** + * 查询店员和礼物关系 + * + * @param id + * 店员和礼物关系主键 + * @return 店员和礼物关系 + */ + PlayClerkGiftInfoEntity selectPlayClerkGiftInfoById(String id); + + /** + * 查询店员和礼物关系列表 + * + * @param playClerkGiftInfo + * 店员和礼物关系 + * @return 店员和礼物关系集合 + */ + IPage selectPlayClerkGiftInfoByPage(PlayClerkGiftInfoEntity playClerkGiftInfo); + + /** + * 新增店员和礼物关系 + * + * @param playClerkGiftInfo + * 店员和礼物关系 + * @return 结果 + */ + boolean create(PlayClerkGiftInfoEntity playClerkGiftInfo); + + /** + * 修改店员和礼物关系 + * + * @param playClerkGiftInfo + * 店员和礼物关系 + * @return 结果 + */ + boolean update(PlayClerkGiftInfoEntity playClerkGiftInfo); + + /** + * 批量删除店员和礼物关系 + * + * @param ids + * 需要删除的店员和礼物关系主键集合 + * @return 结果 + */ + int deletePlayClerkGiftInfoByIds(String[] ids); + + /** + * 删除店员和礼物关系信息 + * + * @param id + * 店员和礼物关系主键 + * @return 结果 + */ + int deletePlayClerkGiftInfoById(String id); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/service/IPlayCommodityAndLevelInfoService.java --- +package com.starry.admin.modules.shop.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.shop.module.entity.PlayCommodityAndLevelInfoEntity; +import java.util.List; + +/** + * 服务项目和店员等级数据Service接口 + * + * @author admin + * @since 2024-08-16 + */ +public interface IPlayCommodityAndLevelInfoService extends IService { + + PlayCommodityAndLevelInfoEntity queryById(String commodityId, String levelId); + /** + * 查询服务项目和店员等级数据 + * + * @return 服务项目和店员等级数据 + */ + List selectAll(); + + /** + * 查询服务项目和店员等级数据 + * + * @param id + * 服务项目和店员等级数据主键 + * @return 服务项目和店员等级数据 + */ + PlayCommodityAndLevelInfoEntity selectPlayCommodityAndLevelInfoById(String id); + + /** + * 查询服务项目和店员等级数据列表 + * + * @param playCommodityAndLevelInfo + * 服务项目和店员等级数据 + * @return 服务项目和店员等级数据集合 + */ + IPage selectPlayCommodityAndLevelInfoByPage( + PlayCommodityAndLevelInfoEntity playCommodityAndLevelInfo); + + /** + * 新增服务项目和店员等级数据 + * + * @param playCommodityAndLevelInfo + * 服务项目和店员等级数据 + * @return 结果 + */ + boolean create(PlayCommodityAndLevelInfoEntity playCommodityAndLevelInfo); + + /** + * 修改服务项目和店员等级数据 + * + * @param playCommodityAndLevelInfo + * 服务项目和店员等级数据 + * @return 结果 + */ + boolean update(PlayCommodityAndLevelInfoEntity playCommodityAndLevelInfo); + + /** + * 批量删除服务项目和店员等级数据 + * + * @param ids + * 需要删除的服务项目和店员等级数据主键集合 + * @return 结果 + */ + int deletePlayCommodityAndLevelInfoByIds(String[] ids); + + /** + * 删除服务项目和店员等级数据信息 + * + * @param id + * 服务项目和店员等级数据主键 + * @return 结果 + */ + int deletePlayCommodityAndLevelInfoById(String id); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/service/IPlayCommodityInfoService.java --- +package com.starry.admin.modules.shop.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.shop.module.entity.PlayCommodityInfoEntity; +import com.starry.admin.modules.shop.module.vo.PlayCommodityInfoVo; +import com.starry.admin.modules.weichat.entity.PlayCommodityReturnVo; +import java.util.List; + +/** + * 服务项目Service接口 + * + * @author admin + * @since 2024-03-31 + */ +public interface IPlayCommodityInfoService extends IService { + + /** + * * 新增租户时 * 初始化租户服务项目 + * + * @param tenantId + * 租户ID + */ + void initPlayCommodityInfo(String tenantId); + + /** + * 查询服务项目 + * + * @param id + * 服务项目ID + * @param levelId + * 店员等级ID + * @return PlayCommodityInfoVo + * @author admin + **/ + PlayCommodityInfoVo queryCommodityInfo(String id, String levelId); + + // /** + // * 查询服务项目 + // * + // * @param id UUID + // * @return 服务项目 + // */ + // PlayCommodityInfoVo queryCommodityInfo(String id); + + /** + * 查询服务项目 + * + * @param id + * 服务项目主键 + * @return 服务项目 + */ + PlayCommodityInfoEntity selectPlayCommodityInfoById(String id); + + /** + * 获取店铺服务项目 + * + * @return List + **/ + List selectTree(); + + /** + * 查询当前租户所有服务项目 + * + * @return 当前租户所有服务项目列表 + */ + List selectByType(); + + /** + * 查询当前租户所有服务项目列表 + * + * @return 当前租户所有服务项目列表 + */ + List selectAll(); + + /** + * 查询当前租户所有服务项目列表 + * + * @return 当前租户所有服务项目列表 + */ + List selectByPId(String pId); + + /** + * 查询服务项目列表 + * + * @param playCommodityInfo + * 服务项目 + * @return 服务项目集合 + */ + IPage selectPlayCommodityInfoByPage(PlayCommodityInfoEntity playCommodityInfo); + + /** + * 新增服务项目 + * + * @param playCommodityInfo + * 服务项目 + * @return 结果 + */ + boolean create(PlayCommodityInfoEntity playCommodityInfo); + + /** + * 修改服务项目 + * + * @param playCommodityInfo + * 服务项目 + * @return 结果 + */ + boolean update(PlayCommodityInfoEntity playCommodityInfo); + + /** + * 批量删除服务项目 + * + * @param ids + * 需要删除的服务项目主键集合 + * @return 结果 + */ + int deletePlayCommodityInfoByIds(String[] ids); + + /** + * 删除服务项目信息 + * + * @param id + * 服务项目主键 + * @return 结果 + */ + int deletePlayCommodityInfoById(String id); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/service/IPlayCouponDetailsService.java --- +package com.starry.admin.modules.shop.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.shop.module.entity.PlayCouponDetailsEntity; +import com.starry.admin.modules.shop.module.vo.PlayCouponDetailsQueryVo; +import com.starry.admin.modules.shop.module.vo.PlayCouponDetailsReturnVo; +import java.util.List; + +/** + * 优惠券详情Service接口 + * + * @author admin + * @since 2024-07-04 + */ +public interface IPlayCouponDetailsService extends IService { + /** + * 查询优惠券详情 + * + * @param id + * 优惠券详情主键 + * @return 优惠券详情 + */ + PlayCouponDetailsReturnVo selectPlayCouponDetailsById(String id); + + /** + * 查询优惠券详情列表 + * + * @param vo + * 优惠券详情 + * @return 优惠券详情集合 + */ + IPage selectByPage(PlayCouponDetailsQueryVo vo); + + /** + * 查询优惠券详情列表 + * + * @param playCouponDetails + * 优惠券详情 + * @return 优惠券详情集合 + */ + IPage selectPlayCouponDetailsByPage(PlayCouponDetailsEntity playCouponDetails); + + /** + * 根据顾客ID,查询当前顾客优惠券列表 + * + * @param customId + * 顾客ID + * @return List + * @author admin + * @since 2024/7/5 11:37 + **/ + List selectByCustomId(String customId); + + /** + * 新建优惠券使用详情 + * + * @param customId + * 用户ID + * @param customNickName + * 用户昵称 + * @param customLevel + * 用户等级 + * @param couponId + * 优惠券ID + * @param obtainingChannels + * 获得渠道(1:自主领取;2:后台发放;3:退款返还;4:分享领取;5:抽奖获得) + * @param useState + * 优惠券使用状态(1:未使用;2:已使用;3:已回收) + * @author admin + * @since 2024/7/8 16:21 + **/ + void create(String customId, String customNickName, String customLevel, String couponId, String obtainingChannels, + String useState); + + /** + * 新增优惠券详情 + * + * @param playCouponDetails + * 优惠券详情 + * @return 结果 + */ + boolean create(PlayCouponDetailsEntity playCouponDetails); + + /** + * 修改优惠券详情 + * + * @param playCouponDetails + * 优惠券详情 + * @return 结果 + */ + boolean update(PlayCouponDetailsEntity playCouponDetails); + + /** + * 批量修改优惠券使用状态 优惠券使用状态(1:未使用;2:已使用;3:已回收) + * + * @param ids + * 需要删除的优惠券详情主键集合 + * @param useState + * 优惠券使用状态(1 : 未使用 ; 2 : 已使用 ; 3 : 已回收) + */ + void updateCouponUseStateByIds(List ids, String useState); + + /** + * 批量删除优惠券详情 + * + * @param ids + * 需要删除的优惠券详情主键集合 + * @return 结果 + */ + int deletePlayCouponDetailsByIds(String[] ids); + + /** + * 删除优惠券详情信息 + * + * @param id + * 优惠券详情主键 + * @return 结果 + */ + int deletePlayCouponDetailsById(String id); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/service/IPlayCouponInfoService.java --- +package com.starry.admin.modules.shop.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.custom.module.entity.PlayCustomUserInfoEntity; +import com.starry.admin.modules.shop.module.entity.PlayCouponInfoEntity; +import com.starry.admin.modules.shop.module.vo.PlayCouponInfoQueryVo; +import com.starry.admin.modules.shop.module.vo.PlayCouponInfoReturnVo; +import java.math.BigDecimal; +import java.util.List; + +/** + * 优惠券信息Service接口 + * + * @author admin + * @since 2024-07-04 + */ +public interface IPlayCouponInfoService extends IService { + + /** + * 获取优惠券不可用的原因 + * + * @param couponInfo + * 优惠券信息 + * @param placeType + * 下单类型 + * @param commodityId + * 商品ID + * @param commodityQuantity + * 商品数量 + * @param price + * 商品单价 + * @return 不可用原因 + */ + String getCouponReasonForUnavailableUse(PlayCouponInfoEntity couponInfo, String placeType, String commodityId, + Integer commodityQuantity, BigDecimal price); + + /** + * 获取优惠券不可领取的原因 + * + * @param entity + * 优惠券实体 + * @param customUserInfo + * 顾客实体 + * @return String + * @author admin + * @since 2024/7/8 14:44 + **/ + String getReasonForNotObtainingCoupons(PlayCouponInfoEntity entity, PlayCustomUserInfoEntity customUserInfo); + + /** + * 查询优惠券信息 + * + * @param id + * 优惠券信息主键 + * @return 优惠券信息 + */ + PlayCouponInfoEntity selectPlayCouponInfoById(String id); + + /** + * 查询优惠券信息列表 + * + * @param vo + * 优惠券分页查询实体 + * @return 优惠券信息集合 + */ + IPage selectByPage(PlayCouponInfoQueryVo vo); + + /** + * 查询优惠券信息列表 + * + * @return 优惠券信息集合 + */ + List queryAll(); + + /** + * 查询优惠券信息列表 + * + * @param playCouponInfo + * 优惠券信息 + * @return 优惠券信息集合 + */ + IPage selectPlayCouponInfoByPage(PlayCouponInfoEntity playCouponInfo); + + /** + * 新增优惠券信息 + * + * @param playCouponInfo + * 优惠券信息 + * @return 结果 + */ + boolean create(PlayCouponInfoEntity playCouponInfo); + + /** + * 修改优惠券信息 + * + * @param playCouponInfo + * 优惠券信息 + * @return 结果 + */ + boolean update(PlayCouponInfoEntity playCouponInfo); + + /** + * 批量删除优惠券信息 + * + * @param ids + * 需要删除的优惠券信息主键集合 + * @return 结果 + */ + int deletePlayCouponInfoByIds(String[] ids); + + /** + * 删除优惠券信息信息 + * + * @param id + * 优惠券信息主键 + * @return 结果 + */ + int deletePlayCouponInfoById(String id); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/service/IPlayGiftInfoService.java --- +package com.starry.admin.modules.shop.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.shop.module.entity.PlayGiftInfoEntity; +import com.starry.admin.modules.weichat.entity.gift.PlayClerkGiftReturnVo; +import java.util.List; + +/** + * 礼物Service接口 + * + * @author admin + * @since 2024-04-25 + */ +public interface IPlayGiftInfoService extends IService { + /** + * 查询礼物 + * + * @param id + * 礼物主键 + * @return 礼物 + */ + PlayGiftInfoEntity selectPlayGiftInfoById(String id); + + /** + * 查询所有礼物 + * + * @return List + * @author admin + * @since 2024/4/25 15:56 + **/ + List listByAll(); + + /** + * 店员查询所有礼物 + * + * @param clerkId + * 店员ID + * @param obtained + * 店员获得礼物状态,[0:未获得,1:已获得] + * @return List + * @author admin + * @since 2024/4/25 15:56 + **/ + List clerkListByAll(String clerkId, String obtained); + + /** + * 店员查询所有礼物 + * + * @param customId + * 顾客ID + * @param obtained + * 礼物状态,[0:未获得,1:已获得] + * @param history + * 是否是历史礼物(0:不是,1:是) + * @return List + * @author admin + * @since 2024/4/25 15:56 + **/ + List customListByAll(String customId, String obtained); + + /** + * 查询礼物列表 + * + * @param playGiftInfo + * 礼物 + * @return 礼物集合 + */ + IPage selectPlayGiftInfoByPage(PlayGiftInfoEntity playGiftInfo); + + /** + * 新增礼物 + * + * @param playGiftInfo + * 礼物 + * @return 结果 + */ + boolean create(PlayGiftInfoEntity playGiftInfo); + + /** + * 修改礼物 + * + * @param playGiftInfo + * 礼物 + * @return 结果 + */ + boolean update(PlayGiftInfoEntity playGiftInfo); + + /** + * 批量删除礼物 + * + * @param ids + * 需要删除的礼物主键集合 + * @return 结果 + */ + int deletePlayGiftInfoByIds(String[] ids); + + /** + * 删除礼物信息 + * + * @param id礼物主键 + * @return 结果 + */ + int deletePlayGiftInfoById(String id); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/service/IPlayShopArticleInfoService.java --- +package com.starry.admin.modules.shop.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.shop.module.entity.PlayShopArticleInfoEntity; +import com.starry.admin.modules.shop.module.vo.PlayShopArticleInfoQueryVo; +import java.util.List; + +/** + * 店铺文章信息Service接口 + * + * @author admin + * @since 2024-06-05 + */ +public interface IPlayShopArticleInfoService extends IService { + /** + * 查询店铺文章信息 + * + * @param id + * 店铺文章信息主键 + * @return 店铺文章信息 + */ + PlayShopArticleInfoEntity selectById(String id); + + /** + * 根据文章类型查询店铺文章 + * + * @param type + * 店铺文章类型 + * @return 店铺文章信息 + */ + PlayShopArticleInfoEntity selectByType(String type); + /** + * 查询店铺文章信息列表 + * + * @param vo + * 店铺文章信息查询对象 + * @return 店铺文章信息集合 + */ + IPage selectByPage(PlayShopArticleInfoQueryVo vo); + + /** + * 查询店铺文章信息列表 + * + * @return 店铺文章信息集合 + */ + List selectByList(); + + /** + * 新增店铺文章信息 + * + * @param articleInfoEntity + * 店铺文章信息 + * @return 结果 + */ + boolean create(PlayShopArticleInfoEntity articleInfoEntity); + + /** + * 修改店铺文章信息 + * + * @param articleInfoEntity + * 店铺文章信息 + * @return 结果 + */ + boolean update(PlayShopArticleInfoEntity articleInfoEntity); + + /** + * 批量删除店铺文章信息 + * + * @param ids + * 需要删除的店铺文章信息主键集合 + * @return 结果 + */ + int deleteByIds(String[] ids); + + /** + * 删除店铺文章信息信息 + * + * @param id + * 店铺文章信息主键 + * @return 结果 + */ + int deleteById(String id); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/service/IPlayShopCarouselInfoService.java --- +package com.starry.admin.modules.shop.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.shop.module.entity.PlayShopCarouselInfoEntity; +import com.starry.admin.modules.shop.module.vo.PlayShopCarouselInfoQueryVo; +import java.util.List; + +/** + * 店铺首页轮播Service接口 + * + * @author admin + * @since 2024-06-05 + */ +public interface IPlayShopCarouselInfoService extends IService { + /** + * 查询店铺首页轮播 + * + * @param id + * 店铺首页轮播主键 + * @return 店铺首页轮播 + */ + PlayShopCarouselInfoEntity selectPlayCarouselInfoById(String id); + + /** + * 查询店铺首页轮播列表 + * + * @param vo + * 店铺首页轮播查询对象 + * @return 店铺首页轮播集合 + */ + IPage selectByPage(PlayShopCarouselInfoQueryVo vo); + + /** + * 查询店铺首页轮播列表 + * + * @return 店铺首页轮播集合 + */ + List selectHomeCarouselInfo(); + + /** + * 新增店铺首页轮播 + * + * @param playCarouselInfo + * 店铺首页轮播 + * @return 结果 + */ + boolean create(PlayShopCarouselInfoEntity playCarouselInfo); + + /** + * 修改店铺首页轮播 + * + * @param playCarouselInfo + * 店铺首页轮播 + * @return 结果 + */ + boolean update(PlayShopCarouselInfoEntity playCarouselInfo); + + /** + * 批量删除店铺首页轮播 + * + * @param ids + * 需要删除的店铺首页轮播主键集合 + * @return 结果 + */ + int deletePlayCarouselInfoByIds(String[] ids); + + /** + * 删除店铺首页轮播信息 + * + * @param id + * 店铺首页轮播主键 + * @return 结果 + */ + int deletePlayCarouselInfoById(String id); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/service/IShopUiSettingService.java --- +package com.starry.admin.modules.shop.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.shop.module.entity.ShopUiSettingEntity; + +/** + * 店铺设置Service接口 + * + * @author admin + * @since 2025-06-11 + */ +public interface IShopUiSettingService extends IService { + /** + * 查询店铺设置 + * + * @return 店铺设置 + */ + ShopUiSettingEntity selectShopUiSettingInfo(); + + /** + * 修改店铺设置 + * + * @param shopUiSetting + * 店铺设置 + * @return 结果 + */ + boolean update(ShopUiSettingEntity shopUiSetting); + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/service/impl/PlayClerkGiftInfoServiceImpl.java --- +package com.starry.admin.modules.shop.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.starry.admin.modules.shop.mapper.PlayClerkGiftInfoMapper; +import com.starry.admin.modules.shop.module.entity.PlayClerkGiftInfoEntity; +import com.starry.admin.modules.shop.service.IPlayClerkGiftInfoService; +import com.starry.common.utils.IdUtils; +import java.util.Arrays; +import java.util.List; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 店员和礼物关系Service业务层处理 + * + * @author admin + * @since 2024-05-25 + */ +@Service +public class PlayClerkGiftInfoServiceImpl extends ServiceImpl + implements + IPlayClerkGiftInfoService { + @Resource + private PlayClerkGiftInfoMapper playClerkGiftInfoMapper; + + @Override + public PlayClerkGiftInfoEntity selectByGiftIdAndClerkId(String giftId, String clerkId) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayClerkGiftInfoEntity::getClerkId, clerkId); + lambdaQueryWrapper.eq(PlayClerkGiftInfoEntity::getGiffId, giftId); + return this.baseMapper.selectOne(lambdaQueryWrapper); + } + + /** + * 根据店员ID查询店员活动礼物列表 + * + * @param clerkId + * 店员ID + * @return 店员活动礼物列表 + */ + @Override + public List selectBtyClerkId(String clerkId) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayClerkGiftInfoEntity::getClerkId, clerkId); + return this.baseMapper.selectList(lambdaQueryWrapper); + } + + /** + * 查询店员和礼物关系 + * + * @param id + * 店员和礼物关系主键 + * @return 店员和礼物关系 + */ + @Override + public PlayClerkGiftInfoEntity selectPlayClerkGiftInfoById(String id) { + return this.baseMapper.selectById(id); + } + + /** + * 查询店员和礼物关系列表 + * + * @param playClerkGiftInfo + * 店员和礼物关系 + * @return 店员和礼物关系 + */ + @Override + public IPage selectPlayClerkGiftInfoByPage(PlayClerkGiftInfoEntity playClerkGiftInfo) { + Page page = new Page<>(1, 10); + return this.baseMapper.selectPage(page, new LambdaQueryWrapper<>()); + } + + /** + * 新增店员和礼物关系 + * + * @param playClerkGiftInfo + * 店员和礼物关系 + * @return 结果 + */ + @Override + public boolean create(PlayClerkGiftInfoEntity playClerkGiftInfo) { + if (StrUtil.isBlankIfStr(playClerkGiftInfo.getId())) { + playClerkGiftInfo.setId(IdUtils.getUuid()); + } + return save(playClerkGiftInfo); + } + + /** + * 修改店员和礼物关系 + * + * @param playClerkGiftInfo + * 店员和礼物关系 + * @return 结果 + */ + @Override + public boolean update(PlayClerkGiftInfoEntity playClerkGiftInfo) { + return updateById(playClerkGiftInfo); + } + + /** + * 批量删除店员和礼物关系 + * + * @param ids + * 需要删除的店员和礼物关系主键 + * @return 结果 + */ + @Override + public int deletePlayClerkGiftInfoByIds(String[] ids) { + return playClerkGiftInfoMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除店员和礼物关系信息 + * + * @param id + * 店员和礼物关系主键 + * @return 结果 + */ + @Override + public int deletePlayClerkGiftInfoById(String id) { + return playClerkGiftInfoMapper.deleteById(id); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/service/impl/PlayCommodityAndLevelInfoServiceImpl.java --- +package com.starry.admin.modules.shop.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.starry.admin.modules.shop.mapper.PlayCommodityAndLevelInfoMapper; +import com.starry.admin.modules.shop.module.entity.PlayCommodityAndLevelInfoEntity; +import com.starry.admin.modules.shop.service.IPlayCommodityAndLevelInfoService; +import com.starry.common.utils.IdUtils; +import java.util.Arrays; +import java.util.List; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 服务项目和店员等级数据Service业务层处理 + * + * @author admin + * @since 2024-08-16 + */ +@Service +public class PlayCommodityAndLevelInfoServiceImpl + extends + ServiceImpl + implements + IPlayCommodityAndLevelInfoService { + @Resource + private PlayCommodityAndLevelInfoMapper playCommodityAndLevelInfoMapper; + + @Override + public PlayCommodityAndLevelInfoEntity queryById(String commodityId, String levelId) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(PlayCommodityAndLevelInfoEntity::getCommodityId, commodityId); + queryWrapper.eq(PlayCommodityAndLevelInfoEntity::getLevelId, levelId); + return playCommodityAndLevelInfoMapper.selectOne(queryWrapper); + } + + @Override + public List selectAll() { + return this.baseMapper.selectList(new LambdaQueryWrapper<>()); + } + + /** + * 查询服务项目和店员等级数据 + * + * @param id + * 服务项目和店员等级数据主键 + * @return 服务项目和店员等级数据 + */ + @Override + public PlayCommodityAndLevelInfoEntity selectPlayCommodityAndLevelInfoById(String id) { + return this.baseMapper.selectById(id); + } + + /** + * 查询服务项目和店员等级数据列表 + * + * @param playCommodityAndLevelInfo + * 服务项目和店员等级数据 + * @return 服务项目和店员等级数据 + */ + @Override + public IPage selectPlayCommodityAndLevelInfoByPage( + PlayCommodityAndLevelInfoEntity playCommodityAndLevelInfo) { + Page page = new Page<>(1, 10); + return this.baseMapper.selectPage(page, new LambdaQueryWrapper()); + } + + /** + * 新增服务项目和店员等级数据 + * + * @param playCommodityAndLevelInfo + * 服务项目和店员等级数据 + * @return 结果 + */ + @Override + public boolean create(PlayCommodityAndLevelInfoEntity playCommodityAndLevelInfo) { + if (StrUtil.isBlankIfStr(playCommodityAndLevelInfo.getId())) { + playCommodityAndLevelInfo.setId(IdUtils.getUuid()); + } + return save(playCommodityAndLevelInfo); + } + + /** + * 修改服务项目和店员等级数据 + * + * @param playCommodityAndLevelInfo + * 服务项目和店员等级数据 + * @return 结果 + */ + @Override + public boolean update(PlayCommodityAndLevelInfoEntity playCommodityAndLevelInfo) { + return updateById(playCommodityAndLevelInfo); + } + + /** + * 批量删除服务项目和店员等级数据 + * + * @param ids + * 需要删除的服务项目和店员等级数据主键 + * @return 结果 + */ + @Override + public int deletePlayCommodityAndLevelInfoByIds(String[] ids) { + return playCommodityAndLevelInfoMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除服务项目和店员等级数据信息 + * + * @param id + * 服务项目和店员等级数据主键 + * @return 结果 + */ + @Override + public int deletePlayCommodityAndLevelInfoById(String id) { + return playCommodityAndLevelInfoMapper.deleteById(id); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/service/impl/PlayCommodityInfoServiceImpl.java --- +package com.starry.admin.modules.shop.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.github.yulichang.wrapper.MPJLambdaWrapper; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.shop.mapper.PlayCommodityInfoMapper; +import com.starry.admin.modules.shop.module.entity.PlayCommodityInfoEntity; +import com.starry.admin.modules.shop.module.vo.PlayCommodityInfoVo; +import com.starry.admin.modules.shop.service.IPlayCommodityInfoService; +import com.starry.admin.modules.weichat.entity.PlayCommodityReturnVo; +import com.starry.admin.utils.SecurityUtils; +import com.starry.common.utils.ConvertUtil; +import com.starry.common.utils.IdUtils; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 服务项目Service业务层处理 + * + * @author admin + * @since 2024-03-31 + */ +@Service +public class PlayCommodityInfoServiceImpl extends ServiceImpl + implements + IPlayCommodityInfoService { + @Resource + private PlayCommodityInfoMapper playCommodityInfoMapper; + + @Override + public void initPlayCommodityInfo(String tenantId) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayCommodityInfoEntity::getTenantId, tenantId); + List list = playCommodityInfoMapper.selectList(lambdaQueryWrapper); + if (list == null || list.isEmpty()) { + // 查询默认租户的服务信息,然后复制其属性 + SecurityUtils.setTenantId("default"); + LambdaQueryWrapper lambdaQueryWrapper1 = new LambdaQueryWrapper<>(); + lambdaQueryWrapper1.eq(PlayCommodityInfoEntity::getPId, "00"); + for (PlayCommodityInfoEntity entity : playCommodityInfoMapper.selectList(lambdaQueryWrapper1)) { + initPlayCommodityInfo(entity, tenantId); + } + } + } + + public void initPlayCommodityInfo(PlayCommodityInfoEntity entity, String tenantId) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayCommodityInfoEntity::getPId, entity.getId()); + entity.setId(IdUtils.getUuid()); + entity.setTenantId(tenantId); + this.baseMapper.insert(entity); + List list = playCommodityInfoMapper.selectList(lambdaQueryWrapper); + for (PlayCommodityInfoEntity commodityInfo : list) { + commodityInfo.setPId(entity.getId()); + initPlayCommodityInfo(commodityInfo, tenantId); + } + } + + @Override + public List selectTree() { + MPJLambdaWrapper lambdaQueryWrapper = new MPJLambdaWrapper<>(); + lambdaQueryWrapper.selectAll(PlayCommodityInfoEntity.class); + lambdaQueryWrapper.orderByDesc(PlayCommodityInfoEntity::getSort); + List list = this.baseMapper.selectJoinList(PlayCommodityInfoEntity.class, + lambdaQueryWrapper); + Map> collect = list.stream().filter(a -> a != null && a.getId() != null) + .collect(Collectors.groupingBy(PlayCommodityInfoEntity::getPId)); + return this.assembleTree(collect, collect.get("00")); + } + + /** + * 组装数据 + * + * @param data + * 数据,key=区域编码,value=区域列表 + * @param list + * 区域略表 + * @return List + * @author admin + * @since 2024/4/10 15:14 + **/ + public List assembleTree(Map> data, + List list) { + if (list == null) { + return new ArrayList<>(); + } + List result = ConvertUtil.entityToVoList(list, PlayCommodityReturnVo.class); + for (PlayCommodityReturnVo entity : result) { + entity.setChild(assembleTree(data, data.get(entity.getId()))); + } + return result; + } + + @Override + public List selectByType() { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayCommodityInfoEntity::getItemType, "服务类型"); + lambdaQueryWrapper.orderByDesc(PlayCommodityInfoEntity::getSort); + return this.baseMapper.selectList(lambdaQueryWrapper); + } + + @Override + public List selectAll() { + return this.baseMapper.selectList(new LambdaQueryWrapper<>()); + } + + @Override + public PlayCommodityInfoVo queryCommodityInfo(String id, String levelId) { + PlayCommodityInfoVo vo = this.baseMapper.queryCommodityInfo(id, levelId); + if (vo == null) { + throw new CustomException("服务项目不存在"); + } + return vo; + } + + /** + * 查询服务项目 + * + * @param id + * 服务项目主键 + * @return 服务项目 + */ + @Override + public PlayCommodityInfoEntity selectPlayCommodityInfoById(String id) { + PlayCommodityInfoEntity entity = this.baseMapper.selectById(id); + if (entity == null) { + throw new CustomException("服务项目不存在"); + } + return entity; + } + + @Override + public List selectByPId(String pId) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(PlayCommodityInfoEntity::getPId, pId); + lambdaQueryWrapper.orderByDesc(PlayCommodityInfoEntity::getSort); + return this.baseMapper.selectList(lambdaQueryWrapper); + } + + /** + * 查询服务项目列表 + * + * @param playCommodityInfo + * 服务项目 + * @return 服务项目 + */ + @Override + public IPage selectPlayCommodityInfoByPage(PlayCommodityInfoEntity playCommodityInfo) { + Page page = new Page<>(1, 10); + return this.baseMapper.selectPage(page, new LambdaQueryWrapper<>()); + } + + /** + * 新增服务项目 + * + * @param playCommodityInfo + * 服务项目 + * @return 结果 + */ + @Override + public boolean create(PlayCommodityInfoEntity playCommodityInfo) { + if (StrUtil.isBlankIfStr(playCommodityInfo.getId())) { + playCommodityInfo.setId(IdUtils.getUuid()); + } + return save(playCommodityInfo); + } + + /** + * 修改服务项目 + * + * @param playCommodityInfo + * 服务项目 + * @return 结果 + */ + @Override + public boolean update(PlayCommodityInfoEntity playCommodityInfo) { + return updateById(playCommodityInfo); + } + + /** + * 批量删除服务项目 + * + * @param ids + * 需要删除的服务项目主键 + * @return 结果 + */ + @Override + public int deletePlayCommodityInfoByIds(String[] ids) { + return playCommodityInfoMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除服务项目信息 + * + * @param id + * 服务项目主键 + * @return 结果 + */ + @Override + public int deletePlayCommodityInfoById(String id) { + return playCommodityInfoMapper.deleteById(id); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/service/impl/PlayCouponDetailsServiceImpl.java --- +package com.starry.admin.modules.shop.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.github.yulichang.wrapper.MPJLambdaWrapper; +import com.starry.admin.modules.shop.mapper.PlayCouponDetailsMapper; +import com.starry.admin.modules.shop.module.entity.PlayCouponDetailsEntity; +import com.starry.admin.modules.shop.module.entity.PlayCouponInfoEntity; +import com.starry.admin.modules.shop.module.vo.PlayCouponDetailsQueryVo; +import com.starry.admin.modules.shop.module.vo.PlayCouponDetailsReturnVo; +import com.starry.admin.modules.shop.service.IPlayCouponDetailsService; +import com.starry.common.utils.IdUtils; +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.List; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 优惠券详情Service业务层处理 + * + * @author admin + * @since 2024-07-04 + */ +@Service +public class PlayCouponDetailsServiceImpl extends ServiceImpl + implements + IPlayCouponDetailsService { + @Resource + private PlayCouponDetailsMapper playCouponDetailsMapper; + + /** + * 查询优惠券详情 + * + * @param id + * 优惠券详情主键 + * @return 优惠券详情 + */ + @Override + public PlayCouponDetailsReturnVo selectPlayCouponDetailsById(String id) { + MPJLambdaWrapper lambdaWrapper = new MPJLambdaWrapper<>(); + lambdaWrapper.selectAll(PlayCouponDetailsEntity.class); + lambdaWrapper.leftJoin(PlayCouponInfoEntity.class, PlayCouponInfoEntity::getId, + PlayCouponDetailsEntity::getCouponId); + lambdaWrapper.eq(PlayCouponDetailsEntity::getId, id); + return this.baseMapper.selectJoinOne(PlayCouponDetailsReturnVo.class, lambdaWrapper); + } + + @Override + public IPage selectByPage(PlayCouponDetailsQueryVo vo) { + MPJLambdaWrapper lambdaWrapper = new MPJLambdaWrapper<>(); + lambdaWrapper.selectAll(PlayCouponDetailsEntity.class); + lambdaWrapper.selectAll(PlayCouponInfoEntity.class); + lambdaWrapper.leftJoin(PlayCouponInfoEntity.class, PlayCouponInfoEntity::getId, + PlayCouponDetailsEntity::getCouponId); + if (StrUtil.isNotBlank(vo.getCouponId())) { + lambdaWrapper.eq(PlayCouponDetailsEntity::getCouponId, vo.getCouponId()); + } + if (StrUtil.isNotBlank(vo.getCustomId())) { + lambdaWrapper.eq(PlayCouponDetailsEntity::getCustomId, vo.getCustomId()); + } + if (StrUtil.isNotBlank(vo.getUseState())) { + lambdaWrapper.eq(PlayCouponDetailsEntity::getUseState, vo.getUseState()); + } + if (StrUtil.isNotBlank(vo.getObtainingChannels())) { + lambdaWrapper.eq(PlayCouponDetailsEntity::getObtainingChannels, vo.getObtainingChannels()); + } + if (vo.getObtainingTime() != null && vo.getObtainingTime().size() == 2) { + lambdaWrapper.between(PlayCouponDetailsEntity::getObtainingTime, vo.getObtainingTime().get(0), + vo.getObtainingTime().get(1)); + } + if (vo.getUseTime() != null && vo.getUseTime().size() == 2) { + lambdaWrapper.between(PlayCouponDetailsEntity::getUseTime, vo.getUseTime().get(0), vo.getUseTime().get(1)); + } + + return this.baseMapper.selectJoinPage(new Page<>(vo.getPageNum(), vo.getPageSize()), + PlayCouponDetailsReturnVo.class, lambdaWrapper); + } + + /** + * 查询优惠券详情列表 + * + * @param playCouponDetails + * 优惠券详情 + * @return 优惠券详情 + */ + @Override + public IPage selectPlayCouponDetailsByPage(PlayCouponDetailsEntity playCouponDetails) { + Page page = new Page<>(1, 10); + return this.baseMapper.selectPage(page, new LambdaQueryWrapper()); + } + + @Override + public void create(String customId, String customNickName, String customLevel, String couponId, + String obtainingChannels, String useState) { + PlayCouponDetailsEntity couponDetails = new PlayCouponDetailsEntity(); + couponDetails.setId(IdUtils.getUuid()); + couponDetails.setCustomId(customId); + couponDetails.setCustomNickname(customNickName); + couponDetails.setCustomLevelId(customLevel); + couponDetails.setCouponId(couponId); + couponDetails.setObtainingChannels(obtainingChannels); + couponDetails.setObtainingTime(LocalDateTime.now()); + couponDetails.setUseState(useState); + this.create(couponDetails); + } + + /** + * 新增优惠券详情 + * + * @param playCouponDetails + * 优惠券详情 + * @return 结果 + */ + @Override + public boolean create(PlayCouponDetailsEntity playCouponDetails) { + if (StrUtil.isBlankIfStr(playCouponDetails.getId())) { + playCouponDetails.setId(IdUtils.getUuid()); + } + return save(playCouponDetails); + } + + @Override + public List selectByCustomId(String customId) { + MPJLambdaWrapper lambdaWrapper = new MPJLambdaWrapper<>(); + lambdaWrapper.selectAll(PlayCouponDetailsEntity.class); + lambdaWrapper.selectAll(PlayCouponInfoEntity.class); + lambdaWrapper.eq(PlayCouponDetailsEntity::getCustomId, customId); + lambdaWrapper.leftJoin(PlayCouponInfoEntity.class, PlayCouponInfoEntity::getId, + PlayCouponDetailsEntity::getCouponId); + return this.baseMapper.selectJoinList(PlayCouponDetailsReturnVo.class, lambdaWrapper); + } + + /** + * 修改优惠券详情 + * + * @param playCouponDetails + * 优惠券详情 + * @return 结果 + */ + @Override + public boolean update(PlayCouponDetailsEntity playCouponDetails) { + return updateById(playCouponDetails); + } + + @Override + public void updateCouponUseStateByIds(List ids, String useState) { + for (String id : ids) { + PlayCouponDetailsEntity entity = new PlayCouponDetailsEntity(); + entity.setId(id); + entity.setUseState(useState); + entity.setUseTime(LocalDateTime.now()); + baseMapper.updateById(entity); + } + } + + /** + * 批量删除优惠券详情 + * + * @param ids + * 需要删除的优惠券详情主键 + * @return 结果 + */ + @Override + public int deletePlayCouponDetailsByIds(String[] ids) { + return playCouponDetailsMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除优惠券详情信息 + * + * @param id + * 优惠券详情主键 + * @return 结果 + */ + @Override + public int deletePlayCouponDetailsById(String id) { + return playCouponDetailsMapper.deleteById(id); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/service/impl/PlayCouponInfoServiceImpl.java --- +package com.starry.admin.modules.shop.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.github.yulichang.wrapper.MPJLambdaWrapper; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.custom.module.entity.PlayCustomUserInfoEntity; +import com.starry.admin.modules.shop.mapper.PlayCouponInfoMapper; +import com.starry.admin.modules.shop.module.entity.PlayCouponInfoEntity; +import com.starry.admin.modules.shop.module.vo.PlayCouponInfoQueryVo; +import com.starry.admin.modules.shop.module.vo.PlayCouponInfoReturnVo; +import com.starry.admin.modules.shop.service.IPlayCouponInfoService; +import com.starry.common.utils.IdUtils; +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.List; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 优惠券信息Service业务层处理 + * + * @author admin + * @since 2024-07-04 + */ +@Service +public class PlayCouponInfoServiceImpl extends ServiceImpl + implements + IPlayCouponInfoService { + @Resource + private PlayCouponInfoMapper playCouponInfoMapper; + + /** + * 获取优惠券不可用的原因 + * + * @param couponInfo + * 优惠券信息 + * @param placeType + * 下单类型 + * @param commodityId + * 商品ID + * @param commodityQuantity + * 商品数量 + * @return 不可用原因 + */ + @Override + public String getCouponReasonForUnavailableUse(PlayCouponInfoEntity couponInfo, String placeType, + String commodityId, Integer commodityQuantity, BigDecimal price) { + if (StrUtil.isEmpty(commodityId) || commodityQuantity <= 0) { + return "订单满1船票余额时可用"; + } + boolean placeTypeSuccess = false; + for (String string : couponInfo.getPlaceType()) { + if (string.equals(placeType)) { + placeTypeSuccess = true; + break; + } + } + if (!placeTypeSuccess) { + return "订单类型不符合"; + } + // 订单门槛不等0,并且订单金额小于订单门槛 + if (BigDecimal.ZERO.compareTo(couponInfo.getUseMinAmount()) != 0 + && price.multiply(new BigDecimal(commodityQuantity)).compareTo(couponInfo.getUseMinAmount()) <= -1) { + return "订单门槛不符合"; + } + return ""; + } + + /** + * 获取优惠券不可领取的原因 + * + * @param entity + * 优惠券实体 + * @param customUserInfo + * 顾客实体 + * @return String + * @author admin + * @since 2024/7/8 14:44 + **/ + @Override + public String getReasonForNotObtainingCoupons(PlayCouponInfoEntity entity, + PlayCustomUserInfoEntity customUserInfo) { + // 优惠券是否设置指定条件领取 + if ("0".equals(entity.getClaimConditionType())) { + return ""; + } + // 顾客等级判断 + String msg = reasonForNotObtainingCoupons(entity.getCustomLevelCheckType(), entity.getCustomLevel(), + customUserInfo.getLevelId(), "0"); + if (StrUtil.isNotEmpty(msg)) { + return msg; + } + // 顾客性别判断 + msg = reasonForNotObtainingCoupons(entity.getCustomSexCheckType(), entity.getCustomSex(), + customUserInfo.getSex().toString(), "`1"); + if (StrUtil.isNotEmpty(msg)) { + return msg; + } + // 顾客关注公众号状态判断 + + // 顾客是否是新用户判断 + return ""; + } + + /** + * 获取优惠券不可领取的原因 + * + * @param checkStatus + * 是否配置了该项指标(0:未配置,1:已配置) + * @param attributes + * 配置的属性列表 + * @param attribute + * 用户属性值 + * @param type + * 条件类型(0:用户等级,1:用户性别) + * @return String + * @author admin + * @since 2024/7/8 15:22 + **/ + public String reasonForNotObtainingCoupons(String checkStatus, List attributes, String attribute, + String type) { + if ("0".equals(checkStatus)) { + return ""; + } + for (String s : attributes) { + if (s.equals(attribute)) { + return ""; + } + } + if ("0".equals(type)) { + return "用户等级不匹配"; + } + if ("1".equals(type)) { + return "用户性别不匹配"; + } + return ""; + } + + /** + * 查询优惠券信息 + * + * @param id + * 优惠券信息主键 + * @return 优惠券信息 + */ + @Override + public PlayCouponInfoEntity selectPlayCouponInfoById(String id) { + PlayCouponInfoEntity entity = this.baseMapper.selectById(id); + if (entity == null) { + throw new CustomException("优惠券不存在"); + } + return entity; + } + + @Override + public IPage selectByPage(PlayCouponInfoQueryVo vo) { + MPJLambdaWrapper lambdaQueryWrapper = new MPJLambdaWrapper<>(); + lambdaQueryWrapper.selectAll(PlayCouponInfoEntity.class); + lambdaQueryWrapper.orderByDesc(PlayCouponInfoEntity::getCreatedTime); + return this.baseMapper.selectJoinPage(new Page<>(vo.getPageNum(), vo.getPageSize()), + PlayCouponInfoReturnVo.class, lambdaQueryWrapper); + } + + @Override + public List queryAll() { + MPJLambdaWrapper lambdaQueryWrapper = new MPJLambdaWrapper<>(); + lambdaQueryWrapper.selectAll(PlayCouponInfoEntity.class); + lambdaQueryWrapper.orderByDesc(PlayCouponInfoEntity::getCreatedTime); + return this.baseMapper.selectJoinList(PlayCouponInfoEntity.class, lambdaQueryWrapper); + } + + /** + * 查询优惠券信息列表 + * + * @param playCouponInfo + * 优惠券信息 + * @return 优惠券信息 + */ + @Override + public IPage selectPlayCouponInfoByPage(PlayCouponInfoEntity playCouponInfo) { + Page page = new Page<>(1, 10); + return this.baseMapper.selectPage(page, new LambdaQueryWrapper()); + } + + /** + * 新增优惠券信息 + * + * @param playCouponInfo + * 优惠券信息 + * @return 结果 + */ + @Override + public boolean create(PlayCouponInfoEntity playCouponInfo) { + if (StrUtil.isBlankIfStr(playCouponInfo.getId())) { + playCouponInfo.setId(IdUtils.getUuid()); + } + return save(playCouponInfo); + } + + /** + * 修改优惠券信息 + * + * @param playCouponInfo + * 优惠券信息 + * @return 结果 + */ + @Override + public boolean update(PlayCouponInfoEntity playCouponInfo) { + return updateById(playCouponInfo); + } + + /** + * 批量删除优惠券信息 + * + * @param ids + * 需要删除的优惠券信息主键 + * @return 结果 + */ + @Override + public int deletePlayCouponInfoByIds(String[] ids) { + return playCouponInfoMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除优惠券信息信息 + * + * @param id + * 优惠券信息主键 + * @return 结果 + */ + @Override + public int deletePlayCouponInfoById(String id) { + return playCouponInfoMapper.deleteById(id); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/service/impl/PlayGiftInfoServiceImpl.java --- +package com.starry.admin.modules.shop.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.github.yulichang.wrapper.MPJLambdaWrapper; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.custom.module.entity.PlayCustomGiftInfoEntity; +import com.starry.admin.modules.custom.service.impl.PlayCustomGiftInfoServiceImpl; +import com.starry.admin.modules.shop.mapper.PlayGiftInfoMapper; +import com.starry.admin.modules.shop.module.entity.PlayClerkGiftInfoEntity; +import com.starry.admin.modules.shop.module.entity.PlayGiftInfoEntity; +import com.starry.admin.modules.shop.service.IPlayGiftInfoService; +import com.starry.admin.modules.weichat.entity.gift.PlayClerkGiftReturnVo; +import com.starry.common.utils.IdUtils; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 礼物Service业务层处理 + * + * @author admin + * @since 2024-04-25 + */ +@Service +public class PlayGiftInfoServiceImpl extends ServiceImpl + implements + IPlayGiftInfoService { + @Resource + private PlayGiftInfoMapper playGiftInfoMapper; + + @Resource + private PlayClerkGiftInfoServiceImpl clerkGiftInfoService; + + @Resource + private PlayCustomGiftInfoServiceImpl customGiftInfoService; + + /** + * 查询礼物 + * + * @param id + * 礼物主键 + * @return 礼物 + */ + @Override + public PlayGiftInfoEntity selectPlayGiftInfoById(String id) { + PlayGiftInfoEntity entity = this.baseMapper.selectById(id); + if (entity == null) { + throw new CustomException("礼物不存在"); + } + return entity; + } + + @Override + public List customListByAll(String customId, String obtained) { + if ("0".equals(obtained)) { + // 查询所有礼物,然后减去已获得礼物 + MPJLambdaWrapper lambdaWrapper = new MPJLambdaWrapper<>(); + lambdaWrapper.selectAll(PlayGiftInfoEntity.class); + List list = this.baseMapper.selectJoinList(PlayClerkGiftReturnVo.class, + lambdaWrapper); + List giftInfoEntities = customGiftInfoService.selectBtyCustomId(customId); + // 使用迭代器安全地移除元素 + Iterator iterator = list.iterator(); + while (iterator.hasNext()) { + PlayClerkGiftReturnVo item = iterator.next(); + for (PlayCustomGiftInfoEntity giftInfoEntity : giftInfoEntities) { + if (giftInfoEntity.getGiffId().equals(item.getId())) { + iterator.remove(); + break; + } + } + + } + return list; + } + if ("1".equals(obtained)) { + MPJLambdaWrapper lambdaWrapper = new MPJLambdaWrapper<>(); + lambdaWrapper.selectAll(PlayGiftInfoEntity.class); + // 礼物活动表 + lambdaWrapper.selectAs(PlayCustomGiftInfoEntity::getGiffNumber, "giffNumber"); + lambdaWrapper.innerJoin(PlayCustomGiftInfoEntity.class, PlayCustomGiftInfoEntity::getGiffId, + PlayGiftInfoEntity::getId); + lambdaWrapper.eq(PlayCustomGiftInfoEntity::getCustomId, customId); + return this.baseMapper.selectJoinList(PlayClerkGiftReturnVo.class, lambdaWrapper); + } + return new ArrayList<>(); + + } + + @Override + public List clerkListByAll(String clerkId, String obtained) { + if ("0".equals(obtained)) { + // 查询所有礼物,然后减去已获得礼物 + MPJLambdaWrapper lambdaWrapper = new MPJLambdaWrapper<>(); + lambdaWrapper.selectAll(PlayGiftInfoEntity.class); + List list = this.baseMapper.selectJoinList(PlayClerkGiftReturnVo.class, + lambdaWrapper); + List clerkGiftInfoEntities = clerkGiftInfoService.selectBtyClerkId(clerkId); + // 使用迭代器安全地移除元素 + Iterator iterator = list.iterator(); + while (iterator.hasNext()) { + PlayClerkGiftReturnVo item = iterator.next(); + for (PlayClerkGiftInfoEntity clerkGiftInfoEntity : clerkGiftInfoEntities) { + if (clerkGiftInfoEntity.getGiffId().equals(item.getId())) { + iterator.remove(); + break; + } + } + + } + return list; + } + if ("1".equals(obtained)) { + MPJLambdaWrapper lambdaWrapper = new MPJLambdaWrapper<>(); + lambdaWrapper.selectAll(PlayGiftInfoEntity.class); + // 礼物活动表 + lambdaWrapper.selectAs(PlayClerkGiftInfoEntity::getGiffNumber, "giffNumber"); + lambdaWrapper.innerJoin(PlayClerkGiftInfoEntity.class, PlayClerkGiftInfoEntity::getGiffId, + PlayGiftInfoEntity::getId); + lambdaWrapper.eq(PlayClerkGiftInfoEntity::getClerkId, clerkId); + return this.baseMapper.selectJoinList(PlayClerkGiftReturnVo.class, lambdaWrapper); + } + return new ArrayList<>(); + } + + @Override + public List listByAll() { + return this.baseMapper.selectList(new LambdaQueryWrapper<>()); + } + + /** + * 查询礼物列表 + * + * @param playGiftInfo + * 礼物 + * @return 礼物 + */ + @Override + public IPage selectPlayGiftInfoByPage(PlayGiftInfoEntity playGiftInfo) { + Page page = new Page<>(1, 10); + return this.baseMapper.selectPage(page, new LambdaQueryWrapper<>()); + } + + /** + * 新增礼物 + * + * @param playGiftInfo + * 礼物 + * @return 结果 + */ + @Override + public boolean create(PlayGiftInfoEntity playGiftInfo) { + if (StrUtil.isBlankIfStr(playGiftInfo.getId())) { + playGiftInfo.setId(IdUtils.getUuid()); + } + return save(playGiftInfo); + } + + /** + * 修改礼物 + * + * @param playGiftInfo + * 礼物 + * @return 结果 + */ + @Override + public boolean update(PlayGiftInfoEntity playGiftInfo) { + return updateById(playGiftInfo); + } + + /** + * 批量删除礼物 + * + * @param ids + * 需要删除的礼物主键 + * @return 结果 + */ + @Override + public int deletePlayGiftInfoByIds(String[] ids) { + return playGiftInfoMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除礼物信息 + * + * @param id + * 礼物主键 + * @return 结果 + */ + @Override + public int deletePlayGiftInfoById(String id) { + return playGiftInfoMapper.deleteById(id); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/service/impl/PlayShopArticleInfoServiceImpl.java --- +package com.starry.admin.modules.shop.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.shop.mapper.PlayShopArticleInfoMapper; +import com.starry.admin.modules.shop.module.entity.PlayShopArticleInfoEntity; +import com.starry.admin.modules.shop.module.vo.PlayShopArticleInfoQueryVo; +import com.starry.admin.modules.shop.service.IPlayShopArticleInfoService; +import com.starry.common.utils.IdUtils; +import java.util.Arrays; +import java.util.List; +import org.springframework.stereotype.Service; + +/** + * 店铺首页轮播Service业务层处理 + * + * @author admin + * @since 2024-06-05 + */ +@Service +public class PlayShopArticleInfoServiceImpl extends ServiceImpl + implements + IPlayShopArticleInfoService { + + @Override + public PlayShopArticleInfoEntity selectByType(String type) { + LambdaQueryWrapper lambdaWrapper = new LambdaQueryWrapper<>(); + lambdaWrapper.eq(PlayShopArticleInfoEntity::getArticleType, type); + return this.baseMapper.selectOne(lambdaWrapper); + } + + /** + * 查询店铺首页轮播 + * + * @param id + * 店铺首页轮播主键 + * @return 店铺首页轮播 + */ + @Override + public PlayShopArticleInfoEntity selectById(String id) { + PlayShopArticleInfoEntity entity = this.baseMapper.selectById(id); + if (entity == null) { + throw new CustomException("对象不存在"); + } + return entity; + } + + @Override + public List selectByList() { + return this.baseMapper.selectList(new LambdaQueryWrapper<>()); + + } + + @Override + public IPage selectByPage(PlayShopArticleInfoQueryVo vo) { + LambdaQueryWrapper lambdaWrapper = new LambdaQueryWrapper<>(); + if (StrUtil.isNotBlank(vo.getId())) { + lambdaWrapper.eq(PlayShopArticleInfoEntity::getId, vo.getId()); + } + if (StrUtil.isNotBlank(vo.getArticleType())) { + lambdaWrapper.eq(PlayShopArticleInfoEntity::getArticleType, vo.getArticleType()); + } + if (StrUtil.isNotBlank(vo.getArticleTitle())) { + lambdaWrapper.like(PlayShopArticleInfoEntity::getArticleTitle, vo.getArticleTitle()); + } + return this.baseMapper.selectPage(new Page<>(vo.getPageNum(), vo.getPageSize()), lambdaWrapper); + } + + /** + * 新增店铺首页轮播 + * + * @param articleInfoEntity + * 店铺首页轮播 + * @return 结果 + */ + @Override + public boolean create(PlayShopArticleInfoEntity articleInfoEntity) { + if (StrUtil.isBlankIfStr(articleInfoEntity.getId())) { + articleInfoEntity.setId(IdUtils.getUuid()); + } + return save(articleInfoEntity); + } + + /** + * 修改店铺首页轮播 + * + * @param articleInfoEntity + * 店铺首页轮播 + * @return 结果 + */ + @Override + public boolean update(PlayShopArticleInfoEntity articleInfoEntity) { + return updateById(articleInfoEntity); + } + + /** + * 批量删除店铺首页轮播 + * + * @param ids + * 需要删除的店铺首页轮播主键 + * @return 结果 + */ + @Override + public int deleteByIds(String[] ids) { + return this.baseMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除店铺首页轮播信息 + * + * @param id + * 店铺首页轮播主键 + * @return 结果 + */ + @Override + public int deleteById(String id) { + return this.baseMapper.deleteById(id); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/service/impl/PlayShopCarouselInfoServiceImpl.java --- +package com.starry.admin.modules.shop.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.starry.admin.modules.shop.mapper.PlayShopCarouselInfoMapper; +import com.starry.admin.modules.shop.module.entity.PlayShopCarouselInfoEntity; +import com.starry.admin.modules.shop.module.vo.PlayShopCarouselInfoQueryVo; +import com.starry.admin.modules.shop.service.IPlayShopCarouselInfoService; +import com.starry.common.utils.IdUtils; +import java.util.Arrays; +import java.util.List; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 店铺首页轮播Service业务层处理 + * + * @author admin + * @since 2024-06-05 + */ +@Service +public class PlayShopCarouselInfoServiceImpl extends ServiceImpl + implements + IPlayShopCarouselInfoService { + @Resource + private PlayShopCarouselInfoMapper playCarouselInfoMapper; + + /** + * 查询店铺首页轮播 + * + * @param id + * 店铺首页轮播主键 + * @return 店铺首页轮播 + */ + @Override + public PlayShopCarouselInfoEntity selectPlayCarouselInfoById(String id) { + return this.baseMapper.selectById(id); + } + + @Override + public List selectHomeCarouselInfo() { + LambdaQueryWrapper lambdaWrapper = new LambdaQueryWrapper<>(); + lambdaWrapper.eq(PlayShopCarouselInfoEntity::getCarouselIndex, "0"); + lambdaWrapper.eq(PlayShopCarouselInfoEntity::getEnableState, "1"); + return this.baseMapper.selectList(lambdaWrapper); + } + + @Override + public IPage selectByPage(PlayShopCarouselInfoQueryVo vo) { + LambdaQueryWrapper lambdaWrapper = new LambdaQueryWrapper<>(); + if (StrUtil.isNotBlank(vo.getCarouselIndex())) { + lambdaWrapper.eq(PlayShopCarouselInfoEntity::getCarouselIndex, vo.getCarouselIndex()); + } + if (StrUtil.isNotBlank(vo.getEnableState())) { + lambdaWrapper.eq(PlayShopCarouselInfoEntity::getEnableState, vo.getEnableState()); + } + if (vo.getAddTime() != null && vo.getAddTime().size() == 2) { + lambdaWrapper.between(PlayShopCarouselInfoEntity::getAddTime, vo.getAddTime().get(0), + vo.getAddTime().get(1)); + } + return this.baseMapper.selectPage(new Page<>(vo.getPageNum(), vo.getPageSize()), lambdaWrapper); + + } + + /** + * 新增店铺首页轮播 + * + * @param playCarouselInfo + * 店铺首页轮播 + * @return 结果 + */ + @Override + public boolean create(PlayShopCarouselInfoEntity playCarouselInfo) { + if (StrUtil.isBlankIfStr(playCarouselInfo.getId())) { + playCarouselInfo.setId(IdUtils.getUuid()); + } + return save(playCarouselInfo); + } + + /** + * 修改店铺首页轮播 + * + * @param playCarouselInfo + * 店铺首页轮播 + * @return 结果 + */ + @Override + public boolean update(PlayShopCarouselInfoEntity playCarouselInfo) { + return updateById(playCarouselInfo); + } + + /** + * 批量删除店铺首页轮播 + * + * @param ids + * 需要删除的店铺首页轮播主键 + * @return 结果 + */ + @Override + public int deletePlayCarouselInfoByIds(String[] ids) { + return playCarouselInfoMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除店铺首页轮播信息 + * + * @param id + * 店铺首页轮播主键 + * @return 结果 + */ + @Override + public int deletePlayCarouselInfoById(String id) { + return playCarouselInfoMapper.deleteById(id); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/shop/service/impl/ShopUiSettingServiceImpl.java --- +package com.starry.admin.modules.shop.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.starry.admin.modules.shop.mapper.ShopUiSettingMapper; +import com.starry.admin.modules.shop.module.entity.ShopUiSettingEntity; +import com.starry.admin.modules.shop.service.IShopUiSettingService; +import java.util.Objects; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 店铺设置Service业务层处理 + * + * @author admin + * @since 2025-06-11 + */ +@Service +public class ShopUiSettingServiceImpl extends ServiceImpl + implements + IShopUiSettingService { + @Resource + private ShopUiSettingMapper shopUiSettingMapper; + + /** + * 查询店铺设置 + * + * @return 店铺设置 + */ + @Override + public ShopUiSettingEntity selectShopUiSettingInfo() { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(ShopUiSettingEntity.class); + ShopUiSettingEntity setting = this.baseMapper.selectOne(wrapper, false); + if (Objects.nonNull(setting)) { + return setting; + } else { + setting = new ShopUiSettingEntity(); + setting.setSettingConfig(null); + this.baseMapper.insert(setting); + } + return setting; + } + + /** + * 修改店铺设置 + * + * @param shopUiSetting + * 店铺设置 + * @return 结果 + */ + @Override + public boolean update(ShopUiSettingEntity shopUiSetting) { + return updateById(shopUiSetting); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/statistics/controller/PlayClerkPerformanceController.java --- +package com.starry.admin.modules.statistics.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.modules.clerk.module.entity.PlayClerkLevelInfoEntity; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity; +import com.starry.admin.modules.clerk.service.IPlayClerkLevelInfoService; +import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService; +import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity; +import com.starry.admin.modules.order.service.IPlayOrderInfoService; +import com.starry.admin.modules.personnel.module.entity.PlayPersonnelGroupInfoEntity; +import com.starry.admin.modules.personnel.service.IPlayPersonnelGroupInfoService; +import com.starry.admin.modules.statistics.module.vo.PlayClerkPerformanceInfoQueryVo; +import com.starry.admin.modules.statistics.module.vo.PlayClerkPerformanceInfoReturnVo; +import com.starry.admin.modules.statistics.service.IPlayClerkPerformanceService; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.temporal.TemporalAdjusters; +import java.util.*; +import java.util.stream.Collectors; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 店员业绩查询对 + * + * @author admin + * @since 2024/6/15 下午3:15 + **/ +@Api(tags = "店员业绩统计", description = "店员业绩统计相关接口,包括按日期、月份查询等操作") +@RestController +@RequestMapping("/statistics/performance") +public class PlayClerkPerformanceController { + + @Resource + private IPlayClerkUserInfoService clerkUserInfoService; + + @Resource + private IPlayOrderInfoService playOrderInfoService; + + @Resource + private IPlayClerkLevelInfoService playClerkLevelInfoService; + + @Resource + private IPlayPersonnelGroupInfoService playPersonnelGroupInfoService; + + @Resource + private IPlayClerkPerformanceService playClerkPerformanceService; + + @ApiOperation(value = "分页查询店员业绩", notes = "分页查询店员业绩统计信息") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayClerkPerformanceInfoReturnVo.class, responseContainer = "Page")}) + @PostMapping("/listByPage") + public R listByPage( + @ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayClerkPerformanceInfoQueryVo vo) { + IPage page = clerkUserInfoService.selectByPage(vo); + IPage voPage = page.convert(u -> { + List clerkLevelInfoEntity = playClerkLevelInfoService.selectAll(); + String startTime = vo.getEndOrderTime() != null ? vo.getEndOrderTime().get(0) : ""; + String endTime = vo.getEndOrderTime() != null ? vo.getEndOrderTime().get(1) : ""; + List orderInfoEntities = playOrderInfoService.clerkSelectOrderInfoList(u.getId(), + startTime, endTime); + List groupInfoEntities = playPersonnelGroupInfoService.selectAll(); + return playClerkPerformanceService.getClerkPerformanceInfo(u, orderInfoEntities, clerkLevelInfoEntity, + groupInfoEntities); + }); + voPage.setRecords(voPage.getRecords().stream() + .sorted(Comparator.comparing(PlayClerkPerformanceInfoReturnVo::getOrderNumber).reversed()) + .collect(Collectors.toList())); + return R.ok(voPage); + } + + @ApiOperation(value = "按日查询业绩", notes = "按日期查询店员业绩统计信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @PostMapping("/listByTime") + public R listByTime( + @ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayClerkPerformanceInfoQueryVo vo) { + // 时间范围 + List dates = getDateRangeByDay(vo.getEndOrderTime().get(0), vo.getEndOrderTime().get(1)); + // 指定时间内所有订单 + // List orderInfoEntities = + // playOrderInfoService.listByTime("", vo.getEndOrderTime().get(0), + // vo.getEndOrderTime().get(1), Stream.of("2", + // "3").collect(Collectors.toList())); + List orderInfoEntities = playOrderInfoService.listByTime("", vo.getEndOrderTime().get(0), + vo.getEndOrderTime().get(1), new ArrayList<>()); + List orders = new ArrayList<>(dates.size()); + for (String date : dates) { + orders.add(getPerformanceInfo(date, orderInfoEntities)); + } + Map resultMap = new HashMap<>(orders.size()); + resultMap.put("dates", dates); + resultMap.put("orderToTal", getTotalInfo(orderInfoEntities)); + resultMap.put("list", orders); + return R.ok(resultMap); + } + + @ApiOperation(value = "按月查询业绩", notes = "按月份查询店员业绩统计信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @PostMapping("/listByMonth") + public R listByMonth( + @ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayClerkPerformanceInfoQueryVo vo) { + String startTime = LocalDate.of(Integer.parseInt(vo.getEndOrderTime().get(0).split("-")[0]), + Integer.parseInt(vo.getEndOrderTime().get(0).split("-")[1]), 1).toString() + " 00:00:00"; + LocalDate endDate = LocalDate.of(Integer.parseInt(vo.getEndOrderTime().get(1).split("-")[0]), + Integer.parseInt(vo.getEndOrderTime().get(1).split("-")[1]), 1); + String endTime = endDate.with(TemporalAdjusters.lastDayOfMonth()) + " 23:59:59"; + + List dates = getDateRangeByMonth(startTime, endTime); + // 指定时间内所有订单 + // List orderInfoEntities = + // playOrderInfoService.listByTime("", startTime, endTime, + // Stream.of("4").collect(Collectors.toList())); + List orderInfoEntities = playOrderInfoService.listByTime("", startTime, endTime, + new ArrayList<>()); + List orders = new ArrayList<>(dates.size()); + for (String date : dates) { + orders.add(getPerformanceInfo(date, orderInfoEntities)); + } + Map resultMap = new HashMap<>(orders.size()); + resultMap.put("dates", dates); + resultMap.put("orderToTal", getTotalInfo(orderInfoEntities)); + resultMap.put("list", orders); + return R.ok(resultMap); + } + + /** + * 根据订单开始时间和结束时间,组装订单统计信息的查询时间范围 + * + * @param startTime + * 开始时间 + * @param endTime + * 结束时间 + * @return 时间范围 + */ + public List getDateRangeByDay(String startTime, String endTime) { + List dates = new ArrayList<>(); + LocalDateTime date1 = LocalDateTime.parse(startTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + LocalDateTime date2 = LocalDateTime.parse(endTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + while (!date1.isAfter(date2)) { + dates.add(date1.toLocalDate().toString()); + date1 = date1.plusDays(1); + + } + return dates; + } + + /** + * 根据订单开始时间和结束时间,组装订单统计信息的查询时间范围 + * + * @param startTime + * 开始时间 + * @param endTime + * 结束时间 + * @return 时间范围 + */ + public List getDateRangeByMonth(String startTime, String endTime) { + List dates = new ArrayList<>(); + LocalDateTime date1 = LocalDateTime.parse(startTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + LocalDateTime date2 = LocalDateTime.parse(endTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + while (!date1.isAfter(date2)) { + dates.add(date1.getYear() + "-" + date1.getMonthValue()); + date1 = date1.plusMonths(1); + + } + return dates; + } + + public PlayClerkPerformanceInfoReturnVo getTotalInfo(List orderInfoEntities) { + Set customIds = new HashSet<>(); + int orderContinueNumber = 0; + int orderRefundNumber = 0; + int ordersExpiredNumber = 0; + BigDecimal orderMoney = BigDecimal.ZERO; + BigDecimal finalAmount = BigDecimal.ZERO; + BigDecimal orderFirstAmount = BigDecimal.ZERO; + BigDecimal orderTotalAmount = BigDecimal.ZERO; + BigDecimal orderRewardAmount = BigDecimal.ZERO; + BigDecimal orderRefundAmount = BigDecimal.ZERO; + BigDecimal estimatedRevenue = BigDecimal.ZERO; + for (PlayOrderInfoEntity orderInfoEntity : orderInfoEntities) { + customIds.add(orderInfoEntity.getPurchaserBy()); + finalAmount = finalAmount.add(orderInfoEntity.getFinalAmount()); + orderMoney = orderMoney.add(orderInfoEntity.getOrderMoney()); + if ("1".equals(orderInfoEntity.getFirstOrder())) { + orderFirstAmount = orderFirstAmount.add(orderInfoEntity.getFinalAmount()); + } else { + orderContinueNumber++; + orderTotalAmount = orderTotalAmount.add(orderInfoEntity.getFinalAmount()); + } + if ("2".equals(orderInfoEntity.getPlaceType())) { + orderRewardAmount = orderRewardAmount.add(orderInfoEntity.getFinalAmount()); + } + if ("1".equals(orderInfoEntity.getRefundType())) { + orderRefundNumber++; + orderRefundAmount = orderRefundAmount.add(orderInfoEntity.getRefundAmount()); + } + if ("1".equals(orderInfoEntity.getOrdersExpiredState())) { + ordersExpiredNumber++; + } + } + PlayClerkPerformanceInfoReturnVo returnVo = new PlayClerkPerformanceInfoReturnVo(); + returnVo.setOrderNumber(orderInfoEntities.size()); + returnVo.setOrderContinueNumber(orderContinueNumber); + returnVo.setOrderRefundNumber(orderRefundNumber); + returnVo.setOrdersExpiredNumber(ordersExpiredNumber); + returnVo.setFinalAmount(finalAmount); + returnVo.setOrderFirstAmount(orderFirstAmount); + returnVo.setOrderTotalAmount(orderTotalAmount); + returnVo.setOrderRewardAmount(orderRewardAmount); + returnVo.setOrderRefundAmount(orderRefundAmount); + returnVo.setCustomNumber(customIds.size()); + returnVo.setEstimatedRevenue(estimatedRevenue); + returnVo.setOrderMoney(estimatedRevenue); + return returnVo; + } + /** + * 组装统计数据 + * + * @param performanceDate + * 统计时间 + * @param orderInfoEntities + * 订单列表 + * @return 统计数据 + */ + + public PlayClerkPerformanceInfoReturnVo getPerformanceInfo(String performanceDate, + List orderInfoEntities) { + + List itemOrderInfo = new ArrayList<>(); + for (PlayOrderInfoEntity orderInfoEntity : orderInfoEntities) { + // 接单时间,在指定日期的 00:00:00点到23:59:59之间 + if (orderInfoEntity.getPurchaserTime() + .isAfter(LocalDateTime.parse(performanceDate + " 00:00:00", + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))) + && orderInfoEntity.getPurchaserTime().isBefore(LocalDateTime.parse(performanceDate + " 23:59:59", + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))) { + itemOrderInfo.add(orderInfoEntity); + } + } + + Set customIds = new HashSet<>(); + int orderContinueNumber = 0; + int orderRefundNumber = 0; + int ordersExpiredNumber = 0; + BigDecimal orderMoney = BigDecimal.ZERO; + BigDecimal finalAmount = BigDecimal.ZERO; + BigDecimal orderFirstAmount = BigDecimal.ZERO; + BigDecimal orderTotalAmount = BigDecimal.ZERO; + BigDecimal orderRewardAmount = BigDecimal.ZERO; + BigDecimal orderRefundAmount = BigDecimal.ZERO; + BigDecimal estimatedRevenue = BigDecimal.ZERO; + for (PlayOrderInfoEntity orderInfoEntity : itemOrderInfo) { + customIds.add(orderInfoEntity.getPurchaserBy()); + finalAmount = finalAmount.add(orderInfoEntity.getFinalAmount()); + orderMoney = orderMoney.add(orderInfoEntity.getOrderMoney()); + if ("1".equals(orderInfoEntity.getFirstOrder())) { + orderFirstAmount = orderFirstAmount.add(orderInfoEntity.getFinalAmount()); + } else { + orderContinueNumber++; + orderTotalAmount = orderTotalAmount.add(orderInfoEntity.getFinalAmount()); + } + if ("2".equals(orderInfoEntity.getPlaceType())) { + orderRewardAmount = orderRewardAmount.add(orderInfoEntity.getFinalAmount()); + } + if ("1".equals(orderInfoEntity.getRefundType())) { + orderRefundNumber++; + orderRefundAmount = orderRefundAmount.add(orderInfoEntity.getRefundAmount()); + } + if ("1".equals(orderInfoEntity.getOrdersExpiredState())) { + ordersExpiredNumber++; + } + } + PlayClerkPerformanceInfoReturnVo returnVo = new PlayClerkPerformanceInfoReturnVo(); + returnVo.setPerformanceDate(performanceDate); + returnVo.setOrderNumber(itemOrderInfo.size()); + returnVo.setOrderContinueNumber(orderContinueNumber); + returnVo.setOrderRefundNumber(orderRefundNumber); + returnVo.setOrdersExpiredNumber(ordersExpiredNumber); + returnVo.setFinalAmount(finalAmount); + returnVo.setOrderFirstAmount(orderFirstAmount); + returnVo.setOrderTotalAmount(orderTotalAmount); + returnVo.setOrderRewardAmount(orderRewardAmount); + returnVo.setOrderRefundAmount(orderRefundAmount); + returnVo.setCustomNumber(customIds.size()); + returnVo.setEstimatedRevenue(estimatedRevenue); + returnVo.setOrderMoney(estimatedRevenue); + return returnVo; + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/statistics/module/vo/PlayClerkPerformanceInfoQueryVo.java --- +package com.starry.admin.modules.statistics.module.vo; + +import com.starry.common.domain.BasePageEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @author admin + * @since 2024/6/10 下午8:58 + **/ +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel(value = "店员业绩查询参数", description = "查询店员业绩统计信息的条件参数") +public class PlayClerkPerformanceInfoQueryVo extends BasePageEntity { + + /** + * 分组ID + */ + @ApiModelProperty(value = "分组ID", example = "1", notes = "店员所属分组ID") + private String groupId; + + /** + * 店员ID + */ + @ApiModelProperty(value = "店员ID", example = "1", notes = "店员ID") + private String clerkId; + + /** + * 店员性别 + */ + @ApiModelProperty(value = "店员性别", example = "1", notes = "店员性别,1男2女") + private String sex; + + /** + * 店员上架状态 + */ + @ApiModelProperty(value = "上架状态", example = "1", notes = "店员上架状态,1上架0下架") + private String listingState; + + /** + * 订单状态ID + */ + @ApiModelProperty(value = "订单状态", example = "[\"1\",\"2\"]", notes = "订单状态ID列表") + private List orderStatus; + /** + * 完成订单时间 + */ + @ApiModelProperty(value = "订单时间范围", example = "[\"2024-01-01 00:00:00\",\"2024-12-31 23:59:59\"]", notes = "订单开始和结束时间") + private List endOrderTime; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/statistics/module/vo/PlayClerkPerformanceInfoReturnVo.java --- +package com.starry.admin.modules.statistics.module.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.math.BigDecimal; +import lombok.Data; + +/** + * @author admin + * @since 2024/6/10 下午8:58 + **/ +@Data +@ApiModel(value = "店员业绩返回数据", description = "店员业绩统计信息的返回数据") +public class PlayClerkPerformanceInfoReturnVo { + + /** + * 店员ID + */ + @ApiModelProperty(value = "店员ID", example = "1") + private String clerkId; + + /** + * 店员昵称 + */ + @ApiModelProperty(value = "店员昵称", example = "张三") + private String clerkNickname; + + /** + * 店员昵称 + */ + @ApiModelProperty(value = "店员性别", example = "1", notes = "1男2女") + private String clerkSex; + /** + * 分组名称 + */ + @ApiModelProperty(value = "分组名称", example = "销售组") + private String groupName = ""; + /** + * 分组名称 + */ + @ApiModelProperty(value = "等级名称", example = "初级") + private String levelName = ""; + /** + * 在线时长 + */ + @ApiModelProperty(value = "在线时长", example = "120", notes = "单位:分钟") + private Integer onlineDuration = 0; + /** + * 订单总数 + */ + @ApiModelProperty(value = "订单总数", example = "10") + private Integer orderNumber = 0; + /** + * 首单数 + */ + @ApiModelProperty(value = "首单数", example = "5") + private Integer orderFirstNumber = 0; + /** + * 续单数 + */ + @ApiModelProperty(value = "续单数", example = "5") + private Integer orderContinueNumber = 0; + /** + * 退款单数 + */ + @ApiModelProperty(value = "退款单数", example = "1") + private Integer orderRefundNumber = 0; + /** + * 超时未接单数 + */ + @ApiModelProperty(value = "超时未接单数", example = "1") + private Integer ordersExpiredNumber = 0; + + /** + * 订单金额 + */ + @ApiModelProperty(value = "订单金额", example = "1000.00") + private BigDecimal orderMoney; + + /** + * 订单最终金额(支付金额) + */ + @ApiModelProperty(value = "支付金额", example = "900.00", notes = "订单最终金额(支付金额)") + private BigDecimal finalAmount = BigDecimal.ZERO; + + /** + * 充值金额 + */ + @ApiModelProperty(value = "充值金额", example = "500.00") + private BigDecimal rechargeAmount = BigDecimal.ZERO; + /** + * 首单金额 + */ + @ApiModelProperty(value = "首单金额", example = "300.00") + private BigDecimal orderFirstAmount = BigDecimal.ZERO; + /** + * 续单金额 + */ + @ApiModelProperty(value = "续单金额", example = "600.00") + private BigDecimal orderTotalAmount = BigDecimal.ZERO; + /** + * 打赏金额 + */ + @ApiModelProperty(value = "打赏金额", example = "100.00") + private BigDecimal orderRewardAmount = BigDecimal.ZERO; + /** + * 退款金额 + */ + @ApiModelProperty(value = "退款金额", example = "50.00") + private BigDecimal orderRefundAmount = BigDecimal.ZERO; + /** + * 用户数 + */ + @ApiModelProperty(value = "用户数", example = "8") + private Integer customNumber = 0; + + /** + * 连续用户数 + */ + @ApiModelProperty(value = "连续用户数", example = "3") + private final Integer continuousCustomNumber = 0; + /** + * 续单比例 + */ + @ApiModelProperty(value = "续单比例", example = "0.5", notes = "续单数/订单总数") + private final BigDecimal orderContinueProportion = BigDecimal.ZERO; + /** + * 订单平均价格 + */ + @ApiModelProperty(value = "订单平均价格", example = "90.00") + private final BigDecimal averageUnitPrice = BigDecimal.ZERO; + + /** + * 续费率 + */ + @ApiModelProperty(value = "续费率", example = "0.6") + private BigDecimal orderContinueRechargeProportion = BigDecimal.ZERO; + /** + * 退单率 + */ + @ApiModelProperty(value = "退单率", example = "0.1") + private BigDecimal orderChargebackProportion = BigDecimal.ZERO; + /** + * 续客率 + */ + @ApiModelProperty(value = "续客率", example = "0.4") + private BigDecimal continuousCustomProportion = BigDecimal.ZERO; + /** + * 店员预计收入 + */ + @ApiModelProperty(value = "预计收入", example = "450.00") + private BigDecimal estimatedRevenue = BigDecimal.ZERO; + + /** + * 统计时间 + */ + @ApiModelProperty(value = "统计时间", example = "2024-06-01") + private String performanceDate; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/statistics/service/IPlayClerkPerformanceService.java --- +package com.starry.admin.modules.statistics.service; + +import com.starry.admin.modules.clerk.module.entity.PlayClerkLevelInfoEntity; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity; +import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity; +import com.starry.admin.modules.personnel.module.entity.PlayPersonnelGroupInfoEntity; +import com.starry.admin.modules.statistics.module.vo.PlayClerkPerformanceInfoReturnVo; +import java.util.List; + +/** + * @author admin + * @since 2024/6/15 下午3:29 + **/ +public interface IPlayClerkPerformanceService { + + /** + * 根据店员订单ID,生成店员业绩信息 + * + * @param userInfo + * 店员信息 + * @param orderInfoEntities + * 店员订单列表 + * @param clerkLevelInfoEntity + * 店员等级信息 + * @param groupInfoEntities + * 店员分组信息 + * @return 业绩信息 + */ + PlayClerkPerformanceInfoReturnVo getClerkPerformanceInfo(PlayClerkUserInfoEntity userInfo, + List orderInfoEntities, List clerkLevelInfoEntity, + List groupInfoEntities); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/statistics/service/impl/PlayClerkPerformanceServiceImpl.java --- +package com.starry.admin.modules.statistics.service.impl; + +import com.starry.admin.modules.clerk.module.entity.PlayClerkLevelInfoEntity; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity; +import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity; +import com.starry.admin.modules.personnel.module.entity.PlayPersonnelGroupInfoEntity; +import com.starry.admin.modules.statistics.module.vo.PlayClerkPerformanceInfoReturnVo; +import com.starry.admin.modules.statistics.service.IPlayClerkPerformanceService; +import java.math.BigDecimal; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.springframework.stereotype.Service; + +/** + * @author admin + * @since 2024/6/15 下午3:29 + **/ +@Service +public class PlayClerkPerformanceServiceImpl implements IPlayClerkPerformanceService { + + @Override + public PlayClerkPerformanceInfoReturnVo getClerkPerformanceInfo(PlayClerkUserInfoEntity userInfo, + List orderInfoEntities, List clerkLevelInfoEntities, + List groupInfoEntities) { + + Set customIds = new HashSet<>(); + int orderContinueNumber = 0; + int orderRefundNumber = 0; + int ordersExpiredNumber = 0; + BigDecimal finalAmount = BigDecimal.ZERO; + BigDecimal orderFirstAmount = BigDecimal.ZERO; + BigDecimal orderTotalAmount = BigDecimal.ZERO; + BigDecimal orderRewardAmount = BigDecimal.ZERO; + BigDecimal orderRefundAmount = BigDecimal.ZERO; + BigDecimal estimatedRevenue = BigDecimal.ZERO; + for (PlayOrderInfoEntity orderInfoEntity : orderInfoEntities) { + customIds.add(orderInfoEntity.getPurchaserBy()); + finalAmount = finalAmount.add(orderInfoEntity.getFinalAmount()); + if ("1".equals(orderInfoEntity.getFirstOrder())) { + orderFirstAmount = orderFirstAmount.add(orderInfoEntity.getFinalAmount()); + } else { + orderContinueNumber++; + orderTotalAmount = orderTotalAmount.add(orderInfoEntity.getFinalAmount()); + } + if ("2".equals(orderInfoEntity.getPlaceType())) { + orderRewardAmount = orderRewardAmount.add(orderInfoEntity.getFinalAmount()); + } + if ("1".equals(orderInfoEntity.getRefundType())) { + orderRefundNumber++; + orderRefundAmount = orderRefundAmount.add(orderInfoEntity.getRefundAmount()); + } + if ("1".equals(orderInfoEntity.getOrdersExpiredState())) { + ordersExpiredNumber++; + } + } + PlayClerkPerformanceInfoReturnVo returnVo = new PlayClerkPerformanceInfoReturnVo(); + returnVo.setClerkId(userInfo.getId()); + returnVo.setClerkNickname(userInfo.getNickname()); + returnVo.setClerkSex(userInfo.getSex()); + for (PlayClerkLevelInfoEntity infoEntity : clerkLevelInfoEntities) { + if (infoEntity.getId().equals(userInfo.getLevelId())) { + returnVo.setLevelName(infoEntity.getName()); + } + } + for (PlayPersonnelGroupInfoEntity infoEntity : groupInfoEntities) { + if (infoEntity.getId().equals(userInfo.getGroupId())) { + returnVo.setGroupName(infoEntity.getGroupName()); + } + } + returnVo.setOrderNumber(orderInfoEntities.size()); + returnVo.setOrderContinueNumber(orderContinueNumber); + returnVo.setOrderRefundNumber(orderRefundNumber); + returnVo.setOrdersExpiredNumber(ordersExpiredNumber); + returnVo.setFinalAmount(finalAmount); + returnVo.setOrderFirstAmount(orderFirstAmount); + returnVo.setOrderTotalAmount(orderTotalAmount); + returnVo.setOrderRewardAmount(orderRewardAmount); + returnVo.setOrderRefundAmount(orderRefundAmount); + returnVo.setCustomNumber(customIds.size()); + returnVo.setEstimatedRevenue(estimatedRevenue); + + return returnVo; + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/controller/AdministrativeAreaDictInfoController.java --- +package com.starry.admin.modules.system.controller; + +import com.starry.admin.modules.system.service.ISysAdministrativeAreaDictInfoService; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import javax.annotation.Resource; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 行政区域字典信息Controller + * + * @author admin + * @since 2024-04-03 + */ +@Api(tags = "行政区域字典", description = "行政区域字典信息相关接口") +@RestController +@RequestMapping("/sys/area") +public class AdministrativeAreaDictInfoController { + @Resource + private ISysAdministrativeAreaDictInfoService playAdministrativeAreaDictInfoService; + + /** + * 查询省/市行政区域代码 + */ + @ApiOperation(value = "获取行政区域树", notes = "查询省/市行政区域代码的树形结构") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @PreAuthorize("@customSs.hasPermission('play:info:list')") + @GetMapping("/tree") + public R list() throws Exception { + return R.ok(playAdministrativeAreaDictInfoService.selectTree("2")); + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/controller/CacheController.java --- +package com.starry.admin.modules.system.controller; + +import com.starry.admin.modules.system.module.entity.Cache; +import com.starry.common.constant.CacheConstants; +import com.starry.common.result.R; +import com.starry.common.utils.StringUtils; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.util.*; +import javax.annotation.Resource; +import org.springframework.data.redis.connection.RedisServerCommands; +import org.springframework.data.redis.core.RedisCallback; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +/** + * @author huoqiang 缓存监控 + * @since 2022/10/17 + */ +@Api(tags = "缓存监控", description = "系统缓存监控相关接口") +@RestController +@RequestMapping("/monitor/cache") +public class CacheController { + + private final static List CACHES = new ArrayList<>(); + @Resource + private RedisTemplate redisTemplate; + + { + CACHES.add(new Cache(CacheConstants.LOGIN_TOKEN_KEY, "用户信息")); + CACHES.add(new Cache(CacheConstants.SYS_DICT_KEY, "数据字典")); + CACHES.add(new Cache(CacheConstants.CAPTCHA_CODE_KEY, "验证码")); + } + + @ApiOperation(value = "获取缓存信息", notes = "获取Redis服务器信息和命令统计") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Map.class)}) + @PreAuthorize("@customSs.hasPermission('monitor:cache:list')") + @GetMapping() + public R getInfo() throws Exception { + Properties info = (Properties) redisTemplate.execute((RedisCallback) RedisServerCommands::info); + Properties commandStats = (Properties) redisTemplate + .execute((RedisCallback) connection -> connection.info("commandstats")); + Object dbSize = redisTemplate.execute((RedisCallback) RedisServerCommands::dbSize); + + Map result = new HashMap<>(3); + result.put("info", info); + result.put("dbSize", dbSize); + List> pieList = new ArrayList<>(); + commandStats.stringPropertyNames().forEach(key -> { + Map data = new HashMap<>(2); + String property = commandStats.getProperty(key); + data.put("name", StringUtils.removeStart(key, "cmdstat_")); + data.put("value", StringUtils.substringBetween(property, "calls=", ",usec")); + pieList.add(data); + }); + result.put("commandStats", pieList); + return R.ok(result); + } + + @ApiOperation(value = "获取缓存名称", notes = "获取系统中所有缓存分类名称") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Cache.class, responseContainer = "List")}) + @PreAuthorize("@customSs.hasPermission('monitor:cache:list')") + @GetMapping("/getNames") + public R cache() { + return R.ok(CACHES); + } + + @ApiOperation(value = "获取缓存键名", notes = "根据缓存名称获取对应的所有缓存键") + @ApiImplicitParam(name = "cacheName", value = "缓存名称", required = true, dataType = "String", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = String.class, responseContainer = "Set")}) + @PreAuthorize("@customSs.hasPermission('monitor:cache:list')") + @GetMapping("/getKeys/{cacheName}") + public R getCacheKeys(@PathVariable String cacheName) { + Set cacheKeys = redisTemplate.keys(cacheName + "*"); + return R.ok(cacheKeys); + } + + @ApiOperation(value = "获取缓存值", notes = "根据缓存名称和键名获取缓存值") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Cache.class)}) + @PreAuthorize("@customSs.hasPermission('monitor:cache:list')") + @GetMapping("/getValue/{cacheName}/{cacheKey}") + public R getCacheValue(@PathVariable String cacheName, @PathVariable String cacheKey) { + String cacheValue = redisTemplate.opsForValue().get(cacheKey); + Cache cache = new Cache(cacheName, cacheKey, cacheValue); + return R.ok(cache); + } + + @ApiOperation(value = "清除缓存名称", notes = "清除指定缓存名称下的所有缓存") + @ApiImplicitParam(name = "cacheName", value = "缓存名称", required = true, dataType = "String", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @PreAuthorize("@customSs.hasPermission('monitor:cache:list')") + @DeleteMapping("/clearCacheName/{cacheName}") + public R clearCacheName(@PathVariable String cacheName) { + Collection cacheKeys = redisTemplate.keys(cacheName + "*"); + redisTemplate.delete(cacheKeys); + return R.ok(); + } + + @ApiOperation(value = "清除缓存键", notes = "清除指定的缓存键") + @ApiImplicitParam(name = "cacheKey", value = "缓存键", required = true, dataType = "String", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @PreAuthorize("@customSs.hasPermission('monitor:cache:list')") + @DeleteMapping("/clearCacheKey/{cacheKey}") + public R clearCacheKey(@PathVariable String cacheKey) { + redisTemplate.delete(cacheKey); + return R.ok(); + } + + @ApiOperation(value = "清除所有缓存", notes = "清除系统中所有缓存数据") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @PreAuthorize("@customSs.hasPermission('monitor:cache:list')") + @DeleteMapping("/clearCacheAll") + public R clearCacheAll() { + Collection cacheKeys = redisTemplate.keys("*"); + redisTemplate.delete(cacheKeys); + return R.ok(); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/controller/HealthController.java --- +package com.starry.admin.modules.system.controller; + +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.HashMap; +import java.util.Map; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * Health Check Controller + * + * @author admin + * @since 2025/08/30 + */ +@Api(tags = "健康检查", description = "服务健康状态检查接口") +@RestController +@RequestMapping("/health") +public class HealthController { + + @ApiOperation(value = "健康检查", notes = "检查服务是否正常运行") + @ApiResponses({@ApiResponse(code = 200, message = "服务正常运行")}) + @GetMapping + public R health() { + Map data = new HashMap<>(); + data.put("status", "UP"); + data.put("message", "Hello, I'm alive!"); + data.put("timestamp", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + data.put("service", "peipei-backend"); + return R.ok(data); + } + + @ApiOperation(value = "简单检查", notes = "最简单的存活检查") + @ApiResponses({@ApiResponse(code = 200, message = "服务正常")}) + @GetMapping("/ping") + public R ping() { + return R.ok("pong"); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/controller/LoginController.java --- +package com.starry.admin.modules.system.controller; + +import com.starry.admin.common.component.JwtToken; +import com.starry.admin.common.domain.LoginUser; +import com.starry.admin.modules.system.module.entity.SysMenuEntity; +import com.starry.admin.modules.system.module.entity.SysUserEntity; +import com.starry.admin.modules.system.service.LoginService; +import com.starry.admin.modules.system.service.SysMenuService; +import com.starry.admin.modules.system.vo.LoginVo; +import com.starry.admin.modules.system.vo.RouterVo; +import com.starry.admin.utils.SecurityUtils; +import com.starry.common.redis.CaptchaService; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.annotation.Resource; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author admin + */ +@Api(tags = "登录管理", description = "用户登录及认证相关接口") +@RestController +public class LoginController { + + @Value("${jwt.tokenHead}") + private String tokenHead; + @Value(value = "${xl.login.authCode.enable}") + private boolean needAuthCode; + @Resource + private LoginService loginService; + @Resource + private SysMenuService menuService; + @Resource + private CaptchaService captchaService; + @Resource + private JwtToken jwtToken; + + @ApiOperation(value = "旧版登录", notes = "用户登录接口,返回Token") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Map.class), + @ApiResponse(code = 500, message = "登录失败,用户名或密码错误")}) + @PostMapping(value = "old-login") + public R login(@ApiParam(value = "登录信息", required = true) @RequestBody LoginVo loginVo) { + // 只有开启了验证码功能才需要验证 + if (needAuthCode) { + String msg = captchaService.checkImageCode(loginVo.getNonceStr(), loginVo.getValue()); + if (StringUtils.isNotBlank(msg)) { + return R.error(msg); + } + } + String token = loginService.login(loginVo.getUserName(), loginVo.getPassWord()); + if (StringUtils.isBlank(token)) { + return R.error("用户名或密码错误"); + } + Map tokenMap = new HashMap<>(); + tokenMap.put("token", token); + tokenMap.put("tokenHead", tokenHead); + return R.ok(tokenMap); + } + + @ApiOperation(value = "获取用户信息", notes = "登录后获取当前用户的详细信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Map.class), + @ApiResponse(code = 401, message = "未授权")}) + @GetMapping("get-info") + public R getInfo() { + SysUserEntity user = SecurityUtils.getLoginUser().getUser(); + if (user == null) { + return R.unauthorized(); + } + // 权限集合 + Set permissions = loginService.getMenuPermission(user); + // 角色集合 + Set roles = loginService.getRolePermission(user); + Map data = new HashMap<>(); + data.put("userCode", user.getUserCode()); + data.put("name", user.getRealName()); + data.put("avatar", user.getAvatar()); + data.put("roles", roles); + data.put("permissions", permissions); + return R.ok(data); + } + + @ApiOperation(value = "获取路由信息", notes = "登录后获取当前用户的菜单路由信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = RouterVo.class, responseContainer = "List")}) + @GetMapping("get-routers") + public R getRoutes() { + List menus = menuService.selectMenuTreeByUserId(SecurityUtils.getUserId()); + List routerVos = menuService.buildMenus(menus); + return R.ok(routerVos); + } + + @ApiOperation(value = "新版登录", notes = "新版用户登录接口,支持租户") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Map.class), + @ApiResponse(code = 500, message = "登录失败,验证码错误或用户名密码错误")}) + @PostMapping(value = "login") + public R newLogin(@ApiParam(value = "登录信息", required = true) @RequestBody LoginVo loginVo) { + // 只有开启了验证码功能才需要验证 + if (needAuthCode) { + String msg = captchaService.checkImageCode(loginVo.getNonceStr(), loginVo.getValue()); + if (StringUtils.isNotBlank(msg)) { + return R.error(msg); + } + } + // 用户登录 + LoginUser userInfo = loginService.newLogin(loginVo.getUserName(), loginVo.getPassWord(), + loginVo.getTenantKey()); + Map tokenMap = jwtToken.createToken(userInfo); + return R.ok(tokenMap); + } + + // @ApiOperation(value = "租户登录") + // @PostMapping(value = "tenant/login") + // public R TenantLoginVo(@RequestBody TenantLoginVo loginVo) { + // // 只有开启了验证码功能才需要验证 + // if (needAuthCode) { + // String msg = captchaService.checkImageCode(loginVo.getNonceStr(), + // loginVo.getValue()); + // if (StringUtils.isNotBlank(msg)) { + // return R.error(msg); + // } + // } + // // 用户登录 + // LoginUser userInfo = loginService.tenantLogin(loginVo.getTenantkey(), + // loginVo.getUserName(), loginVo.getPassWord()); + // Map tokenMap = jwtToken.createToken(userInfo); + // return R.ok(tokenMap); + // } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/controller/ServerController.java --- +package com.starry.admin.modules.system.controller; + +import com.starry.admin.modules.system.module.entity.Server; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author huoqiang 服务器监控 + * @since 2022/10/17 + */ +@Api(tags = "服务器监控", description = "服务器状态监控相关接口") +@RestController +@RequestMapping("/monitor/server") +public class ServerController { + + @ApiOperation(value = "获取服务器信息", notes = "获取服务器运行状态、CPU、内存等信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Server.class)}) + @PreAuthorize("@customSs.hasPermission('monitor:server:list')") + @GetMapping() + public R getInfo() throws Exception { + Server server = new Server(); + server.setServeInfo(); + return R.ok(server); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/controller/SysDeptController.java --- +package com.starry.admin.modules.system.controller; + +import com.starry.admin.common.domain.TreeSelect; +import com.starry.admin.modules.system.module.entity.SysDeptEntity; +import com.starry.admin.modules.system.service.SysDeptService; +import com.starry.common.constant.UserConstants; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.util.Collections; +import java.util.List; +import javax.annotation.Resource; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +/** + *

+ * 部门表 前端控制器 + *

+ * + * @author admin + * @since 2022-07-12 + */ +@Api(tags = "部门管理", description = "系统部门相关接口") +@RestController +@RequestMapping("/ucenter/dept") +public class SysDeptController { + + @Resource + private SysDeptService deptService; + + @ApiOperation(value = "获取部门列表", notes = "根据条件查询部门列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = SysDeptEntity.class, responseContainer = "List")}) + @PreAuthorize("@customSs.hasPermission('system:dept:list')") + @GetMapping("/list") + public R list(@ApiParam(value = "查询条件") SysDeptEntity dept) { + List depts = deptService.selectDeptList(dept); + return R.ok(depts); + } + + @ApiOperation(value = "添加部门", notes = "创建新的部门") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "添加失败,部门名称已存在")}) + @PreAuthorize("@customSs.hasPermission('system:dept:create')") + @PostMapping("/create") + public R creat(@ApiParam(value = "部门信息", required = true) @RequestBody SysDeptEntity dept) { + if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept))) { + return R.error("新增部门'" + dept.getDeptName() + "'失败,部门名称已存在"); + } + boolean success = deptService.create(dept); + if (success) { + return R.ok(); + } + return R.error("添加失败"); + } + + @ApiOperation(value = "修改部门", notes = "根据ID修改部门信息") + @ApiImplicitParam(name = "id", value = "部门ID", required = true, dataType = "Long", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), + @ApiResponse(code = 500, message = "修改失败,部门名称已存在或上级部门不能是自己")}) + @PreAuthorize("@customSs.hasPermission('system:dept:edit')") + @PostMapping("/update/{id}") + public R update(@PathVariable Long id, @ApiParam(value = "部门信息", required = true) @RequestBody SysDeptEntity dept) { + dept.setDeptId(id); + if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept))) { + return R.error("修改部门'" + dept.getDeptName() + "'失败,部门名称已存在"); + } else if (dept.getParentId().equals(id)) { + return R.error("修改部门'" + dept.getDeptName() + "'失败,上级部门不能是自己"); + } + boolean success = deptService.update(dept); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + @ApiOperation(value = "删除部门", notes = "根据ID删除部门") + @ApiImplicitParam(name = "id", value = "部门ID", required = true, dataType = "Long", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "删除失败,存在下级部门")}) + @PreAuthorize("@customSs.hasPermission('system:dept:delete')") + @PostMapping(value = "/delete/{id}") + public R delete(@PathVariable("id") Long deptId) { + if (deptService.hasChildByDeptId(deptId)) { + return R.error("存在下级部门,不允许删除"); + } + boolean success = deptService.delete(Collections.singletonList(deptId)); + if (success) { + return R.ok(); + } + return R.error("删除失败"); + } + + @ApiOperation(value = "获取部门下拉树列表", notes = "获取部门的树形结构数据") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = TreeSelect.class, responseContainer = "List")}) + @GetMapping("/treeselect") + public R treeselect(@ApiParam(value = "查询条件") SysDeptEntity dept) { + List list = deptService.selectDeptList(dept); + List treeList = deptService.buildDeptTreeSelect(list); + return R.ok(treeList); + } + + @ApiOperation(value = "获取部门详情", notes = "根据部门ID获取详细信息") + @ApiImplicitParam(name = "deptId", value = "部门ID", required = true, dataType = "Long", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = SysDeptEntity.class)}) + @GetMapping(value = "/{deptId}") + public R getInfo(@PathVariable Long deptId) { + return R.ok(deptService.getById(deptId)); + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/controller/SysDictController.java --- +package com.starry.admin.modules.system.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.starry.admin.modules.system.module.entity.SysDictEntity; +import com.starry.admin.modules.system.service.ISysDictService; +import com.starry.admin.modules.system.vo.SysDictVo; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.util.List; +import javax.annotation.Resource; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +/** + * 字典表Controller + * + * @author admin + */ +@Api(tags = "字典类型管理", description = "系统字典类型相关接口") +@RestController +@RequestMapping("/system/dict") +public class SysDictController { + @Resource + private ISysDictService xlDictService; + + /** + * 查询字典表列表 + */ + @ApiOperation(value = "查询字典类型列表", notes = "分页查询字典类型列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = SysDictEntity.class, responseContainer = "Page")}) + @PreAuthorize("@customSs.hasPermission('system:dict:list')") + @GetMapping("/list") + public R list(@ApiParam(value = "查询条件") SysDictVo dictVo) { + Page list = xlDictService.selectXlDictList(dictVo); + return R.ok(list); + } + + /** + * 获取字典表详细信息 + */ + @ApiOperation(value = "获取字典类型详情", notes = "根据ID获取字典类型详细信息") + @ApiImplicitParam(name = "dictId", value = "字典ID", required = true, dataType = "Long", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = SysDictEntity.class)}) + @PreAuthorize("@customSs.hasPermission('system:dict:query')") + @GetMapping(value = "/{dictId}") + public R getInfo(@PathVariable("dictId") Long dictId) { + return R.ok(xlDictService.selectXlDictByDictId(dictId)); + } + + /** + * 新增字典表 + */ + @ApiOperation(value = "新增字典类型", notes = "创建新的字典类型") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "添加失败")}) + @PreAuthorize("@customSs.hasPermission('system:dict:create')") + @Log(title = "字典表", businessType = BusinessType.INSERT) + @PostMapping("/create") + public R create(@ApiParam(value = "字典类型信息", required = true) @RequestBody SysDictEntity sysDictEntity) { + boolean success = xlDictService.create(sysDictEntity); + if (success) { + return R.ok(); + } + return R.error("添加失败"); + } + + /** + * 修改字典表 + */ + @ApiOperation(value = "修改字典类型", notes = "根据ID修改字典类型") + @ApiImplicitParam(name = "dictId", value = "字典ID", required = true, dataType = "Long", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败")}) + @PreAuthorize("@customSs.hasPermission('system:dict:edit')") + @Log(title = "字典表", businessType = BusinessType.UPDATE) + @PostMapping(value = "/update/{dictId}") + public R update(@PathVariable Long dictId, + @ApiParam(value = "字典类型信息", required = true) @RequestBody SysDictEntity sysDictEntity) { + sysDictEntity.setDictId(dictId); + boolean success = xlDictService.update(sysDictEntity); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + /** + * 删除字典表 + */ + @ApiOperation(value = "删除字典类型", notes = "根据ID批量删除字典类型") + @ApiImplicitParam(name = "dictIds", value = "字典ID数组", required = true, dataType = "Long[]", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Boolean.class)}) + @PreAuthorize("@customSs.hasPermission('system:dict:remove')") + @Log(title = "字典表", businessType = BusinessType.DELETE) + @DeleteMapping("/{dictIds}") + public R remove(@PathVariable Long[] dictIds) { + return R.ok(xlDictService.deleteXlDictByDictIds(dictIds)); + } + + @ApiOperation(value = "获取字典选择列表", notes = "获取所有字典类型的下拉选择数据") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = SysDictEntity.class, responseContainer = "List")}) + @GetMapping("/optionselect") + public R optionselect() { + List list = xlDictService.selectDictTypeAll(); + return R.ok(list); + } + + /** + * 刷新字典缓存 + */ + @ApiOperation(value = "刷新字典缓存", notes = "清除并重新加载字典缓存") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @PreAuthorize("@customSs.hasPermission('system:dict:remove')") + @Log(title = "字典类型", businessType = BusinessType.CLEAN) + @DeleteMapping("/refreshCache") + public R refreshCache() { + xlDictService.resetDictCache(); + return R.ok(); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/controller/SysDictDataController.java --- +package com.starry.admin.modules.system.controller; + +import cn.hutool.core.collection.CollectionUtil; +import com.starry.admin.modules.system.module.entity.SysDictDataEntity; +import com.starry.admin.modules.system.service.ISysDictDataService; +import com.starry.admin.modules.system.vo.SysDictDataVo; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.util.ArrayList; +import java.util.List; +import javax.annotation.Resource; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +/** + * 字典数据表Controller + * + * @author admin + */ +@Api(tags = "字典数据管理", description = "系统字典数据项相关接口") +@RestController +@RequestMapping("/system/dict/data") +public class SysDictDataController { + @Resource + private ISysDictDataService xlDictDataService; + + /** + * 查询字典数据表列表 + */ + @ApiOperation(value = "查询字典数据列表", notes = "根据条件查询字典数据项列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = SysDictDataEntity.class, responseContainer = "Page")}) + @PreAuthorize("@customSs.hasPermission('system:dict:list')") + @GetMapping("/list") + public R list(@ApiParam(value = "查询条件") SysDictDataVo sysDictDataEntity) { + return R.ok(xlDictDataService.selectXlDictDataList(sysDictDataEntity)); + } + + /** + * 获取字典数据表详细信息 + */ + @ApiOperation(value = "获取字典数据详情", notes = "根据ID获取字典数据项详细信息") + @ApiImplicitParam(name = "dictDataId", value = "字典数据ID", required = true, dataType = "Long", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = SysDictDataEntity.class)}) + @PreAuthorize("@customSs.hasPermission('system:dict:query')") + @GetMapping(value = "/{dictDataId}") + public R getInfo(@PathVariable("dictDataId") Long dictDataId) { + return R.ok(xlDictDataService.selectXlDictDataByDictDataId(dictDataId)); + } + + /** + * 新增字典数据表 + */ + @ApiOperation(value = "新增字典数据", notes = "创建新的字典数据项") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "添加失败")}) + @PreAuthorize("@customSs.hasPermission('system:dict:create')") + @Log(title = "字典数据表", businessType = BusinessType.INSERT) + @PostMapping("/create") + public R create(@ApiParam(value = "字典数据信息", required = true) @RequestBody SysDictDataEntity sysDictDataEntity) { + boolean success = xlDictDataService.create(sysDictDataEntity); + if (success) { + return R.ok(); + } + return R.error("添加失败"); + } + + /** + * 修改字典数据表 + */ + @ApiOperation(value = "修改字典数据", notes = "根据ID修改字典数据项") + @ApiImplicitParam(name = "dictDataId", value = "字典数据ID", required = true, dataType = "Long", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败")}) + @PreAuthorize("@customSs.hasPermission('system:dict:edit')") + @Log(title = "字典数据表", businessType = BusinessType.UPDATE) + @PostMapping(value = "/update/{dictDataId}") + public R update(@PathVariable Long dictDataId, + @ApiParam(value = "字典数据信息", required = true) @RequestBody SysDictDataEntity sysDictDataEntity) { + sysDictDataEntity.setDictDataId(dictDataId); + boolean success = xlDictDataService.update(sysDictDataEntity); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + /** + * 删除字典数据表 + */ + @ApiOperation(value = "删除字典数据", notes = "根据ID批量删除字典数据项") + @ApiImplicitParam(name = "dictDataIds", value = "字典数据ID数组", required = true, dataType = "Long[]", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Boolean.class)}) + @PreAuthorize("@customSs.hasPermission('system:dict:remove')") + @Log(title = "字典数据表", businessType = BusinessType.DELETE) + @DeleteMapping("/{dictDataIds}") + public R remove(@PathVariable Long[] dictDataIds) { + return R.ok(xlDictDataService.deleteXlDictDataByDictDataIds(dictDataIds)); + } + + /** + * 根据字典类型查询字典数据信息 + */ + @ApiOperation(value = "根据类型查询字典数据", notes = "根据字典类型查询对应的字典数据项列表") + @ApiImplicitParam(name = "dictType", value = "字典类型", required = true, dataType = "String", paramType = "path") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = SysDictDataEntity.class, responseContainer = "List")}) + @GetMapping(value = "/type/{dictType}") + public R getDictDataByType(@PathVariable String dictType) { + List list = xlDictDataService.selectDictDataByType(dictType); + if (CollectionUtil.isEmpty(list)) { + list = new ArrayList<>(); + } + return R.ok(list); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/controller/SysLoginLogController.java --- +package com.starry.admin.modules.system.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.modules.system.module.entity.SysLoginLogEntity; +import com.starry.admin.modules.system.module.entity.SysLoginLogVo; +import com.starry.admin.modules.system.service.ISysLoginLogService; +import com.starry.admin.utils.ExcelUtils; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +/** + * 系统访问日志表Controller + * + * @author admin + */ +@Api(tags = "登录日志管理", description = "系统访问日志相关接口") +@RestController +@RequestMapping("/system/loginlog") +public class SysLoginLogController { + @Resource + private ISysLoginLogService xlLoginLogService; + + /** + * 查询系统访问日志表列表 + */ + @ApiOperation(value = "查询日志列表", notes = "分页查询系统访问日志列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = SysLoginLogEntity.class, responseContainer = "Page")}) + @PreAuthorize("@customSs.hasPermission('system:loginlog:list')") + @GetMapping("/list") + public R list(@ApiParam(value = "查询条件") SysLoginLogVo vo) { + IPage list = xlLoginLogService.selectXlLoginLogList(vo); + return R.ok(list); + } + + /** + * 导出系统访问日志表列表 + */ + @ApiOperation(value = "导出日志", notes = "导出系统访问日志表列表") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @PreAuthorize("@customSs.hasPermission('system:loginlog:export')") + @Log(title = "登录日志", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(HttpServletResponse response, @ApiParam(value = "查询条件") SysLoginLogVo vo) { + IPage list = xlLoginLogService.selectXlLoginLogList(vo); + ExcelUtils.exportEasyExcel(response, SysLoginLogEntity.class, list.getRecords(), "系统访问日志表数据"); + } + + /** + * 获取系统访问日志表详细信息 + */ + @ApiOperation(value = "获取日志详情", notes = "根据ID获取系统访问日志详细信息") + @ApiImplicitParam(name = "loginId", value = "日志ID", required = true, dataType = "Long", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = SysLoginLogEntity.class)}) + @PreAuthorize("@customSs.hasPermission('system:log:query')") + @GetMapping(value = "/{loginId}") + public R getInfo(@PathVariable("loginId") Long loginId) { + return R.ok(xlLoginLogService.selectXlLoginLogByLoginId(loginId)); + } + + /** + * 删除系统访问日志表 + */ + @ApiOperation(value = "删除日志", notes = "根据ID批量删除系统访问日志") + @ApiImplicitParam(name = "loginIds", value = "日志ID数组", required = true, dataType = "Long[]", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Boolean.class)}) + @PreAuthorize("@customSs.hasPermission('system:loginlog:remove')") + @Log(title = "登录日志", businessType = BusinessType.DELETE) + @DeleteMapping("/{loginIds}") + public R remove(@PathVariable Long[] loginIds) { + return R.ok(xlLoginLogService.deleteXlLoginLogByLoginIds(loginIds)); + } + + @ApiOperation(value = "清空日志", notes = "清空所有系统访问日志") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @PreAuthorize("@customSs.hasPermission('monitor:logininfor:clean')") + @Log(title = "登录日志", businessType = BusinessType.CLEAN) + @DeleteMapping("/clean") + public R clean() { + xlLoginLogService.cleanLoginlog(); + return R.ok(); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/controller/SysMenuController.java --- +package com.starry.admin.modules.system.controller; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.starry.admin.common.domain.TreeSelect; +import com.starry.admin.modules.system.module.entity.SysMenuEntity; +import com.starry.admin.modules.system.service.SysMenuService; +import com.starry.admin.modules.system.vo.SimpleMenu; +import com.starry.admin.utils.SecurityUtils; +import com.starry.common.constant.UserConstants; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.util.*; +import java.util.stream.Collectors; +import javax.annotation.Resource; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +/** + *

+ * 菜单表 前端控制器 + *

+ * + * @author admin + * @since 2022-07-03 + */ +@Api(tags = "菜单管理", description = "系统菜单管理相关接口") +@RestController +@RequestMapping("/ucenter/menu") +public class SysMenuController { + + @Resource + private SysMenuService menuService; + + @ApiOperation(value = "获取菜单列表", notes = "获取系统所有菜单列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = SysMenuEntity.class, responseContainer = "List")}) + @PreAuthorize("@customSs.hasPermission('system:menu:list')") + @GetMapping("/list") + public R list(@ApiParam(value = "菜单查询条件") SysMenuEntity menu) { + // 获取登录人的userId; + String userId = SecurityUtils.getUserId(); + List menus = menuService.selectMenuList(menu, userId); + return R.ok(menus); + } + + @ApiOperation(value = "分页获取菜单列表", notes = "分页查询系统菜单列表") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageSize", value = "每页记录数", defaultValue = "5", dataType = "Integer", paramType = "query"), + @ApiImplicitParam(name = "pageNum", value = "页码", defaultValue = "1", dataType = "Integer", paramType = "query")}) + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = SysMenuEntity.class, responseContainer = "Page")}) + @GetMapping("/list-page") + public R listPage(@ApiParam(value = "菜单查询条件") @RequestParam(value = "menu", required = false) SysMenuEntity menu, + @RequestParam(value = "pageSize", defaultValue = "5") Integer pageSize, + @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum) { + Page pageMenu = menuService.listPage(menu, SecurityUtils.getUserId(), pageSize, pageNum); + return R.ok(pageMenu); + } + + @ApiOperation(value = "添加菜单", notes = "创建新的系统菜单") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), + @ApiResponse(code = 500, message = "添加失败,菜单名称已存在或地址格式错误")}) + @PreAuthorize("@customSs.hasPermission('system:menu:create')") + @PostMapping("/create") + public R create(@ApiParam(value = "菜单信息", required = true) @RequestBody SysMenuEntity menu) { + if (UserConstants.NOT_UNIQUE.equals(menuService.checkMenuNameUnique(menu))) { + return R.error("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在"); + } else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) + && !StrUtil.startWithAny(menu.getPath(), "http://", "https://")) { + return R.error("新增菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头"); + } + boolean success = menuService.create(menu); + if (success) { + return R.ok(); + } + return R.error("添加失败"); + } + + @ApiOperation(value = "修改菜单", notes = "根据ID修改菜单信息") + @ApiImplicitParam(name = "id", value = "菜单ID", required = true, dataType = "Long", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), + @ApiResponse(code = 500, message = "修改失败,菜单名称已存在或地址格式错误")}) + @PreAuthorize("@customSs.hasPermission('system:menu:edit')") + @PostMapping("/update/{id}") + public R update(@PathVariable Long id, @ApiParam(value = "菜单信息", required = true) @RequestBody SysMenuEntity menu) { + menu.setMenuId(id); + if (UserConstants.NOT_UNIQUE.equals(menuService.checkMenuNameUnique(menu))) { + return R.error("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在"); + } else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) + && !StrUtil.startWithAny(menu.getPath(), "http://", "https://")) { + return R.error("修改菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头"); + } else if (menu.getMenuId().equals(menu.getParentId())) { + return R.error("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己"); + } + boolean success = menuService.updateById(menu); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + @ApiOperation(value = "删除菜单", notes = "根据ID删除菜单") + @ApiImplicitParam(name = "id", value = "菜单ID", required = true, dataType = "Long", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "删除失败,存在子菜单")}) + @PreAuthorize("@customSs.hasPermission('system:menu:delete')") + @PostMapping(value = "/delete/{id}") + public R delete(@PathVariable("id") Long menuId) { + if (menuService.hasChildByMenuId(menuId)) { + return R.error("存在子菜单,不允许删除"); + } + boolean success = menuService.removeByIds(Collections.singletonList(menuId)); + if (success) { + return R.ok(); + } + return R.error("删除失败"); + } + + @ApiOperation(value = "获取菜单下拉树列表", notes = "获取菜单的树形结构") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = TreeSelect.class, responseContainer = "List")}) + @GetMapping("/treeselect") + public R treeselect(@ApiParam(value = "菜单查询条件") SysMenuEntity menu) { + List menus = menuService.selectMenuList(menu, SecurityUtils.getUserId()); + List tree = menuService.buildMenuTreeSelect(menus); + return R.ok(tree); + } + + @ApiOperation(value = "获取菜单详情", notes = "根据菜单ID获取菜单详细信息") + @ApiImplicitParam(name = "menuId", value = "菜单ID", required = true, dataType = "Long", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = SysMenuEntity.class)}) + @PreAuthorize("@customSs.hasPermission('system:menu:query')") + @GetMapping(value = "/{menuId}") + public R getInfo(@PathVariable Long menuId) { + return R.ok(menuService.selectMenuById(menuId)); + } + + @ApiOperation(value = "获取角色菜单树", notes = "获取指定角色的菜单树形结构") + @ApiImplicitParam(name = "roleId", value = "角色ID", required = true, dataType = "Long", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Map.class)}) + @GetMapping(value = "/roleMenuTreeselect/{roleId}") + public R roleMenuTreeselect(@PathVariable("roleId") Long roleId) { + List menus = menuService.selectMenuList(SecurityUtils.getUserId()); + Map resultMap = new HashMap<>(); + resultMap.put("checkedKeys", menuService.selectMenuListByRoleId(roleId)); + resultMap.put("menus", menuService.buildMenuTreeSelect(menus)); + return R.ok(resultMap); + } + + @ApiOperation(value = "获取菜单精简信息列表", notes = "只包含被开启的菜单,用于【角色分配菜单】功能的选项。在多租户的场景下,会只返回租户所在套餐有的菜单") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = SimpleMenu.class, responseContainer = "List")}) + @GetMapping("/list-all-simple") + public R getSimpleMenus() { + // 获得菜单列表,只要开启状态的 + List menus = menuService.selectSimpleMenuList(); + // TODO 移除公共模块 + List forbidList = Arrays.asList(26L, 48L, 47L, 19L); + List menuList = menus.stream() + .filter(ca -> !forbidList.contains(ca.getId()) || !forbidList.contains(ca.getParentId())) + .collect(Collectors.toList()); + return R.ok(menus); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/controller/SysOperationLogController.java --- +package com.starry.admin.modules.system.controller; + +import com.starry.admin.modules.system.module.entity.SysOperationLogEntity; +import com.starry.admin.modules.system.service.ISysOperationLogService; +import com.starry.admin.modules.system.vo.SysOperationLogVo; +import com.starry.admin.utils.ExcelUtils; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +/** + * 操作日志表Controller + * + * @author admin + */ +@Api(tags = "操作日志管理", description = "系统操作日志相关接口") +@RestController +@RequestMapping("/system/operlog") +public class SysOperationLogController { + + @Resource + private ISysOperationLogService xlOperLogService; + + /** + * 查询操作日志表列表 + */ + @ApiOperation(value = "查询操作日志列表", notes = "分页查询系统操作日志列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = SysOperationLogEntity.class, responseContainer = "Page")}) + @PreAuthorize("@customSs.hasPermission('system:operlog:list')") + @GetMapping("/list") + public R list(@ApiParam(value = "查询条件") SysOperationLogVo sysOperationLogEntity) { + return R.ok(xlOperLogService.selectXlOperLogList(sysOperationLogEntity)); + } + + /** + * 获取操作日志表详细信息 + */ + @ApiOperation(value = "获取操作日志详情", notes = "根据ID获取操作日志详细信息") + @ApiImplicitParam(name = "operId", value = "日志ID", required = true, dataType = "Long", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = SysOperationLogEntity.class)}) + @PreAuthorize("@customSs.hasPermission('system:operlog:query')") + @GetMapping(value = "/{operId}") + public R getInfo(@PathVariable("operId") Long operId) { + return R.ok(xlOperLogService.selectXlOperLogByOperId(operId)); + } + + /** + * 新增操作日志表 + */ + @ApiOperation(value = "新增操作日志", notes = "手动创建系统操作日志记录") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "添加失败")}) + @PreAuthorize("@customSs.hasPermission('system:operlog:create')") + @Log(title = "操作日志表", businessType = BusinessType.INSERT) + @PostMapping + public R create( + @ApiParam(value = "操作日志信息", required = true) @RequestBody SysOperationLogEntity sysOperationLogEntity) { + boolean success = xlOperLogService.create(sysOperationLogEntity); + if (success) { + return R.ok(); + } + return R.error("添加失败"); + } + + /** + * 修改操作日志表 + */ + @ApiOperation(value = "修改操作日志", notes = "根据ID修改操作日志信息") + @ApiImplicitParam(name = "operId", value = "日志ID", required = true, dataType = "Long", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败")}) + @PreAuthorize("@customSs.hasPermission('system:operlog:edit')") + @Log(title = "操作日志表", businessType = BusinessType.UPDATE) + @PostMapping(value = "/update/{operId}") + public R update(@PathVariable Long operId, + @ApiParam(value = "操作日志信息", required = true) @RequestBody SysOperationLogEntity sysOperationLogEntity) { + sysOperationLogEntity.setOperId(operId); + boolean success = xlOperLogService.updateXlOperLog(sysOperationLogEntity); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + /** + * 删除操作日志表 + */ + @ApiOperation(value = "删除操作日志", notes = "根据ID批量删除操作日志") + @ApiImplicitParam(name = "operIds", value = "日志ID数组", required = true, dataType = "Long[]", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Boolean.class)}) + @PreAuthorize("@customSs.hasPermission('system:operlog:remove')") + @Log(title = "操作日志表", businessType = BusinessType.DELETE) + @DeleteMapping("/{operIds}") + public R remove(@PathVariable Long[] operIds) { + return R.ok(xlOperLogService.deleteXlOperLogByOperIds(operIds)); + } + + /** + * 导出操作日志表 + */ + @ApiOperation(value = "导出操作日志", notes = "导出系统操作日志表数据") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @PreAuthorize("@customSs.hasPermission('system:operlog:export')") + @Log(title = "操作日志", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(HttpServletResponse response, + @ApiParam(value = "查询条件") SysOperationLogVo sysOperationLogEntity) { + ExcelUtils.exportEasyExcel(response, SysOperationLogEntity.class, + xlOperLogService.selectXlOperLogList(sysOperationLogEntity).getRecords(), "系统操作日志表数据"); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/controller/SysRoleController.java --- +package com.starry.admin.modules.system.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.starry.admin.modules.system.module.entity.SysDeptEntity; +import com.starry.admin.modules.system.module.entity.SysRoleEntity; +import com.starry.admin.modules.system.module.entity.SysUserRoleEntity; +import com.starry.admin.modules.system.service.SysDeptService; +import com.starry.admin.modules.system.service.SysRoleService; +import com.starry.admin.modules.system.service.SysUserService; +import com.starry.admin.modules.system.vo.RoleUserResultVo; +import com.starry.admin.modules.system.vo.SysRoleAddVo; +import com.starry.admin.modules.system.vo.SysUserQueryVo; +import com.starry.common.annotation.Log; +import com.starry.common.constant.UserConstants; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.annotation.Resource; +import org.springframework.beans.BeanUtils; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + *

+ * 角色表 前端控制器 + *

+ * + * @author admin + * @since 2022-07-01 + */ +@Api(tags = "角色管理", description = "系统角色管理相关接口") +@RestController +@RequestMapping("/ucenter/role") +public class SysRoleController { + + @Resource + private SysRoleService roleService; + @Resource + private SysDeptService deptService; + @Resource + private SysUserService userService; + + @ApiOperation(value = "添加角色", notes = "创建新的系统角色") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "操作失败,角色名称或权限已存在")}) + @PreAuthorize("@customSs.hasPermission('system:role:create')") + @PostMapping("/create") + public R create(@ApiParam(value = "角色信息", required = true) @Validated @RequestBody SysRoleAddVo roleAddVo) { + SysRoleEntity role = new SysRoleEntity(); + BeanUtils.copyProperties(roleAddVo, role); + if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role))) { + return R.error("新增角色'" + role.getRoleName() + "'失败,角色名称已存在"); + } else if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role))) { + return R.error("新增角色'" + role.getRoleName() + "'失败,角色权限已存在"); + } + boolean success = roleService.create(role); + if (success) { + return R.ok(); + } + return R.error("添加失败"); + } + + @ApiOperation(value = "修改角色", notes = "根据ID修改角色信息") + @ApiImplicitParam(name = "id", value = "角色ID", required = true, dataType = "Long", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败,角色名称或权限已存在")}) + @PreAuthorize("@customSs.hasPermission('system:role:edit')") + @PostMapping("/update/{id}") + public R update(@PathVariable Long id, @ApiParam(value = "角色信息", required = true) @RequestBody SysRoleEntity role) { + role.setRoleId(id); + roleService.checkRoleAllowed(role); + roleService.checkRoleDataScope(role.getRoleId()); + if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role))) { + return R.error("修改角色'" + role.getRoleName() + "'失败,角色名称已存在"); + } else if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role))) { + return R.error("修改角色'" + role.getRoleName() + "'失败,角色权限已存在"); + } + boolean success = roleService.updateById(role); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + @ApiOperation(value = "批量删除角色", notes = "根据ID批量删除角色") + @ApiImplicitParam(name = "roleIds", value = "角色ID数组", required = true, dataType = "Long[]", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "删除失败")}) + @PreAuthorize("@customSs.hasPermission('system:role:remove')") + @DeleteMapping("/{roleIds}") + public R delete(@PathVariable Long[] roleIds) { + boolean success = roleService.delete(roleIds); + if (success) { + return R.ok(); + } + return R.error("删除失败"); + } + + @ApiOperation(value = "获取所有角色", notes = "获取系统中所有角色列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = SysRoleEntity.class, responseContainer = "List")}) + @GetMapping("/list-all") + public R listAll() { + List list = roleService.list(); + return R.ok(list); + } + + @ApiOperation(value = "分页获取角色列表", notes = "根据角色名称分页获取角色列表") + @ApiImplicitParams({@ApiImplicitParam(name = "keyword", value = "搜索关键词", dataType = "String", paramType = "query"), + @ApiImplicitParam(name = "pageSize", value = "每页记录数", defaultValue = "5", dataType = "Integer", paramType = "query"), + @ApiImplicitParam(name = "pageNum", value = "页码", defaultValue = "1", dataType = "Integer", paramType = "query")}) + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = SysRoleEntity.class, responseContainer = "Page")}) + @GetMapping("/list-page") + public R listPage(@RequestParam(value = "keyword", required = false) String keyword, + @RequestParam(value = "pageSize", defaultValue = "5") Integer pageSize, + @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum) { + Page rolePage = roleService.list(keyword, pageSize, pageNum); + return R.ok(rolePage); + } + + @ApiOperation(value = "修改角色状态", notes = "启用或禁用角色") + @ApiImplicitParams({ + @ApiImplicitParam(name = "id", value = "角色ID", required = true, dataType = "Long", paramType = "path"), + @ApiImplicitParam(name = "status", value = "状态(0-正常,1-停用)", required = true, dataType = "Integer", paramType = "query")}) + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败")}) + @PreAuthorize("@customSs.hasPermission('system:role:edit')") + @PostMapping("/update-status/{id}") + public R updateStatus(@PathVariable Long id, @RequestParam(value = "status") Integer status) { + SysRoleEntity role = new SysRoleEntity(); + role.setRoleId(id); + role.setStatus(status); + boolean success = roleService.updateById(role); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + @ApiOperation(value = "分配菜单权限", notes = "为角色分配菜单权限") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "分配失败")}) + @PreAuthorize("@customSs.hasPermission('system:role:auth')") + @PostMapping("/auth-role-menu") + public R authRoleMenu(@ApiParam(value = "角色信息", required = true) @RequestBody SysRoleEntity role) { + boolean success = roleService.authRoleMenu(role); + if (success) { + return R.ok(); + } + return R.error("分配失败"); + } + + /** + * 根据角色编号获取详细信息 + */ + @ApiOperation(value = "获取角色详情", notes = "根据角色ID获取角色详细信息") + @ApiImplicitParam(name = "roleId", value = "角色ID", required = true, dataType = "Long", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = SysRoleEntity.class)}) + @GetMapping(value = "/{roleId}") + public R getInfo(@PathVariable Long roleId) { + roleService.checkRoleDataScope(roleId); + return R.ok(roleService.getById(roleId)); + } + + /** + * 获取对应角色部门树列表 + */ + @ApiOperation(value = "获取角色部门树列表", notes = "获取角色关联的部门树结构") + @ApiImplicitParam(name = "roleId", value = "角色ID", required = true, dataType = "Long", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Map.class)}) + @GetMapping(value = "/deptTree/{roleId}") + public R deptTree(@PathVariable("roleId") Long roleId) { + Map resultMap = new HashMap<>(8); + resultMap.put("checkedKeys", deptService.selectDeptListByRoleId(roleId)); + resultMap.put("depts", deptService.selectDeptTreeList(new SysDeptEntity())); + return R.ok(resultMap); + } + + /** + * 修改保存数据权限 + */ + @ApiOperation(value = "保存数据权限", notes = "修改角色的数据权限范围") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Boolean.class)}) + @Log(title = "角色管理-保存数据权限", businessType = BusinessType.UPDATE) + @PostMapping("/dataScope") + public R dataScope(@ApiParam(value = "角色信息", required = true) @RequestBody SysRoleEntity role) { + roleService.checkRoleAllowed(role); + roleService.checkRoleDataScope(role.getRoleId()); + return R.ok(roleService.authDataScope(role)); + } + + /** + * 查询已分配用户角色列表 + */ + @ApiOperation(value = "查询已分配用户角色列表", notes = "获取已经分配给指定角色的用户列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = RoleUserResultVo.class, responseContainer = "Page")}) + @PreAuthorize("@customSs.hasPermission('system:role:list')") + @GetMapping("/authUser/allocatedList") + public R allocatedList(SysUserQueryVo user) { + IPage list = userService.selectAllocatedList(user); + return R.ok(list); + } + + /** + * 查询未分配用户角色列表 + */ + @ApiOperation(value = "查询未分配用户角色列表", notes = "获取尚未分配给指定角色的用户列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = RoleUserResultVo.class, responseContainer = "Page")}) + @PreAuthorize("@customSs.hasPermission('system:role:list')") + @GetMapping("/authUser/unallocatedList") + public R unallocatedList(SysUserQueryVo user) { + return R.ok(userService.selectUnallocatedList(user)); + } + + /** + * 取消授权用户 + */ + @ApiOperation(value = "取消授权用户", notes = "取消指定用户的角色授权") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Boolean.class)}) + @PreAuthorize("@customSs.hasPermission('system:role:edit')") + @Log(title = "角色管理", businessType = BusinessType.GRANT) + @PutMapping("/authUser/cancel") + public R cancelAuthUser(@ApiParam(value = "用户角色关系", required = true) @RequestBody SysUserRoleEntity userRole) { + return R.ok(roleService.deleteAuthUser(userRole)); + } + + /** + * 批量取消授权用户 + */ + @ApiOperation(value = "批量取消授权用户", notes = "批量取消多个用户的角色授权") + @ApiImplicitParams({ + @ApiImplicitParam(name = "roleId", value = "角色ID", required = true, dataType = "Long", paramType = "query"), + @ApiImplicitParam(name = "userIds", value = "用户ID数组", required = true, dataType = "String[]", paramType = "query")}) + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Boolean.class)}) + @PreAuthorize("@customSs.hasPermission('system:role:edit')") + @Log(title = "角色管理", businessType = BusinessType.GRANT) + @PutMapping("/authUser/cancelAll") + public R cancelAuthUserAll(Long roleId, String[] userIds) { + return R.ok(roleService.deleteAuthUsers(roleId, userIds)); + } + + /** + * 批量选择用户授权 + */ + @ApiOperation(value = "批量选择用户授权", notes = "为角色批量添加用户授权") + @ApiImplicitParams({ + @ApiImplicitParam(name = "roleId", value = "角色ID", required = true, dataType = "Long", paramType = "query"), + @ApiImplicitParam(name = "userIds", value = "用户ID数组", required = true, dataType = "String[]", paramType = "query")}) + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Boolean.class)}) + @PreAuthorize("@customSs.hasPermission('system:role:edit')") + @Log(title = "角色管理", businessType = BusinessType.GRANT) + @PutMapping("/authUser/selectAll") + public R selectAuthUserAll(Long roleId, String[] userIds) { + roleService.checkRoleDataScope(roleId); + return R.ok(roleService.insertAuthUsers(roleId, userIds)); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/controller/SysSmsController.java --- +package com.starry.admin.modules.system.controller; + +import com.starry.admin.modules.system.module.entity.SysTenantEntity; +import com.starry.admin.modules.system.service.ISysTenantService; +import com.starry.admin.utils.SmsUtils; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +/** + * 动态接口 + * + * @author admin + * @since 2024/5/20 下午11:19 + **/ +@Api(tags = "短信管理", description = "系统短信发送相关接口") +@Slf4j +@RestController +@RequestMapping("/system/sms") +public class SysSmsController { + @Resource + private SmsUtils smsUtils; + @Resource + private ISysTenantService tenantService; + + @ApiOperation(value = "发送短信", notes = "向指定手机号发送短信验证码") + @ApiImplicitParam(name = "phone", value = "手机号码", required = true, dataType = "String", paramType = "query") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @GetMapping("/send") + public R sendSms(@RequestParam("phone") String phone) { + smsUtils.sendSmsApi(phone); + return R.ok(); + } + + @ApiOperation(value = "测试接口", notes = "测试租户角色初始化") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Boolean.class)}) + @GetMapping("/test") + public R test() { + SysTenantEntity sysTenantEntity = tenantService.selectSysTenantByTenantId("y5PNjqco"); + tenantService.initRole(sysTenantEntity); + return R.ok(true); + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/controller/SysTenantController.java --- +package com.starry.admin.modules.system.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService; +import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity; +import com.starry.admin.modules.order.service.IPlayOrderInfoService; +import com.starry.admin.modules.system.module.entity.SysTenantEntity; +import com.starry.admin.modules.system.service.ISysTenantService; +import com.starry.admin.modules.system.vo.SysTenantAddVo; +import com.starry.admin.modules.system.vo.SysTenantQueryVo; +import com.starry.admin.modules.system.vo.SysTenantReturnVo; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import com.starry.common.utils.ConvertUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.math.BigDecimal; +import java.util.List; +import javax.annotation.Resource; +import org.springframework.beans.BeanUtils; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 租户表Controller + * + * @author admin + */ +@Api(tags = "租户管理", description = "系统租户相关接口") +@RestController +@RequestMapping("/platform/tenant") +public class SysTenantController { + @Resource + private ISysTenantService sysTenantService; + + @Resource + private IPlayClerkUserInfoService playClerkUserInfoService; + + @Resource + private IPlayOrderInfoService playOrderInfoService; + + /** + * 新增租户表 + */ + @ApiOperation(value = "新增租户", notes = "创建新的系统租户") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "添加失败")}) + // @PreAuthorize("@customSs.hasPermission('platform:tenant:create')") + @Log(title = "租户表", businessType = BusinessType.INSERT) + @PostMapping("/create") + public R create(@ApiParam(value = "租户信息", required = true) @Validated @RequestBody SysTenantAddVo vo) { + SysTenantEntity entity = ConvertUtil.entityToVo(vo, SysTenantEntity.class); + return sysTenantService.addTenant(entity); + } + + /** + * 查询租户表列表 + */ + @ApiOperation(value = "分页查询租户列表", notes = "根据条件分页查询租户列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = SysTenantReturnVo.class, responseContainer = "Page")}) + @PreAuthorize("@customSs.hasPermission('platform:tenant:list')") + @PostMapping("/listByPage") + public R listByPage(@ApiParam(value = "查询条件", required = true) @RequestBody SysTenantQueryVo vo) { + IPage page = sysTenantService.selectSysTenantList(vo); + IPage voPage = page.convert(u -> { + SysTenantReturnVo returnVo = new SysTenantReturnVo(); + List orderInfoEntities = playOrderInfoService.getTotalOrderInfo(u.getTenantId()); + BigDecimal rechargeAmount = BigDecimal.ZERO; + for (PlayOrderInfoEntity orderInfoEntity : orderInfoEntities) { + if ("0".equals(orderInfoEntity.getOrderType())) { + rechargeAmount = rechargeAmount.add(orderInfoEntity.getFinalAmount()); + } + } + + BeanUtils.copyProperties(u, returnVo); + returnVo.setClerkNumber(playClerkUserInfoService.getTotalClerkUser(u.getTenantId())); + returnVo.setOrderNumber((long) orderInfoEntities.size()); + returnVo.setRechargeAmount(rechargeAmount); + return returnVo; + }); + + return R.ok(voPage); + } + + /** + * 获取租户表详细信息 + */ + @ApiOperation(value = "获取租户详情", notes = "根据租户ID获取租户详细信息") + @ApiImplicitParam(name = "tenantId", value = "租户ID", required = true, dataType = "String", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = SysTenantEntity.class)}) + @PreAuthorize("@customSs.hasPermission('platform:tenant:query')") + @GetMapping(value = "/{tenantId}") + public R getInfo(@PathVariable("tenantId") String tenantId) { + return R.ok(sysTenantService.selectSysTenantByTenantId(tenantId)); + } + + /** + * 修改租户表 + */ + @ApiOperation(value = "修改租户", notes = "根据租户ID修改租户信息") + @ApiImplicitParam(name = "tenantId", value = "租户ID", required = true, dataType = "String", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败")}) + @PreAuthorize("@customSs.hasPermission('platform:tenant:edit')") + @Log(title = "租户表", businessType = BusinessType.UPDATE) + @PostMapping(value = "/update/{tenantId}") + public R update(@PathVariable String tenantId, + @ApiParam(value = "租户信息", required = true) @RequestBody SysTenantEntity sysTenantEntity) { + return sysTenantService.updateTenant(sysTenantEntity); + } + + /** + * 删除租户表 + */ + @ApiOperation(value = "删除租户", notes = "根据租户ID批量删除租户") + @ApiImplicitParam(name = "tenantIds", value = "租户ID数组", required = true, dataType = "String[]", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Boolean.class)}) + @PreAuthorize("@customSs.hasPermission('platform:tenant:remove')") + @Log(title = "租户表", businessType = BusinessType.DELETE) + @DeleteMapping("/{tenantIds}") + public R remove(@PathVariable String[] tenantIds) { + return R.ok(sysTenantService.deleteSysTenantByTenantIds(tenantIds)); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/controller/SysTenantPackageController.java --- +package com.starry.admin.modules.system.controller; + +import com.starry.admin.modules.system.module.entity.SysTenantPackageEntity; +import com.starry.admin.modules.system.service.ISysTenantPackageService; +import com.starry.admin.modules.system.vo.SimplePackage; +import com.starry.admin.modules.system.vo.SysTenantPackageVo; +import com.starry.admin.utils.ExcelUtils; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import com.starry.common.utils.ConvertUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.util.List; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +/** + * 租户套餐表Controller + * + * @author admin + */ +@Api(tags = "租户套餐管理", description = "系统租户套餐相关接口") +@RestController +@RequestMapping("/platform/package") +public class SysTenantPackageController { + @Resource + private ISysTenantPackageService SysTenantPackageService; + + /** + * 查询租户套餐表列表 + */ + @ApiOperation(value = "查询租户套餐列表", notes = "分页查询租户套餐列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = SysTenantPackageEntity.class, responseContainer = "Page")}) + @PreAuthorize("@customSs.hasPermission('platform:package:list')") + @GetMapping("/list") + public R list(@ApiParam(value = "查询条件") SysTenantPackageVo sysTenantPackageEntity) { + return R.ok(SysTenantPackageService.selectSysTenantPackageList(sysTenantPackageEntity)); + } + + /** + * 导出租户套餐表列表 + */ + @ApiOperation(value = "导出租户套餐", notes = "导出租户套餐表数据到Excel") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @PreAuthorize("@customSs.hasPermission('platform:package:export')") + @Log(title = "租户套餐表", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(HttpServletResponse response, + @ApiParam(value = "查询条件") SysTenantPackageVo sysTenantPackageEntity) { + ExcelUtils.exportEasyExcel(response, SysTenantPackageEntity.class, + SysTenantPackageService.selectSysTenantPackageList(sysTenantPackageEntity).getRecords(), "租户套餐表数据"); + } + + /** + * 获取租户套餐表详细信息 + */ + @ApiOperation(value = "获取租户套餐详情", notes = "根据ID获取租户套餐详细信息") + @ApiImplicitParam(name = "packageId", value = "套餐ID", required = true, dataType = "String", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = SysTenantPackageEntity.class)}) + @PreAuthorize("@customSs.hasPermission('platform:package:query')") + @GetMapping(value = "/{packageId}") + public R getInfo(@PathVariable("packageId") String packageId) { + return R.ok(SysTenantPackageService.selectSysTenantPackageByPackageId(packageId)); + } + + /** + * 新增租户套餐表 + */ + @ApiOperation(value = "新增租户套餐", notes = "创建新的租户套餐") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "添加失败")}) + @PreAuthorize("@customSs.hasPermission('platform:package:create')") + @Log(title = "租户套餐表", businessType = BusinessType.INSERT) + @PostMapping("/create") + public R create(@ApiParam(value = "套餐信息", required = true) @RequestBody SysTenantPackageEntity vo) { + SysTenantPackageEntity entity = ConvertUtil.entityToVo(vo, SysTenantPackageEntity.class); + boolean success = SysTenantPackageService.create(entity); + if (success) { + return R.ok(); + } + return R.error("添加失败"); + } + + /** + * 修改租户套餐表 + */ + @ApiOperation(value = "修改租户套餐", notes = "根据ID修改租户套餐信息") + @ApiImplicitParam(name = "packageId", value = "套餐ID", required = true, dataType = "String", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败")}) + @PreAuthorize("@customSs.hasPermission('platform:package:edit')") + @Log(title = "租户套餐表", businessType = BusinessType.UPDATE) + @PostMapping(value = "/update/{packageId}") + public R update(@PathVariable String packageId, + @ApiParam(value = "套餐信息", required = true) @RequestBody SysTenantPackageEntity sysTenantPackageEntity) { + + sysTenantPackageEntity.setPackageId(packageId); + boolean success = SysTenantPackageService.update(sysTenantPackageEntity); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + /** + * 删除租户套餐表 + */ + @ApiOperation(value = "删除租户套餐", notes = "根据ID批量删除租户套餐") + @ApiImplicitParam(name = "packageIds", value = "套餐ID数组", required = true, dataType = "String[]", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Boolean.class)}) + @PreAuthorize("@customSs.hasPermission('platform:package:remove')") + @Log(title = "租户套餐表", businessType = BusinessType.DELETE) + @DeleteMapping("/{packageIds}") + public R remove(@PathVariable String[] packageIds) { + return R.ok(SysTenantPackageService.deleteSysTenantPackageByPackageIds(packageIds)); + } + + /** + * 查询租户套餐精简列表 + */ + @ApiOperation(value = "查询套餐精简列表", notes = "获取租户套餐的精简信息列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = SimplePackage.class, responseContainer = "List")}) + @GetMapping("/get-simple-list") + public R getSimpleList() { + List list = SysTenantPackageService.getSimpleList(); + return R.ok(list); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/controller/SysTenantRechargeInfoController.java --- +package com.starry.admin.modules.system.controller; + +import com.starry.admin.modules.system.module.entity.SysTenantRechargeInfoEntity; +import com.starry.admin.modules.system.module.vo.SysTenantRechargeInfoAddVo; +import com.starry.admin.modules.system.module.vo.SysTenantRechargeInfoQueryVo; +import com.starry.admin.modules.system.service.ISysTenantRechargeInfoService; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import javax.annotation.Resource; +import org.springframework.beans.BeanUtils; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 租户充值信息Controller + * + * @author admin + * @since 2024-09-05 + */ +@Api(tags = "租户充值管理", description = "租户充值记录相关接口") +@RestController +@RequestMapping("/platform/recharge") +public class SysTenantRechargeInfoController { + @Resource + private ISysTenantRechargeInfoService sysTenantRechargeInfoService; + + /** + * 查询租户充值信息列表 + */ + @ApiOperation(value = "查询充值记录", notes = "分页查询租户充值记录列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = SysTenantRechargeInfoEntity.class, responseContainer = "Page")}) + // @PreAuthorize("@customSs.hasPermission('play:info:list')") + @PostMapping("/listByPage") + public R list(@ApiParam(value = "查询条件", required = true) @Validated @RequestBody SysTenantRechargeInfoQueryVo vo) { + return R.ok(sysTenantRechargeInfoService.selectByPage(vo)); + } + + /** + * 获取租户充值信息详细信息 + */ + @ApiOperation(value = "获取充值详情", notes = "根据ID获取租户充值记录详细信息") + @ApiImplicitParam(name = "id", value = "充值记录ID", required = true, dataType = "String", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = SysTenantRechargeInfoEntity.class)}) + // @PreAuthorize("@customSs.hasPermission('play:info:query')") + @GetMapping(value = "/{id}") + public R getInfo(@PathVariable("id") String id) { + return R.ok(sysTenantRechargeInfoService.selectSysTenantRechargeInfoById(id)); + } + + /** + * 新增租户充值信息 + */ + @ApiOperation(value = "新增充值记录", notes = "创建租户充值记录") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "添加失败")}) + // @PreAuthorize("@customSs.hasPermission('play:info:create')") + @Log(title = "租户充值信息", businessType = BusinessType.INSERT) + @PostMapping("/create") + public R create( + @ApiParam(value = "充值信息", required = true) @Validated @RequestBody SysTenantRechargeInfoAddVo addVo) { + SysTenantRechargeInfoEntity entity = new SysTenantRechargeInfoEntity(); + BeanUtils.copyProperties(addVo, entity); + boolean success = sysTenantRechargeInfoService.create(entity); + if (success) { + return R.ok(); + } + return R.error("添加失败"); + } + + /** + * 修改租户充值信息 + */ + @ApiOperation(value = "修改充值记录", notes = "根据ID修改租户充值记录") + @ApiImplicitParam(name = "id", value = "充值记录ID", required = true, dataType = "String", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败")}) + @PreAuthorize("@customSs.hasPermission('play:info:edit')") + @Log(title = "租户充值信息", businessType = BusinessType.UPDATE) + @PostMapping(value = "/update/{id}") + public R update(@PathVariable String id, + @ApiParam(value = "充值信息", required = true) @RequestBody SysTenantRechargeInfoEntity sysTenantRechargeInfo) { + sysTenantRechargeInfo.setId(id); + boolean success = sysTenantRechargeInfoService.update(sysTenantRechargeInfo); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + /** + * 删除租户充值信息 + */ + @ApiOperation(value = "删除充值记录", notes = "根据ID批量删除租户充值记录") + @ApiImplicitParam(name = "ids", value = "充值记录ID数组", required = true, dataType = "String[]", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Boolean.class)}) + // @PreAuthorize("@customSs.hasPermission('play:info:remove')") + @Log(title = "租户充值信息", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@PathVariable String[] ids) { + return R.ok(sysTenantRechargeInfoService.deleteSysTenantRechargeInfoByIds(ids)); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/controller/SysUserController.java --- +package com.starry.admin.modules.system.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.starry.admin.common.component.JwtToken; +import com.starry.admin.common.domain.LoginUser; +import com.starry.admin.common.oss.service.IOssFileService; +import com.starry.admin.modules.system.module.entity.SysRoleEntity; +import com.starry.admin.modules.system.module.entity.SysUserEntity; +import com.starry.admin.modules.system.service.SysRoleService; +import com.starry.admin.modules.system.service.SysUserService; +import com.starry.admin.modules.system.vo.*; +import com.starry.admin.utils.SecurityUtils; +import com.starry.common.annotation.Log; +import com.starry.common.constant.UserConstants; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import javax.annotation.Resource; +import javax.validation.Valid; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +/** + *

+ * 后台用户表 前端控制器 + *

+ * + * @author admin + * @since 2021-09-03 + */ +@Api(tags = "用户管理", description = "系统用户管理相关接口") +@RestController +@RequestMapping("/ucenter/user") +public class SysUserController { + + @Resource + private SysUserService userService; + @Resource + private SysRoleService roleService; + @Resource + private JwtToken tokenService; + + @Resource + private IOssFileService ossFileService; + + @ApiOperation(value = "注册用户", notes = "新用户注册接口") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = SysUserEntity.class), + @ApiResponse(code = 500, message = "操作失败")}) + @PostMapping(value = "register") + public R register(@ApiParam(value = "用户信息", required = true) @RequestBody SysUserEntity user) { + SysUserEntity sysUserEntity = userService.register(user); + if (sysUserEntity == null) { + return R.error("注册失败,用户名已存在"); + } + return R.ok(sysUserEntity); + } + + @ApiOperation(value = "分页用户列表", notes = "分页查询用户列表信息") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = SysUserEntity.class, responseContainer = "Page")}) + @GetMapping(value = "/list-page") + public R listPage(UserQueryVo queryVo) { + IPage page = userService.listMemberPage(queryVo); + return R.ok(page); + } + + @ApiOperation(value = "分页用户列表(V1)", notes = "分页查询用户列表信息,返回格式化后的结果") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = SysUserEntityListVo.class, responseContainer = "Page")}) + @GetMapping(value = "/list-page/v1") + public R listPageV1(UserQueryVo queryVo) { + IPage page = userService.listMemberPage(queryVo); + List records = page.getRecords(); + List list = userService.generatePageData(records); + IPage result = new Page<>(); + result.setTotal(page.getTotal()); + result.setRecords(list); + return R.ok(result); + } + + @ApiOperation(value = "添加用户", notes = "创建新的系统用户") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "操作失败,登录账号已存在")}) + @PostMapping(value = "add") + public R add(@ApiParam(value = "用户信息", required = true) @RequestBody SysUserEntity user) { + if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user.getUserCode()))) { + return R.error("新增用户'" + user.getUserCode() + "'失败,登录账号已存在"); + } + boolean success = userService.create(user); + if (success) { + return R.ok(); + } + return R.error("添加失败"); + } + + @ApiOperation(value = "添加用户(V1)", notes = "创建新的系统用户,使用参数对象") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @PostMapping(value = "add/v1") + public R addV1(@ApiParam(value = "用户添加参数", required = true) @Valid @RequestBody UserAddParam param) { + boolean success = userService.addV1(param); + return R.ok(); + } + + @ApiOperation(value = "修改用户", notes = "根据ID修改用户信息") + @ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "String", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "修改失败")}) + @PostMapping(value = "/update/{id}") + public R update(@PathVariable("id") String id, + @ApiParam(value = "用户信息", required = true) @RequestBody SysUserEntity user) { + user.setUserId(id); + boolean flag = userService.update(user); + if (flag) { + return R.ok(); + } + return R.error("修改失败"); + } + + @ApiOperation(value = "修改用户密码", notes = "修改当前用户的密码") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @PostMapping(value = "/update/password") + public R updatePassword( + @ApiParam(value = "密码修改参数", required = true) @Valid @RequestBody UpdateUserPasswordParam param) { + userService.updatePassword(param); + return R.ok(); + } + + @ApiOperation(value = "修改用户密码", notes = "修改当前用户的密码") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @PostMapping(value = "/profile/updatePwd") + public R updatePasswordV2( + @ApiParam(value = "密码修改参数", required = true) @Valid @RequestBody UpdateUserPasswordParamV2 param) { + userService.updatePasswordV2(param); + return R.ok(); + } + + @ApiOperation(value = "修改用户手机号", notes = "修改当前用户的手机号") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @PostMapping(value = "/update/mobile") + public R updateMobile( + @ApiParam(value = "手机号修改参数", required = true) @Valid @RequestBody UpdateUserMobileParam param) { + userService.updateMobile(param); + return R.ok(); + } + + @ApiOperation(value = "删除用户", notes = "根据ID删除用户") + @ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "String", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "操作失败")}) + @PostMapping(value = "/delete/{id}") + public R delete(@PathVariable("id") String id) { + boolean flag = userService.delete(Collections.singletonList(id)); + if (flag) { + return R.ok(); + } + return R.error(); + } + + @ApiOperation(value = "登出功能", notes = "用户登出系统") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @PostMapping(value = "logout") + public R logout() { + return R.ok(); + } + + @ApiOperation(value = "获取用户详情", notes = "根据用户ID获取用户详细信息,不传ID则获取当前用户") + @ApiImplicitParam(name = "userId", value = "用户ID", required = false, dataType = "String", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Map.class)}) + @GetMapping(value = {"/", "/{userId}"}) + public R getInfo(@PathVariable(value = "userId", required = false) String userId) { + SysUserEntity user = userService.selectUserById(userId); + Map map = new HashMap<>(8); + List roles = roleService.selectRoleList(new SysRoleEntity()); + map.put("roles", + SysUserEntity.isAdmin(user) + ? roles + : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList())); + map.put("roleIds", user.getRoles().stream().map(SysRoleEntity::getRoleId).collect(Collectors.toList())); + map.put("user", user); + return R.ok(map); + } + + @ApiOperation(value = "获取个人信息", notes = "获取当前登录用户的个人信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Map.class)}) + @GetMapping(value = "/profile") + public R getProfile() { + Map map = new HashMap<>(8); + SysUserEntity loginUser = userService.selectUserById(SecurityUtils.getUserId()); + map.put("user", loginUser); + map.put("roleGroup", userService.selectUserRoleGroup(loginUser.getUserId())); + return R.ok(map); + } + + @ApiOperation(value = "用户头像上传", notes = "上传用户头像图片") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = String.class), + @ApiResponse(code = 500, message = "上传头像异常")}) + @Log(title = "用户头像上传", businessType = BusinessType.UPDATE) + @PostMapping("/profile/avatar") + public R uploadAvatar(@ApiParam(value = "头像文件", required = true) @RequestParam("avatarfile") MultipartFile file) + throws Exception { + if (!file.isEmpty()) { + String avatar = ossFileService.upload(file.getInputStream(), "avatar", file.getOriginalFilename()); + if (userService.updateUserAvatar(SecurityUtils.getUserId(), avatar)) { + // 更新缓存用户头像 + LoginUser loginUser = SecurityUtils.getLoginUser(); + loginUser.getUser().setAvatar(avatar); + tokenService.refreshToken(loginUser); + return R.ok(avatar); + } + } + return R.error("上传头像异常,请联系管理员"); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/controller/UserOnlineController.java --- +package com.starry.admin.modules.system.controller; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.starry.admin.common.domain.LoginUser; +import com.starry.admin.modules.system.module.entity.UserOnline; +import com.starry.admin.modules.system.service.UserOnlineService; +import com.starry.common.annotation.Log; +import com.starry.common.constant.CacheConstants; +import com.starry.common.enums.BusinessType; +import com.starry.common.redis.RedisCache; +import com.starry.common.result.R; +import com.starry.common.utils.StringUtils; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import javax.annotation.Resource; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +/** + * @author huoqiang 在线用户监控 + * @since 2022/10/18 + */ +@Api(tags = "在线用户监控", description = "系统在线用户监控相关接口") +@RestController +@RequestMapping("/monitor/online") +public class UserOnlineController { + + @Resource + private RedisCache redisCache; + @Resource + private UserOnlineService userOnlineService; + + @ApiOperation(value = "查询在线用户列表", notes = "根据IP地址和用户名查询在线用户") + @ApiImplicitParams({@ApiImplicitParam(name = "ipaddr", value = "IP地址", dataType = "String", paramType = "query"), + @ApiImplicitParam(name = "userName", value = "用户名", dataType = "String", paramType = "query")}) + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = UserOnline.class, responseContainer = "Page")}) + @PreAuthorize("@customSs.hasPermission('monitor:online:list')") + @GetMapping("/list") + public R list(String ipaddr, String userName) { + Collection keys = redisCache.keys(CacheConstants.LOGIN_TOKEN_KEY + "*"); + List userOnlineList = new ArrayList<>(); + for (String key : keys) { + LoginUser user = redisCache.getCacheObject(key); + if (StrUtil.isNotBlank(ipaddr) && StrUtil.isNotBlank(userName)) { + if (StringUtils.equals(ipaddr, user.getIpaddr()) && StringUtils.equals(userName, user.getUsername())) { + userOnlineList.add(userOnlineService.selectOnlineByInfo(ipaddr, userName, user)); + } + } else if (StrUtil.isNotBlank(ipaddr)) { + if (StringUtils.equals(ipaddr, user.getIpaddr())) { + userOnlineList.add(userOnlineService.selectOnlineByIpaddr(ipaddr, user)); + } + } else if (StrUtil.isNotBlank(userName) && StringUtils.isNotNull(user.getUser())) { + if (StringUtils.equals(userName, user.getUsername())) { + userOnlineList.add(userOnlineService.selectOnlineByUserName(userName, user)); + } + } else { + userOnlineList.add(userOnlineService.setUserOnline(user)); + } + } + IPage page = new Page<>(); + page.setRecords(userOnlineList); + page.setTotal(userOnlineList.size()); + return R.ok(page); + } + + /** + * 强退用户 + */ + @ApiOperation(value = "强制退出用户", notes = "强制指定token的用户下线") + @ApiImplicitParam(name = "tokenId", value = "用户token", required = true, dataType = "String", paramType = "path") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @PreAuthorize("@customSs.hasPermission('monitor:online:forceLogout')") + @Log(title = "在线用户", businessType = BusinessType.FORCE) + @DeleteMapping("/{tokenId}") + public R forceLogout(@PathVariable String tokenId) { + redisCache.deleteObject(CacheConstants.LOGIN_TOKEN_KEY + tokenId); + return R.ok(); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/mapper/SysAdministrativeAreaDictInfoMapper.java --- +package com.starry.admin.modules.system.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.starry.admin.modules.system.module.entity.SysAdministrativeAreaDictInfoEntity; +import org.apache.ibatis.annotations.Mapper; + +; + +/** + * 行政区域字典信息Mapper接口 + * + * @author admin + * @since 2024-04-03 + */ +@Mapper +public interface SysAdministrativeAreaDictInfoMapper extends BaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/mapper/SysDeptMapper.java --- +package com.starry.admin.modules.system.mapper; + +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.starry.admin.modules.system.module.entity.SysDeptEntity; +import java.util.List; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 部门表 Mapper 接口 + *

+ * + * @author admin + * @since 2022-07-12 + */ +@Mapper +public interface SysDeptMapper extends BaseMapper { + + /** + * 查询部门管理数据 + * + * @param dept + * 部门信息 + * @return 部门信息集合 + */ + List selectDeptList(@Param(value = "dept") SysDeptEntity dept); + + /** + * 根据ID查询所有子部门 + * + * @param deptId + * 部门ID + * @return 部门列表 + */ + List selectChildrenDeptById(Long deptId); + + /** + * 删除部门信息-根据租户ID + * + * @param ids + * 租户id + * @return 结果 + */ + @InterceptorIgnore(tenantLine = "1") + int deleteDeptByTenantId(String[] ids); + + /** + * 根据角色ID查询部门树信息 + * + * @param roleId + * 角色ID + * @param deptCheckStrictly + * 部门树选择项是否关联显示 + * @return 选中部门列表 + */ + List selectDeptListByRoleId(@Param("roleId") Long roleId, + @Param("deptCheckStrictly") boolean deptCheckStrictly); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/mapper/SysDictDataMapper.java --- +package com.starry.admin.modules.system.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.starry.admin.modules.system.module.entity.SysDictDataEntity; +import com.starry.admin.modules.system.vo.SysDictDataVo; +import java.util.List; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + * 字典数据表Mapper接口 + * + * @author admin + */ +@Mapper +public interface SysDictDataMapper extends BaseMapper { + /** + * 查询字典数据表 + * + * @param dictDataId + * 字典数据表主键 + * @return 字典数据表 + */ + SysDictDataEntity selectXlDictDataByDictDataId(Long dictDataId); + + /** + * 查询字典数据表列表 + * + * @param sysDictDataEntity + * 字典数据表 + * @return 字典数据表集合 + */ + IPage selectXlDictDataList(Page page, + @Param("vo") SysDictDataVo sysDictDataEntity); + + /** + * 根据字典类型查询字典数据 + * + * @param dictType + * 字典类型 + * @return 字典数据集合信息 + */ + List selectDictDataByType(String dictType); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/mapper/SysDictMapper.java --- +package com.starry.admin.modules.system.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.starry.admin.modules.system.module.entity.SysDictEntity; +import com.starry.admin.modules.system.vo.SysDictVo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + * 字典表Mapper接口 + * + * @author admin + */ +@Mapper +public interface SysDictMapper extends BaseMapper { + /** + * 查询字典表 + * + * @param dictId + * 字典表主键 + * @return 字典表 + */ + SysDictEntity selectXlDictByDictId(Long dictId); + + /** + * 查询字典表列表 + * + * @param sysDictEntity + * 字典表 + * @return 字典表集合 + */ + Page selectXlDictList(IPage page, + @Param(value = "sysDictVo") SysDictVo sysDictEntity); + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/mapper/SysLoginLogMapper.java --- +package com.starry.admin.modules.system.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.starry.admin.modules.system.module.entity.SysLoginLogEntity; +import com.starry.admin.modules.system.module.entity.SysLoginLogVo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + * 系统访问日志表Mapper接口 + * + * @author admin + */ +@Mapper +public interface SysLoginLogMapper extends BaseMapper { + /** + * 查询系统访问日志表 + * + * @param loginId + * 系统访问日志表主键 + * @return 系统访问日志表 + */ + SysLoginLogEntity selectXlLoginLogByLoginId(Long loginId); + + /** + * 查询系统访问日志表列表 + * + * @param sysLoginLogEntity + * 系统访问日志表 + * @return 系统访问日志表集合 + */ + IPage selectXlLoginLogList(Page page, + @Param("vo") SysLoginLogVo sysLoginLogEntity); + + /** + * 清空系统登录日志 + * + * @return 结果 + */ + int cleanLoginlog(); + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/mapper/SysMenuMapper.java --- +package com.starry.admin.modules.system.mapper; + +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.starry.admin.modules.system.module.entity.SysMenuEntity; +import com.starry.admin.modules.system.vo.SimpleMenu; +import java.util.List; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 菜单表 Mapper 接口 + *

+ * + * @author admin + * @since 2022-07-03 + */ +@Mapper +public interface SysMenuMapper extends BaseMapper { + + List selectMenuListByUserId(@Param(value = "menu") SysMenuEntity menu, + @Param(value = "userId") String userId, Page page); + + /** + * 查询系统菜单列表 + * + * @param menu + * 菜单信息 + * @return 菜单列表 + */ + List selectMenuList(SysMenuEntity menu); + + List selectMenuListByUserId(@Param(value = "menu") SysMenuEntity menu, + @Param(value = "userId") String userId); + + /** + * 根据角色ID查询菜单树信息 + * + * @param roleId + * 角色ID + * @param menuCheckStrictly + * 菜单树选择项是否关联显示 + * @return 选中菜单列表 + */ + List selectMenuListByRoleId(@Param("roleId") Long roleId, + @Param("menuCheckStrictly") boolean menuCheckStrictly); + + /** + * 根据用户ID查询权限 + * + * @param userId + * 用户ID + * @return 权限列表 + */ + @InterceptorIgnore(tenantLine = "1") + List selectMenuPermsByUserId(String userId); + + /** + * 查询菜单 + * + * @return 菜单列表 + */ + List selectMenuTreeAll(); + + /** + * 根据用户ID查询菜单 + * + * @param userId + * 用户ID + * @return 菜单列表 + */ + List selectMenuTreeByUserId(String userId); + + /** + * 查询所有开启状态菜单精简信息 + * + * @return 菜单列表 + */ + List selectSimpleMenuList(); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/mapper/SysOperationLogMapper.java --- +package com.starry.admin.modules.system.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.starry.admin.modules.system.module.entity.SysOperationLogEntity; +import com.starry.admin.modules.system.vo.SysOperationLogVo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + * 操作日志表Mapper接口 + * + * @author admin + */ +@Mapper +public interface SysOperationLogMapper extends BaseMapper { + /** + * 查询操作日志表 + * + * @param operId + * 操作日志表主键 + * @return 操作日志表 + */ + SysOperationLogEntity selectXlOperLogByOperId(Long operId); + + /** + * 查询操作日志表列表 + * + * @param sysOperationLogEntity + * 操作日志表 + * @return 操作日志表集合 + */ + IPage selectXlOperLogList(Page page, + @Param("vo") SysOperationLogVo sysOperationLogEntity); + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/mapper/SysRoleDeptMapper.java --- +package com.starry.admin.modules.system.mapper; + +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.starry.admin.modules.system.module.entity.SysRoleDeptEntity; +import java.util.List; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 角色和部门关联表 Mapper 接口 + *

+ * + * @author admin + * @since 2022-07-06 + */ +@Mapper +public interface SysRoleDeptMapper extends BaseMapper { + + /** + * 通过租户ID删除角色和部门关联 + * + * @param tenantId + * 租户ID + * @return 结果 + */ + @InterceptorIgnore(tenantLine = "1") + int deleteRoleDeptByTenantId(Long tenantId); + + /** + * 通过角色ID删除角色和部门关联 + * + * @param roleId + * 角色ID + * @return 结果 + */ + int deleteRoleDeptByRoleId(Long roleId); + + /** + * 批量新增角色部门信息 + * + * @param roleDeptList + * 角色部门列表 + * @return 结果 + */ + int batchRoleDept(List roleDeptList); + + /** + * 批量删除角色部门关联信息 + * + * @param ids + * 需要删除的数据ID + * @return 结果 + */ + int deleteRoleDept(Long[] ids); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/mapper/SysRoleMapper.java --- +package com.starry.admin.modules.system.mapper; + +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.starry.admin.modules.system.module.entity.SysRoleEntity; +import java.util.List; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 角色表 Mapper 接口 + *

+ * + * @author admin + * @since 2022-07-01 + */ +@Mapper +public interface SysRoleMapper extends BaseMapper { + + /** + * 通过角色ID查询角色 + * + * @param roleId + * 角色ID + * @return 角色对象信息 + */ + SysRoleEntity selectRoleById(Long roleId); + + /** + * 校验角色名称是否唯一 + * + * @param roleName + * 角色名称 + * @return 角色信息 + */ + SysRoleEntity checkRoleNameUnique(String roleName); + + /** + * 校验角色权限是否唯一 + * + * @param roleKey + * 角色权限 + * @return 角色信息 + */ + SysRoleEntity checkRoleKeyUnique(String roleKey); + + /** + * 根据用户ID查询角色 + * + * @param userId + * 用户ID + * @return 角色列表 + */ + List selectRolePermissionByUserId(String userId); + + /** + * 根据条件分页查询角色数据 + * + * @param role + * 角色信息 + * @return 角色数据集合信息 + */ + List selectRoleList(SysRoleEntity role); + + /** + * 根据租户ID查询默认管理员角色 + * + * @param tenantId + * 租户ID + * @return 角色 + */ + @InterceptorIgnore(tenantLine = "1") + List queryAdminRole(String tenantId); + + /** + * 批量删除角色信息-根据租户 + * + * @param ids + * 需要删除的租户id + * @return 结果 + */ + @InterceptorIgnore(tenantLine = "1") + int deleteRoleByTenantId(String[] ids); + + /** + * 通过角色ID查询角色使用数量 + * + * @param roleId + * 角色ID + * @return 结果 + */ + int countUserRoleByRoleId(Long roleId); + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/mapper/SysRoleMenuMapper.java --- +package com.starry.admin.modules.system.mapper; + +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.starry.admin.modules.system.module.entity.SysRoleMenuEntity; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 角色和菜单关联表 Mapper 接口 + *

+ * + * @author admin + * @since 2022-07-06 + */ +@Mapper +public interface SysRoleMenuMapper extends BaseMapper { + + /** + * 通过租户ID删除角色和菜单关联 + * + * @param tenantId + * 租户ID + * @return 结果 + */ + @InterceptorIgnore(tenantLine = "1") + int deleteRoleMenuByTenantId(String tenantId); + + /** + * 通过租户ID删除角色和菜单关联 + * + * @param ids + * 租户ID + * @return 结果 + */ + @InterceptorIgnore(tenantLine = "1") + int deleteRoleMenuByTenantIds(String[] ids); + + /** + * 批量删除角色菜单关联信息 + * + * @param ids + * 需要删除的数据ID + * @return 结果 + */ + int deleteRoleMenu(Long[] ids); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/mapper/SysTenantMapper.java --- +package com.starry.admin.modules.system.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.starry.admin.modules.system.module.entity.SysTenantEntity; +import com.starry.admin.modules.system.vo.SysTenantQueryVo; +import com.starry.admin.modules.system.vo.TenantResultVo; +import org.apache.ibatis.annotations.Param; + +/** + * 租户表Mapper接口 + * + * @author admin + * @since 2023-03-03 + */ +public interface SysTenantMapper extends BaseMapper { + /** + * 查询租户表 + * + * @param tenantId + * 租户表主键 + * @return 租户表 + */ + SysTenantEntity selectSysTenantByTenantId(String tenantId); + + /** + * 查询租户表列表 + * + * @param page + * 分页参数 + * @param sysTenantEntity + * 租户表 + * @return 租户表集合 + */ + IPage selectSysTenantList(Page page, @Param("vo") SysTenantQueryVo sysTenantEntity); + + /** + * 批量删除租户管理 + * + * @param ids + * 需要删除的数据主键集合 + * @return 结果 + */ + int deleteTenantByIds(String[] ids); + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/mapper/SysTenantPackageMapper.java --- +package com.starry.admin.modules.system.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.starry.admin.modules.system.module.entity.SysTenantPackageEntity; +import com.starry.admin.modules.system.vo.SimplePackage; +import com.starry.admin.modules.system.vo.SysTenantPackageVo; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + * 租户套餐表Mapper接口 + * + * @author admin + */ +public interface SysTenantPackageMapper extends BaseMapper { + /** + * 查询租户套餐表 + * + * @param packageId + * 租户套餐表主键 + * @return 租户套餐表 + */ + SysTenantPackageEntity selectSysTenantPackageByPackageId(String packageId); + + /** + * 查询租户套餐表列表 + * + * @param sysTenantPackageEntity + * 租户套餐表 + * @return 租户套餐表集合 + */ + IPage selectSysTenantPackageList(Page page, + @Param("vo") SysTenantPackageVo sysTenantPackageEntity); + + /** + * 查询租户套餐 + * + * @return 租户套餐 + */ + List getSimpleList(); + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/mapper/SysTenantRechargeInfoMapper.java --- +package com.starry.admin.modules.system.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.starry.admin.modules.system.module.entity.SysTenantRechargeInfoEntity; + +/** + * 租户充值信息Mapper接口 + * + * @author admin + * @since 2024-09-05 + */ +public interface SysTenantRechargeInfoMapper extends MPJBaseMapper { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/mapper/SysUserMapper.java --- +package com.starry.admin.modules.system.mapper; + +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.github.yulichang.base.MPJBaseMapper; +import com.starry.admin.modules.system.module.entity.SysUserEntity; +import com.starry.admin.modules.system.vo.RoleUserResultVo; +import com.starry.admin.modules.system.vo.SysUserQueryVo; +import com.starry.admin.modules.system.vo.UserQueryVo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 后台用户表 Mapper 接口 + *

+ * + * @author admin + * @since 2021-09-03 + */ +@Mapper +public interface SysUserMapper extends MPJBaseMapper { + + /** + * 通过用户ID查询用户 + * + * @param userId + * 用户ID + * @return 用户对象信息 + */ + SysUserEntity selectUserById(String userId); + + /** + * 根据条件分页查询用户列表 + * + * @param queryVo + * 条件信息 + * @param page + * 分页信息 + * @return 用户信息集合信息 + */ + IPage selectUserList(IPage page, @Param("user") UserQueryVo queryVo); + + /** + * 通过用户名查询用户 + * + * @param userName + * 用户名 + * @return 用户对象信息 + */ + @InterceptorIgnore(tenantLine = "1") + SysUserEntity selectUserByUserName(String userName); + + /** + * 校验用户名称是否唯一 + * + * @param userName + * 用户名称 + * @return 结果 + */ + @InterceptorIgnore(tenantLine = "1") + int checkUserNameUnique(String userName); + + /** + * 批量删除用户信息-根据租户 + * + * @param ids + * 需要删除的租户ID + * @return 结果 + */ + @InterceptorIgnore(tenantLine = "1") + int deleteUserByTenantId(String[] ids); + + /** + * 根据条件分页查询已配用户角色列表 + * + * @param user + * 用户信息 + * @return 用户信息集合信息 + */ + IPage selectAllocatedList(Page page, @Param("query") SysUserQueryVo user); + + /** + * 根据条件分页查询未配用户角色列表 + * + * @param user + * 用户信息 + * @return 用户信息集合信息 + */ + IPage selectUnallocatedList(Page page, @Param("query") SysUserQueryVo user); + + @InterceptorIgnore(tenantLine = "1") + SysUserEntity selectUserByUserNameAndTenantId(@Param("userName") String userName, + @Param("tenantId") String tenantId); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/mapper/SysUserRoleMapper.java --- +package com.starry.admin.modules.system.mapper; + +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.starry.admin.modules.system.module.entity.SysUserRoleEntity; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 用户角色关联表 Mapper 接口 + *

+ * + * @author admin + * @since 2022-07-08 + */ +@Mapper +public interface SysUserRoleMapper extends BaseMapper { + + /** + * 批量删除用户和角色关联-根据租户 + * + * @param ids + * 需要删除的用户租户id + * @return 结果 + */ + @InterceptorIgnore(tenantLine = "1") + int deleteUserRoleByTenantId(String[] ids); + + /** + * 删除用户和角色关联信息 + * + * @param userRole + * 用户和角色关联信息 + * @return 结果 + */ + int deleteUserRoleInfo(SysUserRoleEntity userRole); + + /** + * 批量取消授权用户角色 + * + * @param roleId + * 角色ID + * @param userIds + * 需要删除的用户数据ID + * @return 结果 + */ + int deleteUserRoleInfos(@Param("roleId") Long roleId, @Param("userIds") String[] userIds); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/module/entity/Cache.java --- +package com.starry.admin.modules.system.module.entity; + +import com.starry.common.utils.StringUtils; +import lombok.Data; + +/** + * @author admin 缓存信息 + * @since 2022/10/18 + */ +@Data +public class Cache { + + /** + * 缓存名称 + */ + private String cacheName = ""; + + /** + * 缓存键名 + */ + private String cacheKey = ""; + + /** + * 缓存内容 + */ + private String cacheValue = ""; + + /** + * 备注 + */ + private String remark = ""; + + public Cache() { + + } + + public Cache(String cacheName, String remark) { + this.cacheName = cacheName; + this.remark = remark; + } + + public Cache(String cacheName, String cacheKey, String cacheValue) { + this.cacheName = StringUtils.replace(cacheName, ":", ""); + this.cacheKey = StringUtils.replace(cacheKey, cacheName, ""); + this.cacheValue = cacheValue; + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/module/entity/Cpu.java --- +package com.starry.admin.modules.system.module.entity; + +import com.starry.common.utils.Arith; +import lombok.Data; + +/** + * @author admin cpu相关信息 + * @since 2022/10/17 + */ +@Data +public class Cpu { + + /** + * 核心数 + */ + private int cpuNum; + + /** + * CPU总的使用率 + */ + private double total; + + /** + * CPU系统使用率 + */ + private double sys; + + /** + * CPU用户使用率 + */ + private double used; + + /** + * CPU当前等待率 + */ + private double wait; + + /** + * CPU当前空闲率 + */ + private double free; + + public int getCpuNum() { + return cpuNum; + } + + public void setCpuNum(int cpuNum) { + this.cpuNum = cpuNum; + } + + public double getTotal() { + return Arith.round(Arith.mul(total, 100), 2); + } + + public void setTotal(double total) { + this.total = total; + } + + public double getSys() { + return Arith.round(Arith.mul(sys / total, 100), 2); + } + + public void setSys(double sys) { + this.sys = sys; + } + + public double getUsed() { + return Arith.round(Arith.mul(used / total, 100), 2); + } + + public void setUsed(double used) { + this.used = used; + } + + public double getWait() { + return Arith.round(Arith.mul(wait / total, 100), 2); + } + + public void setWait(double wait) { + this.wait = wait; + } + + public double getFree() { + return Arith.round(Arith.mul(free / total, 100), 2); + } + + public void setFree(double free) { + this.free = free; + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/module/entity/Jvm.java --- +package com.starry.admin.modules.system.module.entity; + +import cn.hutool.core.date.DateUtil; +import com.starry.common.utils.Arith; +import java.lang.management.ManagementFactory; +import java.util.Date; + +/** + * @author admin 虚拟机相关信息 + * @since 2022/10/17 + */ + +public class Jvm { + + /** + * 当前JVM占用的内存总数(M) + */ + private double total; + + /** + * JVM最大可用内存总数(M) + */ + private double max; + + /** + * JVM空闲内存(M) + */ + private double free; + + /** + * JDK版本 + */ + private String version; + + /** + * JDK路径 + */ + private String home; + + public double getTotal() { + return Arith.div(total, (1024 * 1024), 2); + } + + public void setTotal(double total) { + this.total = total; + } + + public double getMax() { + return Arith.div(max, (1024 * 1024), 2); + } + + public void setMax(double max) { + this.max = max; + } + + public double getFree() { + return Arith.div(free, (1024 * 1024), 2); + } + + public void setFree(double free) { + this.free = free; + } + + public double getUsed() { + return Arith.div(total - free, (1024 * 1024), 2); + } + + public double getUsage() { + return Arith.mul(Arith.div(total - free, total, 4), 100); + } + + /** + * 获取JDK名称 + */ + public String getName() { + return ManagementFactory.getRuntimeMXBean().getVmName(); + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getHome() { + return home; + } + + public void setHome(String home) { + this.home = home; + } + + /** + * JDK启动时间 + */ + public String getStartTime() { + return DateUtil.format(new Date(ManagementFactory.getRuntimeMXBean().getStartTime()), "yyyy-MM-dd HH:mm:ss"); + } + + /** + * JDK运行时间 + */ + public String getRunTime() { + return DateUtil.formatBetween(new Date(), new Date(ManagementFactory.getRuntimeMXBean().getStartTime())); + } + + /** + * 运行参数 + */ + public String getInputArgs() { + return ManagementFactory.getRuntimeMXBean().getInputArguments().toString(); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/module/entity/Mem.java --- +package com.starry.admin.modules.system.module.entity; + +import com.starry.common.utils.Arith; +import lombok.Data; + +/** + * @author admin 内存相关信息 + * @since 2022/10/17 + */ +@Data +public class Mem { + + /** + * 内存总量 + */ + private double total; + + /** + * 已用内存 + */ + private double used; + + /** + * 剩余内存 + */ + private double free; + + public double getTotal() { + return Arith.div(total, (1024 * 1024 * 1024), 2); + } + + public void setTotal(long total) { + this.total = total; + } + + public double getUsed() { + return Arith.div(used, (1024 * 1024 * 1024), 2); + } + + public void setUsed(long used) { + this.used = used; + } + + public double getFree() { + return Arith.div(free, (1024 * 1024 * 1024), 2); + } + + public void setFree(long free) { + this.free = free; + } + + public double getUsage() { + return Arith.mul(Arith.div(used, total, 4), 100); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/module/entity/Server.java --- +package com.starry.admin.modules.system.module.entity; + +import com.starry.common.utils.Arith; +import com.starry.common.utils.ip.IpUtils; +import java.net.UnknownHostException; +import java.util.LinkedList; +import java.util.List; +import java.util.Properties; +import lombok.Data; +import oshi.SystemInfo; +import oshi.hardware.CentralProcessor; +import oshi.hardware.GlobalMemory; +import oshi.hardware.HardwareAbstractionLayer; +import oshi.software.os.FileSystem; +import oshi.software.os.OSFileStore; +import oshi.software.os.OperatingSystem; +import oshi.util.Util; + +/** + * @author admin 服务器相关信息 + * @since 2022/10/17 + */ +@Data +public class Server { + + /** + * CPU相关信息 + */ + private Cpu cpu = new Cpu(); + + /** + * 內存相关信息 + */ + private Mem mem = new Mem(); + + /** + * JVM相关信息 + */ + private Jvm jvm = new Jvm(); + + /** + * 系统相关信息 + */ + private Sys sys = new Sys(); + + /** + * 磁盘相关信息 + */ + private List sysFiles = new LinkedList<>(); + + public void setServeInfo() throws Exception { + // 系统信息 + SystemInfo si = new SystemInfo(); + // 获取硬件抽象层 + HardwareAbstractionLayer hal = si.getHardware(); + setCpuInfo(hal.getProcessor()); + setMemInfo(hal.getMemory()); + setSysInfo(); + setJvmInfo(); + setSysFiles(si.getOperatingSystem()); + } + + /** + * 设置CPU信息 + */ + private void setCpuInfo(CentralProcessor processor) { + // CPU信息 + long[] prevTicks = processor.getSystemCpuLoadTicks(); + Util.sleep(1000); + long[] ticks = processor.getSystemCpuLoadTicks(); + long nice = ticks[CentralProcessor.TickType.NICE.getIndex()] + - prevTicks[CentralProcessor.TickType.NICE.getIndex()]; + long irq = ticks[CentralProcessor.TickType.IRQ.getIndex()] + - prevTicks[CentralProcessor.TickType.IRQ.getIndex()]; + long softirq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()] + - prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()]; + long steal = ticks[CentralProcessor.TickType.STEAL.getIndex()] + - prevTicks[CentralProcessor.TickType.STEAL.getIndex()]; + long cSys = ticks[CentralProcessor.TickType.SYSTEM.getIndex()] + - prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()]; + long user = ticks[CentralProcessor.TickType.USER.getIndex()] + - prevTicks[CentralProcessor.TickType.USER.getIndex()]; + long iowait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()] + - prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()]; + long idle = ticks[CentralProcessor.TickType.IDLE.getIndex()] + - prevTicks[CentralProcessor.TickType.IDLE.getIndex()]; + long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal; + cpu.setCpuNum(processor.getLogicalProcessorCount()); + cpu.setTotal(totalCpu); + cpu.setSys(cSys); + cpu.setUsed(user); + cpu.setWait(iowait); + cpu.setFree(idle); + } + + /** + * 设置内存信息 + */ + private void setMemInfo(GlobalMemory memory) { + mem.setTotal(memory.getTotal()); + mem.setUsed(memory.getTotal() - memory.getAvailable()); + mem.setFree(memory.getAvailable()); + } + + /** + * 设置服务器信息 + */ + private void setSysInfo() { + Properties properties = System.getProperties(); + sys.setComputerName(IpUtils.getHostName()); + sys.setComputerIp(IpUtils.getHostIp()); + sys.setOsName(properties.getProperty("os.name")); + sys.setOsArch(properties.getProperty("os.arch")); + sys.setUserDir(properties.getProperty("user.dir")); + } + + /** + * 设置Java虚拟机 + */ + private void setJvmInfo() throws UnknownHostException { + Properties props = System.getProperties(); + jvm.setTotal(Runtime.getRuntime().totalMemory()); + jvm.setMax(Runtime.getRuntime().maxMemory()); + jvm.setFree(Runtime.getRuntime().freeMemory()); + jvm.setVersion(props.getProperty("java.version")); + jvm.setHome(props.getProperty("java.home")); + } + + /** + * 设置磁盘信息 + */ + private void setSysFiles(OperatingSystem os) { + FileSystem fileSystem = os.getFileSystem(); + List fsArray = fileSystem.getFileStores(); + for (OSFileStore fs : fsArray) { + long free = fs.getUsableSpace(); + long total = fs.getTotalSpace(); + long used = total - free; + SysFile sysFile = new SysFile(); + sysFile.setDirName(fs.getMount()); + sysFile.setSysTypeName(fs.getType()); + sysFile.setTypeName(fs.getName()); + sysFile.setTotal(convertFileSize(total)); + sysFile.setFree(convertFileSize(free)); + sysFile.setUsed(convertFileSize(used)); + sysFile.setUsage(Arith.mul(Arith.div(used, total, 4), 100)); + sysFiles.add(sysFile); + } + } + + /** + * 字节转换 + * + * @param size + * 字节大小 + * @return 转换后值 + */ + public String convertFileSize(long size) { + long kb = 1024; + long mb = kb * 1024; + long gb = mb * 1024; + if (size >= gb) { + return String.format("%.1f GB", (float) size / gb); + } else if (size >= mb) { + float f = (float) size / mb; + return String.format(f > 100 ? "%.0f MB" : "%.1f MB", f); + } else if (size >= kb) { + float f = (float) size / kb; + return String.format(f > 100 ? "%.0f KB" : "%.1f KB", f); + } else { + return String.format("%d B", size); + } + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/module/entity/Sys.java --- +package com.starry.admin.modules.system.module.entity; + +import lombok.Data; + +/** + * @author admin 系统相关信息 + * @since 2022/10/17 + */ +@Data +public class Sys { + + /** + * 服务器名称 + */ + private String computerName; + + /** + * 服务器Ip + */ + private String computerIp; + + /** + * 项目路径 + */ + private String userDir; + + /** + * 操作系统 + */ + private String osName; + + /** + * 系统架构 + */ + private String osArch; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/module/entity/SysAdministrativeAreaDictInfoEntity.java --- +package com.starry.admin.modules.system.module.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.common.domain.BaseEntity; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 行政区域字典信息对象 play_administrative_area_dict_info + * + * @author admin + * @since 2024-04-03 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("sys_administrative_area_dict_info") +public class SysAdministrativeAreaDictInfoEntity extends BaseEntity { + + /** + * UUID + */ + private String id; + + /** + * 行政单位编码 + */ + private String code; + + /** + * 新增单位名称 + */ + private String name; + + /** + * 上级单位编码 + */ + private String pCode; + + /** + * 行政单位等级 + **/ + private String level; + + /** + * 子数据 + * + * @since 2024/4/10 15:09 + **/ + @TableField(exist = false) + private List child; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/module/entity/SysDeptEntity.java --- +package com.starry.admin.modules.system.module.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.common.domain.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.ArrayList; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + *

+ * 部门表 + *

+ * + * @author admin + * @since 2022-07-12 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@TableName("sys_dept") +@ApiModel(value = "XlDept对象", description = "部门表") +public class SysDeptEntity extends BaseEntity { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键ID") + @TableId(value = "dept_id", type = IdType.AUTO) + private Long deptId; + + @ApiModelProperty("父部门id") + private Long parentId; + + @ApiModelProperty("祖级列表") + private String ancestors; + + @ApiModelProperty("部门名称") + private String deptName; + + @ApiModelProperty("显示顺序") + private Integer sort; + + @ApiModelProperty("负责人") + private String leader; + + @ApiModelProperty("联系电话") + private String phone; + + @ApiModelProperty("邮箱") + private String email; + + @ApiModelProperty("部门状态(0正常 1停用)") + private Integer status; + + @ApiModelProperty("部门级别") + private Integer deptLevel; + + @ApiModelProperty("租户ID") + private String tenantId; + + /** + * 子部门 + */ + @TableField(exist = false) + private List children = new ArrayList<>(); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/module/entity/SysDictDataEntity.java --- +package com.starry.admin.modules.system.module.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.common.domain.BaseEntity; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + * 字典数据表对象 sys_dict_data + * + * @author admin + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@TableName("sys_dict_data") +public class SysDictDataEntity extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * 主键ID + */ + @ApiModelProperty("主键ID") + @TableId(value = "dict_data_id", type = IdType.AUTO) + private Long dictDataId; + + /** + * 字典类型 + */ + private String dictType; + + /** + * 字典名称 + */ + private String dictLabel; + + /** + * 字典值 + */ + private String dictValue; + + /** + * 显示顺序 + */ + private Long sort; + + /** + * 是否默认(Y是 N否) + */ + private String isDefault; + + /** + * 表格回显样式 + */ + private String listClass; + + /** + * 状态(0正常 1停用) + */ + private Integer status; + + /** + * 备注 + */ + private String remark; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/module/entity/SysDictEntity.java --- +package com.starry.admin.modules.system.module.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.common.domain.BaseEntity; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + * 字典表对象 sys_dict + * + * @author admin + * @since 2022-08-09 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@TableName("sys_dict") +public class SysDictEntity extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * 主键ID + */ + @ApiModelProperty("主键ID") + @TableId(value = "dict_id", type = IdType.AUTO) + private Long dictId; + + /** + * 字典类型 + */ + private String dictType; + + /** + * 字典名称 + */ + private String dictName; + + /** + * 状态(0正常 1停用) + */ + private Integer status; + + /** + * 备注 + */ + private String remark; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/module/entity/SysFile.java --- +package com.starry.admin.modules.system.module.entity; + +import lombok.Data; + +/** + * @author admin 系统文件相关信息 + */ +@Data +public class SysFile { + + /** + * 盘符路径 + */ + private String dirName; + + /** + * 盘符类型 + */ + private String sysTypeName; + + /** + * 文件类型 + */ + private String typeName; + + /** + * 总大小 + */ + private String total; + + /** + * 剩余大小 + */ + private String free; + + /** + * 已经使用量 + */ + private String used; + + /** + * 资源的使用率 + */ + private double usage; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/module/entity/SysLoginLogEntity.java --- +package com.starry.admin.modules.system.module.entity; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.admin.modules.system.vo.StatusConverter; +import com.starry.common.domain.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.Date; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 系统访问日志表对象 sys_login_log + * + * @author admin + */ +@EqualsAndHashCode(callSuper = true) +@ExcelIgnoreUnannotated +@Data +@TableName("sys_login_log") +@ApiModel(value = "XlLoginLog对象", description = "登录日志表") +public class SysLoginLogEntity extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * 主键ID + */ + @ApiModelProperty("主键ID") + @TableId(value = "login_id", type = IdType.AUTO) + private Long loginId; + + /** + * 用户账号 + */ + @ExcelProperty(value = "用户账号") + private String userCode; + + /** + * 登录IP地址 + */ + @ExcelProperty(value = "登录IP地址") + private String ipaddr; + + /** + * 登录地点 + */ + @ExcelProperty(value = "登录地点") + private String loginLocation; + + /** + * 浏览器类型 + */ + @ExcelProperty(value = "浏览器类型") + private String browser; + + /** + * 操作系统 + */ + @ExcelProperty(value = "操作系统") + private String os; + + /** + * 提示消息 + */ + private String msg; + + /** + * 登录状态(0成功 1失败) + */ + @ExcelProperty(value = "登录状态", converter = StatusConverter.class) + private Integer status; + + /** + * 访问时间 + */ + private Date loginTime; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/module/entity/SysLoginLogVo.java --- +package com.starry.admin.modules.system.module.entity; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.starry.admin.modules.system.vo.StatusConverter; +import com.starry.common.domain.BasePageEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.Date; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 系统访问日志表对象 sys_login_log + * + * @author admin + */ +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel(value = "登录日志查询参数", description = "系统访问日志查询条件") +public class SysLoginLogVo extends BasePageEntity { + + private static final long serialVersionUID = 1L; + + /** + * 主键ID + */ + @ApiModelProperty(value = "日志ID", example = "1", notes = "主键ID") + @TableId(value = "login_id", type = IdType.AUTO) + private Long loginId; + + /** + * 用户账号 + */ + @ApiModelProperty(value = "用户账号", example = "admin", notes = "登录的用户账号,支持模糊查询") + @ExcelProperty(value = "用户账号") + private String userCode; + + /** + * 登录IP地址 + */ + @ApiModelProperty(value = "登录IP", example = "127.0.0.1", notes = "用户登录的IP地址") + @ExcelProperty(value = "登录IP地址") + private String ipaddr; + + /** + * 登录地点 + */ + @ApiModelProperty(value = "登录地点", example = "北京", notes = "根据IP解析的登录地理位置") + @ExcelProperty(value = "登录地点") + private String loginLocation; + + /** + * 浏览器类型 + */ + @ApiModelProperty(value = "浏览器类型", example = "Chrome", notes = "用户使用的浏览器") + @ExcelProperty(value = "浏览器类型") + private String browser; + + /** + * 操作系统 + */ + @ApiModelProperty(value = "操作系统", example = "Windows 10", notes = "用户使用的操作系统") + @ExcelProperty(value = "操作系统") + private String os; + + /** + * 提示消息 + */ + @ApiModelProperty(value = "提示消息", example = "登录成功", notes = "登录操作的提示信息") + private String msg; + + /** + * 登录状态(0成功 1失败) + */ + @ApiModelProperty(value = "登录状态", example = "0", notes = "0:成功 1:失败") + @ExcelProperty(value = "登录状态", converter = StatusConverter.class) + private Integer status; + + /** + * 访问时间 + */ + @ApiModelProperty(value = "登录时间", example = "2023-01-01 00:00:00", notes = "用户登录的时间") + private Date loginTime; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/module/entity/SysMenuEntity.java --- +package com.starry.admin.modules.system.module.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.common.domain.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.ArrayList; +import java.util.List; +import lombok.Getter; +import lombok.Setter; + +/** + *

+ * 菜单表 + *

+ * + * @author admin + * @since 2022-07-03 + */ +@Getter +@Setter +@TableName("sys_menu") +@ApiModel(value = "XlMenu对象", description = "菜单表") +public class SysMenuEntity extends BaseEntity { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("菜单ID") + @TableId(value = "menu_id", type = IdType.AUTO) + private Long menuId; + + @ApiModelProperty("菜单名") + private String menuName; + + @ApiModelProperty("菜单编码") + private String menuCode; + + @ApiModelProperty("权限字符串") + private String permission; + + @ApiModelProperty("图标") + private String icon; + + @ApiModelProperty("菜单级别") + private Long menuLevel; + + @ApiModelProperty("排序") + private Integer sort; + + @ApiModelProperty("父ID") + private Long parentId; + + @ApiModelProperty("菜单类型;0:目录,1:菜单,2:按钮") + private String menuType; + + @ApiModelProperty("菜单状态;0正常 1停用") + private Integer status; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("路由地址") + private String path; + + @ApiModelProperty("组件路径") + private String component; + + @ApiModelProperty("路由参数") + private String routerQuery; + + @ApiModelProperty("是否为外链(0否 1是)") + private Integer isFrame; + + @ApiModelProperty("菜单状态;0:隐藏 1:显示") + private Integer visible; + + /** + * 子菜单 + */ + @TableField(exist = false) + private List children = new ArrayList<>(); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/module/entity/SysOperationLogEntity.java --- +package com.starry.admin.modules.system.module.entity; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.common.domain.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.Date; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 操作日志表对象 sys_operation_log + * + * @author admin + */ +@EqualsAndHashCode(callSuper = true) +@ExcelIgnoreUnannotated +@Data +@TableName("sys_operation_log") +@ApiModel(value = "SysOperationLog对象", description = "操作日志表") +public class SysOperationLogEntity extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * 主键ID + */ + @ApiModelProperty("主键ID") + @TableId(value = "oper_id", type = IdType.AUTO) + private Long operId; + + /** + * 模块标题 + */ + @ExcelProperty(value = "系统模块") + private String title; + + /** + * 业务类型(0其它 1新增 2修改 3删除) + */ + private Integer businessType; + + /** + * 业务类型数组 + */ + @TableField(exist = false) + private Integer[] businessTypes; + + /** + * 方法名称 + */ + @ExcelProperty(value = "方法名称") + private String method; + + /** + * 请求方式 + */ + private String requestMethod; + + /** + * 操作类别(0其它 1后台用户 2手机端用户) + */ + private Integer operatorType; + + /** + * 操作人员 + */ + private String operName; + + /** + * 请求URL + */ + private String operUrl; + + /** + * 主机地址 + */ + private String operIp; + + /** + * 操作地点 + */ + private String operLocation; + + /** + * 请求参数 + */ + private String operParam; + + /** + * 返回参数 + */ + private String jsonResult; + + /** + * 操作状态(0正常 1异常) + */ + private Integer status; + + /** + * 错误消息 + */ + private String errorMsg; + + /** + * 操作时间 + */ + private Date operTime; + + /** + * 部门名称 + */ + private String deptName; + + /** + * 部门id + */ + private Long deptId; + + /** + * 租户ID + */ + private Long tenantId; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/module/entity/SysRoleDeptEntity.java --- +package com.starry.admin.modules.system.module.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.common.domain.BaseEntity; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + * 角色部门表对象 sys_dict_data + * + * @author admin + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@TableName("sys_role_dept") +public class SysRoleDeptEntity extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * 主键ID + */ + @ApiModelProperty("主键ID") + @TableId(value = "role_dept_id", type = IdType.AUTO) + private Long roleDeptId; + + @ApiModelProperty("角色ID") + private Long roleId; + + @ApiModelProperty("菜单ID") + private Long deptId; + + @ApiModelProperty("租户ID") + private Long tenantId; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/module/entity/SysRoleEntity.java --- +package com.starry.admin.modules.system.module.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.common.domain.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.Set; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + *

+ * 角色表 + *

+ * + * @author admin + * @since 2022-07-01 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@TableName("sys_role") +@NoArgsConstructor +@ApiModel(value = "XlRole对象", description = "角色表") +public class SysRoleEntity extends BaseEntity { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("角色ID") + @TableId(value = "role_id", type = IdType.AUTO) + private Long roleId; + + @ApiModelProperty("角色名称") + private String roleName; + + @ApiModelProperty("角色描述") + private String description; + + @ApiModelProperty("状态;0正常 1停用") + private Integer status; + + @ApiModelProperty("数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限;5:仅本人数据权限) ") + private String dataScope; + + @ApiModelProperty("菜单树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示)") + private boolean menuCheckStrictly; + + @ApiModelProperty("部门树选择项是否关联显示(0:父子不互相关联显示 1:父子互相关联显示 )") + private boolean deptCheckStrictly; + + @ApiModelProperty("角色权限") + private String roleKey; + + @ApiModelProperty("租户ID") + private String tenantId; + + /** + * 菜单组 + */ + @TableField(exist = false) + private Long[] menuIds; + + /** + * 部门组(数据权限) + */ + @TableField(exist = false) + private Long[] deptIds; + + /** + * 角色菜单权限 + */ + @TableField(exist = false) + private Set permissions; + + public SysRoleEntity(Long roleId) { + this.roleId = roleId; + } + + public static boolean isAdmin(Long roleId) { + return roleId != null && 1L == roleId; + } + + public boolean isAdmin() { + return isAdmin(this.roleId); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/module/entity/SysRoleMenuEntity.java --- +package com.starry.admin.modules.system.module.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.common.domain.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; + +/** + *

+ * 角色和菜单关联表 + *

+ * + * @author admin + * @since 2022-07-06 + */ +@Getter +@Setter +@TableName("sys_role_menu") +@ApiModel(value = "SysRoleMenu对象", description = "角色和菜单关联表") +public class SysRoleMenuEntity extends BaseEntity { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键id") + @TableId(value = "role_menu_id", type = IdType.AUTO) + private Long roleMenuId; + + @ApiModelProperty("角色ID") + private Long roleId; + + @ApiModelProperty("菜单ID") + private Long menuId; + + @ApiModelProperty("租户ID") + private String tenantId; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/module/entity/SysTenantEntity.java --- +package com.starry.admin.modules.system.module.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.common.domain.BaseEntity; +import io.swagger.annotations.ApiModelProperty; +import java.util.Date; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + * 租户表对象 sys_tenant + * + * @author admin + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@TableName("sys_tenant") +public class SysTenantEntity extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * 租户ID + */ + @ApiModelProperty("主键ID") + @TableId(value = "tenant_id", type = IdType.AUTO) + private String tenantId; + + /** + * 租户类型;0:公司;1:部门;2:个人;3:其他 + */ + private String tenantType; + + /** + * 用户状态;0:正常,1:停用 + */ + private String tenantStatus; + + /** + * 编码 + */ + private String tenantCode; + + /** + * 名称 + */ + private String tenantName; + + /** + * logo图 + */ + private String tenantLogo; + + /** + * 显示顺序 + */ + private Long sortOrder; + + /** + * 官方地址 + */ + private String homeUrl; + + /** + * 电话 + */ + private String phone; + + /** + * 传真 + */ + private String fax; + + /** + * 邮箱 + */ + private String email; + + /** + * 地址 + */ + private String address; + + /** + * 管理员账号 + */ + private String userName; + + /** + * 管理员密码 + */ + private String userPwd; + + /** + * 租户套餐 + */ + private String packageId; + + /** + * 租赁到期时间 + */ + private Date tenantTime; + + /** + * 租户权限标识 + */ + private String tenantKey; + + /** + * 微信公众号ID + */ + private String appId; + + /** + * 微信公众号的app secret + */ + private String secret; + + /** + * 微信商户ID + */ + private String mchId; + + /** + * 设置微信商户秘钥 + */ + private String mchKey; + + /** + * 商户秘钥 + */ + private String certificatePath; + + /** + * 备注 + */ + private String remarks; + + // 充值成功通知模板id + private String czcgtzTemplateId; + // 下单通知模板id + private String xdcgtzTemplateId; + // 收到新订单通知模板id + private String sdxddtzTemplateId; + // 认证申请审核通知模板id + private String rzsqshtxTemplateId; + // 认证申请通知for管理员 + private String rzsqAdminTemplateId; + + private String dingdantousuchuliTemplateId; + private String jiedanchenggongtongzhiTemplateId; + private String quxiaodingdantongzhiTemplateId; + private String dingdanwanchengtongzhiTemplateId; + private String chongzhichenggongTemplateId; + private String xindingdanshoulitongzhiTemplateId; + + private Integer profitsharingRate = 0; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/module/entity/SysTenantPackageEntity.java --- +package com.starry.admin.modules.system.module.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.common.domain.BaseEntity; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + * 租户套餐表对象 sys_tenant_package + * + * @author admin + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@TableName("sys_tenant_package") +public class SysTenantPackageEntity extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * 套餐id + */ + @ApiModelProperty("主键ID") + @TableId(value = "package_id", type = IdType.AUTO) + private String packageId; + + /** + * 名称 + */ + private String packageName; + + /** + * 关联菜单id + */ + private String menuIds; + + /** + * 状态;0:正常,1:停用 + */ + private String status; + + /** + * 备注 + */ + private String remarks; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/module/entity/SysTenantRechargeInfoEntity.java --- +package com.starry.admin.modules.system.module.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.starry.common.domain.BaseEntity; +import java.time.LocalDateTime; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 租户充值信息对象 sys_tenant_recharge_info + * + * @author admin + * @since 2024-09-05 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("sys_tenant_recharge_info") +public class SysTenantRechargeInfoEntity extends BaseEntity { + + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 充值金额 + */ + private String rechargeAmount; + + /** + * 充值用户 + */ + private String rechargeUser; + + /** + * 充值时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime rechargeTime; + + /** + * 支付方式,1:微信支付,2:支付宝支付;3:银行卡支付 + */ + private String payMethod; + + /** + * 支付账号 + */ + private String payAccount; + + /** + * 备注 + */ + private String remark; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/module/entity/SysUserEntity.java --- +package com.starry.admin.modules.system.module.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.starry.common.domain.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.time.LocalDateTime; +import java.util.Date; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.springframework.format.annotation.DateTimeFormat; + +/** + *

+ * 用户表 + *

+ * + * @author admin + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@ApiModel(value = "SysUser对象", description = "用户表") +@TableName("sys_user") +public class SysUserEntity extends BaseEntity { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "用户ID") + @TableId(value = "user_id", type = IdType.AUTO) + private String userId; + + @ApiModelProperty(value = "用户类型;1:admin;2:普通,废弃字段") + private Integer userType; + + @ApiModelProperty(value = "是否为超管") + private Boolean superAdmin; + + @ApiModelProperty(value = "用户名") + private String userCode; + + @ApiModelProperty(value = "密码") + private String passWord; + + @ApiModelProperty(value = "姓名") + private String realName; + + @ApiModelProperty(value = "用户昵称") + private String userNickname; + + @ApiModelProperty(value = "邮箱") + private String userEmail; + + @ApiModelProperty(value = "用户头像") + private String avatar; + + @ApiModelProperty(value = "中国手机不带国家代码,国际手机号格式为:国家代码-手机号") + private String mobile; + + @ApiModelProperty(value = "性别 0:未知;1:男;2:女") + private Integer sex; + + @ApiModelProperty(value = "出生年月") + private Date birthday; + + @ApiModelProperty(value = "用户状态;0正常 1停用") + private Integer status; + + @ApiModelProperty(value = "最后登录时间") + private Date lastLoginTime; + + @ApiModelProperty(value = "最后登录ip") + private String lastLoginIp; + + @ApiModelProperty(value = "所属部门id") + private Long deptId; + + @ApiModelProperty(value = "租户id") + private String tenantId; + + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime addTime; + + private String clerkId; + + /** + * 角色对象 + */ + @TableField(exist = false) + private List roles; + + /** + * 角色组 + */ + @TableField(exist = false) + private Long[] roleIds; + + /** + * 部门对象 + */ + @TableField(exist = false) + private SysDeptEntity dept; + + /** + * 角色ID + */ + @TableField(exist = false) + private Long roleId; + + public static boolean isAdmin(SysUserEntity user) { + return user.getSuperAdmin(); + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/module/entity/SysUserRoleEntity.java --- +package com.starry.admin.modules.system.module.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.common.domain.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; + +/** + *

+ * 用户角色关联表 + *

+ * + * @author admin + * @since 2022-07-08 + */ +@Getter +@Setter +@TableName("sys_user_role") +@ApiModel(value = "SysUserRole对象", description = "用户角色关联表") +public class SysUserRoleEntity extends BaseEntity { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键ID") + @TableId(value = "user_role_id", type = IdType.AUTO) + private Long userRoleId; + + @ApiModelProperty("用户ID") + private String userId; + + @ApiModelProperty("角色ID") + private Long roleId; + + @ApiModelProperty(value = "租户id") + private String tenantId; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/module/entity/UserOnline.java --- +package com.starry.admin.modules.system.module.entity; + +import lombok.Data; + +/** + * @author admin 当前在线会话 + */ +@Data +public class UserOnline { + /** + * 会话编号 + */ + private String tokenId; + + /** + * 部门名称 + */ + private String deptName; + + /** + * 用户名称 + */ + private String userName; + + /** + * 登录IP地址 + */ + private String ipaddr; + + /** + * 登录地址 + */ + private String loginLocation; + + /** + * 浏览器类型 + */ + private String browser; + + /** + * 操作系统 + */ + private String os; + + /** + * 登录时间 + */ + private Long loginTime; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/module/vo/SysTenantRechargeInfoAddVo.java --- +package com.starry.admin.modules.system.module.vo; + +import java.time.LocalDateTime; +import lombok.Data; + +/** + * @author admin + * @since 2024/9/5 下午3:44 + **/ +@Data +public class SysTenantRechargeInfoAddVo { + + /** + * 充值金额 + */ + private String rechargeAmount; + + /** + * 充值用户 + */ + private String rechargeUser; + + /** + * 充值时间 + */ + private LocalDateTime rechargeTime = LocalDateTime.now(); + + /** + * 支付方式,1:微信支付,2:支付宝支付;3:银行卡支付 + */ + private String payMethod; + + /** + * 支付账号 + */ + private String payAccount; + + /** + * 备注 + */ + private String remark; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/module/vo/SysTenantRechargeInfoQueryVo.java --- +package com.starry.admin.modules.system.module.vo; + +import com.starry.common.domain.BasePageEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @author admin + * @since 2024/9/5 下午3:44 + **/ +@EqualsAndHashCode(callSuper = true) +@Data +public class SysTenantRechargeInfoQueryVo extends BasePageEntity { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/module/vo/SysTenantRechargeInfoReturnVo.java --- +package com.starry.admin.modules.system.module.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import java.time.LocalDateTime; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * @author admin + * @since 2024/9/5 下午3:44 + **/ +@Data +public class SysTenantRechargeInfoReturnVo { + private String id; + + /** + * 充值金额 + */ + private String rechargeAmount; + + /** + * 充值用户 + */ + private String rechargeUser; + + /** + * 充值用户 + */ + private String rechargeName; + + /** + * 充值时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime rechargeTime; + + /** + * 支付方式,1:微信支付,2:支付宝支付;3:银行卡支付 + */ + private String payMethod; + + /** + * 支付账号 + */ + private String payAccount; + + /** + * 备注 + */ + private String remark; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/service/ISysAdministrativeAreaDictInfoService.java --- +package com.starry.admin.modules.system.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.system.module.entity.SysAdministrativeAreaDictInfoEntity; +import com.starry.admin.modules.system.vo.AdministrativeAreaQueryReturnVo; +import java.util.List; + +/** + * 行政区域字典信息Service接口 + * + * @author admin + * @since 2024-04-03 + */ +public interface ISysAdministrativeAreaDictInfoService extends IService { + + /** + * 查询行政区域字典信息 + * + * @param id + * 行政区域字典信息主键 + * @return 行政区域字典信息 + */ + SysAdministrativeAreaDictInfoEntity selectPlayAdministrativeAreaDictInfoById(String id); + + /** + * 查询树形接口的区域信息 + * + * @param level + * 行政区域等级(1:省级别,2:城市级别:4:区县级别) + * @return List + * @author admin + * @since 2024/4/10 14:47 + **/ + List selectTree(String level); + + /** + * 查询所有行政区域字典信息列表 + * + * @return 行政区域字典信息集合 + */ + List selectAll(); + + /** + * 查询行政区域字典信息列表 + * + * @param playAdministrativeAreaDictInfo + * 行政区域字典信息 + * @return 行政区域字典信息集合 + */ + IPage selectPlayAdministrativeAreaDictInfoByPage( + SysAdministrativeAreaDictInfoEntity playAdministrativeAreaDictInfo); + + /** + * 新增行政区域字典信息 + * + * @param playAdministrativeAreaDictInfo + * 行政区域字典信息 + * @return 结果 + */ + boolean create(SysAdministrativeAreaDictInfoEntity playAdministrativeAreaDictInfo); + + boolean create(List list); + + /** + * 修改行政区域字典信息 + * + * @param playAdministrativeAreaDictInfo + * 行政区域字典信息 + * @return 结果 + */ + boolean update(SysAdministrativeAreaDictInfoEntity playAdministrativeAreaDictInfo); + + /** + * 批量删除行政区域字典信息 + * + * @param ids + * 需要删除的行政区域字典信息主键集合 + * @return 结果 + */ + int deletePlayAdministrativeAreaDictInfoByIds(String[] ids); + + /** + * 删除行政区域字典信息信息 + * + * @param id + * 行政区域字典信息主键 + * @return 结果 + */ + int deletePlayAdministrativeAreaDictInfoById(String id); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/service/ISysDictDataService.java --- +package com.starry.admin.modules.system.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.system.module.entity.SysDictDataEntity; +import com.starry.admin.modules.system.vo.SysDictDataVo; +import java.util.List; + +/** + * 字典数据表Service接口 + * + * @author admin + */ +public interface ISysDictDataService extends IService { + /** + * 查询字典数据表 + * + * @param dictDataId + * 字典数据表主键 + * @return 字典数据表 + */ + SysDictDataEntity selectXlDictDataByDictDataId(Long dictDataId); + + /** + * 查询字典数据表列表 + * + * @param sysDictDataEntity + * 字典数据表 + * @return 字典数据表集合 + */ + IPage selectXlDictDataList(SysDictDataVo sysDictDataEntity); + + /** + * 新增字典数据表 + * + * @param sysDictDataEntity + * 字典数据表 + * @return 结果 + */ + boolean create(SysDictDataEntity sysDictDataEntity); + + /** + * 修改字典数据表 + * + * @param sysDictDataEntity + * 字典数据表 + * @return 结果 + */ + boolean update(SysDictDataEntity sysDictDataEntity); + + /** + * 批量删除字典数据表 + * + * @param dictDataIds + * 需要删除的字典数据表主键集合 + * @return 结果 + */ + int deleteXlDictDataByDictDataIds(Long[] dictDataIds); + + /** + * 删除字典数据表信息 + * + * @param dictDataId + * 字典数据表主键 + * @return 结果 + */ + int deleteXlDictDataByDictDataId(Long dictDataId); + + /** + * 根据字典类型查询字典数据 + * + * @param dictType + * 字典类型 + * @return 字典数据集合信息 + */ + List selectDictDataByType(String dictType); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/service/ISysDictService.java --- +package com.starry.admin.modules.system.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.system.module.entity.SysDictEntity; +import com.starry.admin.modules.system.vo.SysDictVo; +import java.util.List; + +/** + * 字典表Service接口 + * + * @author admin + * @since 2022-08-09 + */ +public interface ISysDictService extends IService { + /** + * 查询字典表 + * + * @param dictId + * 字典表主键 + * @return 字典表 + */ + SysDictEntity selectXlDictByDictId(Long dictId); + + /** + * 查询字典表列表 + * + * @param sysDictVo + * 字典表 + * @return 字典表集合 + */ + Page selectXlDictList(SysDictVo sysDictVo); + + /** + * 新增字典表 + * + * @param sysDictEntity + * 字典表 + * @return 结果 + */ + boolean create(SysDictEntity sysDictEntity); + + /** + * 修改字典表 + * + * @param sysDictEntity + * 字典表 + * @return 结果 + */ + boolean update(SysDictEntity sysDictEntity); + + /** + * 批量删除字典表 + * + * @param dictIds + * 需要删除的字典表主键集合 + * @return 结果 + */ + int deleteXlDictByDictIds(Long[] dictIds); + + /** + * 删除字典表信息 + * + * @param dictId + * 字典表主键 + * @return 结果 + */ + int deleteXlDictByDictId(Long dictId); + + /** + * 根据所有字典类型 + * + * @return 字典类型集合信息 + */ + List selectDictTypeAll(); + + /** + * 加载字典缓存数据 + */ + void loadingDictCache(); + + /** + * 清空字典缓存数据 + */ + void clearDictCache(); + + /** + * 重置字典缓存数据 + */ + void resetDictCache(); + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/service/ISysLoginLogService.java --- +package com.starry.admin.modules.system.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.system.module.entity.SysLoginLogEntity; +import com.starry.admin.modules.system.module.entity.SysLoginLogVo; + +/** + * 系统访问日志表Service接口 + * + * @author admin + */ +public interface ISysLoginLogService extends IService { + /** + * 查询系统访问日志表 + * + * @param loginId + * 系统访问日志表主键 + * @return 系统访问日志表 + */ + SysLoginLogEntity selectXlLoginLogByLoginId(Long loginId); + + /** + * 查询系统访问日志表列表 + * + * @param sysLoginLogEntity + * 系统访问日志表 + * @return 系统访问日志表集合 + */ + IPage selectXlLoginLogList(SysLoginLogVo sysLoginLogEntity); + + /** + * 新增系统访问日志表 + * + * @param sysLoginLogEntity + * 系统访问日志表 + * @return 结果 + */ + boolean create(SysLoginLogEntity sysLoginLogEntity); + + /** + * 修改系统访问日志表 + * + * @param sysLoginLogEntity + * 系统访问日志表 + * @return 结果 + */ + boolean update(SysLoginLogEntity sysLoginLogEntity); + + /** + * 批量删除系统访问日志表 + * + * @param loginIds + * 需要删除的系统访问日志表主键集合 + * @return 结果 + */ + int deleteXlLoginLogByLoginIds(Long[] loginIds); + + /** + * 删除系统访问日志表信息 + * + * @param loginId + * 系统访问日志表主键 + * @return 结果 + */ + int deleteXlLoginLogByLoginId(Long loginId); + + /** + * 清空系统登录日志 + */ + void cleanLoginlog(); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/service/ISysOperationLogService.java --- +package com.starry.admin.modules.system.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.system.module.entity.SysOperationLogEntity; +import com.starry.admin.modules.system.vo.SysOperationLogVo; + +/** + * 操作日志表Service接口 + * + * @author admin + */ +public interface ISysOperationLogService extends IService { + /** + * 查询操作日志表 + * + * @param operId + * 操作日志表主键 + * @return 操作日志表 + */ + SysOperationLogEntity selectXlOperLogByOperId(Long operId); + + /** + * 查询操作日志表列表 + * + * @param sysOperationLogEntity + * 操作日志表 + * @return 操作日志表集合 + */ + IPage selectXlOperLogList(SysOperationLogVo sysOperationLogEntity); + + /** + * 新增操作日志表 + * + * @param sysOperationLogEntity + * 操作日志表 + * @return 结果 + */ + boolean create(SysOperationLogEntity sysOperationLogEntity); + + /** + * 修改操作日志表 + * + * @param sysOperationLogEntity + * 操作日志表 + * @return 结果 + */ + boolean updateXlOperLog(SysOperationLogEntity sysOperationLogEntity); + + /** + * 批量删除操作日志表 + * + * @param operIds + * 需要删除的操作日志表主键集合 + * @return 结果 + */ + int deleteXlOperLogByOperIds(Long[] operIds); + + /** + * 删除操作日志表信息 + * + * @param operId + * 操作日志表主键 + * @return 结果 + */ + int deleteXlOperLogByOperId(Long operId); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/service/ISysTenantPackageService.java --- +package com.starry.admin.modules.system.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.system.module.entity.SysTenantPackageEntity; +import com.starry.admin.modules.system.vo.SimplePackage; +import com.starry.admin.modules.system.vo.SysTenantPackageVo; +import java.util.List; + +/** + * 租户套餐表Service接口 + * + * @author admin + */ +public interface ISysTenantPackageService extends IService { + /** + * 查询租户套餐表 + * + * @param packageId + * 租户套餐表主键 + * @return 租户套餐表 + */ + SysTenantPackageEntity selectSysTenantPackageByPackageId(String packageId); + + /** + * 查询租户套餐表列表 + * + * @param sysTenantPackageEntity + * 租户套餐表 + * @return 租户套餐表集合 + */ + IPage selectSysTenantPackageList(SysTenantPackageVo sysTenantPackageEntity); + + /** + * 新增租户套餐表 + * + * @param sysTenantPackageEntity + * 租户套餐表 + * @return 结果 + */ + boolean create(SysTenantPackageEntity sysTenantPackageEntity); + + /** + * 修改租户套餐表 + * + * @param sysTenantPackageEntity + * 租户套餐表 + * @return 结果 + */ + boolean update(SysTenantPackageEntity sysTenantPackageEntity); + + /** + * 批量删除租户套餐表 + * + * @param packageIds + * 需要删除的租户套餐表主键集合 + * @return 结果 + */ + int deleteSysTenantPackageByPackageIds(String[] packageIds); + + /** + * 删除租户套餐表信息 + * + * @param packageId + * 租户套餐表主键 + * @return 结果 + */ + int deleteSysTenantPackageByPackageId(Long packageId); + + /** + * 查询租户套餐 + * + * @return 租户套餐 + */ + List getSimpleList(); + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/service/ISysTenantRechargeInfoService.java --- +package com.starry.admin.modules.system.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.system.module.entity.SysTenantRechargeInfoEntity; +import com.starry.admin.modules.system.module.vo.SysTenantRechargeInfoQueryVo; +import com.starry.admin.modules.system.module.vo.SysTenantRechargeInfoReturnVo; + +/** + * 租户充值信息Service接口 + * + * @author admin + * @since 2024-09-05 + */ +public interface ISysTenantRechargeInfoService extends IService { + /** + * 查询租户充值信息 + * + * @param id + * 租户充值信息主键 + * @return 租户充值信息 + */ + SysTenantRechargeInfoEntity selectSysTenantRechargeInfoById(String id); + + /** + * 查询租户充值信息列表 + * + * @param queryVo + * 租户充值信息分页查询对象 + * @return 租户充值信息集合 + */ + IPage selectByPage(SysTenantRechargeInfoQueryVo queryVo); + + /** + * 新增租户充值信息 + * + * @param sysTenantRechargeInfo + * 租户充值信息 + * @return 结果 + */ + boolean create(SysTenantRechargeInfoEntity sysTenantRechargeInfo); + + /** + * 修改租户充值信息 + * + * @param sysTenantRechargeInfo + * 租户充值信息 + * @return 结果 + */ + boolean update(SysTenantRechargeInfoEntity sysTenantRechargeInfo); + + /** + * 批量删除租户充值信息 + * + * @param ids + * 需要删除的租户充值信息主键集合 + * @return 结果 + */ + int deleteSysTenantRechargeInfoByIds(String[] ids); + + /** + * 删除租户充值信息信息 + * + * @param id + * 租户充值信息主键 + * @return 结果 + */ + int deleteSysTenantRechargeInfoById(String id); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/service/ISysTenantService.java --- +package com.starry.admin.modules.system.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.system.module.entity.SysTenantEntity; +import com.starry.admin.modules.system.vo.SysTenantQueryVo; +import com.starry.common.result.R; +import java.util.List; + +/** + * 租户表Service接口 + * + * @author admin + */ +public interface ISysTenantService extends IService { + + /** + * 获得所有的租户信息 + * + * @return 租户表 + */ + List listAll(); + + /** + * 根据租户权限标识查询租户 + * + * @param tenantKey + * 租户权限标识 + * @return 租户表 + */ + SysTenantEntity selectByTenantKey(String tenantKey); + + /** + * 查询租户表 + * + * @param tenantId + * 租户表主键 + * @return 租户表 + */ + SysTenantEntity selectSysTenantByTenantId(String tenantId); + + /** + * 查询租户表列表 + * + * @param sysTenantEntity + * 租户表 + * @return 租户表集合 + */ + IPage selectSysTenantList(SysTenantQueryVo sysTenantEntity); + + /** + * 新增租户表 + * + * @param sysTenantEntity + * 租户表 + * @return 结果 + */ + boolean create(SysTenantEntity sysTenantEntity); + + /** + * 修改租户表 + * + * @param sysTenantEntity + * 租户表 + * @return 结果 + */ + boolean update(SysTenantEntity sysTenantEntity); + + /** + * 批量删除租户表 + * + * @param tenantIds + * 需要删除的租户表主键集合 + * @return 结果 + */ + int deleteSysTenantByTenantIds(String[] tenantIds); + + /** + * 删除租户表信息 + * + * @param tenantId + * 租户表主键 + * @return 结果 + */ + int deleteSysTenantByTenantId(Long tenantId); + + /** + * 新增租户 + * + * @param sysTenantEntity + * 租户表 + * @return 结果 + */ + R addTenant(SysTenantEntity sysTenantEntity); + + /** + * 修改租户 + * + * @param sysTenantEntity + * 租户表 + * @return 结果 + */ + R updateTenant(SysTenantEntity sysTenantEntity); + + /** + * 根据套餐ID查询租户 + * + * @param packageId + * 套餐ID + * @return + */ + List queryByPackage(String packageId); + + void initRole(SysTenantEntity sysTenantEntity); + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/service/LoginService.java --- +package com.starry.admin.modules.system.service; + +import com.starry.admin.common.domain.LoginUser; +import com.starry.admin.modules.system.module.entity.SysUserEntity; +import java.util.Set; + +/** + * @author admin + */ +public interface LoginService { + + /** + * 登录功能 + * + * @param username + * 用户名 + * @param password + * 密码 + * @return 生成的JWT的token + */ + String login(String username, String password); + + /** + * 获取菜单数据权限 + * + * @param user + * 用户信息 + * @return 菜单权限信息 + */ + Set getMenuPermission(SysUserEntity user); + + /** + * 获取角色数据权限 + * + * @param user + * 用户信息 + * @return 角色权限信息 + */ + Set getRolePermission(SysUserEntity user); + + /** + * 租户登录功能 + * + * @param tenantkey + * 租户标识 + * @param username + * 用户名 + * @param password + * 密码 + * @return 生成的JWT的token + */ + LoginUser tenantLogin(String tenantkey, String username, String password); + + /** + * 登录功能 + * + * @param username + * 用户名 + * @param password + * 密码 + * @param tenantKey + * @return 生成的JWT的token + */ + LoginUser newLogin(String username, String password, String tenantKey); + + /** + * 新登录功能,增加租户相关 + * + * @param userName + * 用户名 + * @param tenantId + * @return 获取信息 + */ + LoginUser getLoginUserInfo(String userName, String tenantId); + + LoginUser getLoginUserInfo(String userId); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/service/SysDeptService.java --- +package com.starry.admin.modules.system.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.common.domain.TreeSelect; +import com.starry.admin.modules.system.module.entity.SysDeptEntity; +import java.util.List; + +/** + *

+ * 部门表 服务类 + *

+ * + * @author admin + * @since 2022-07-12 + */ +public interface SysDeptService extends IService { + + /** + * 查询部门管理数据 + * + * @param dept + * 部门信息 + * @return 部门信息集合 + */ + List selectDeptList(SysDeptEntity dept); + + /** + * 校验部门名称是否唯一 + * + * @param dept + * 部门信息 + * @return 结果 + */ + String checkDeptNameUnique(SysDeptEntity dept); + + /** + * 添加部门 + * + * @param dept + * @return boolean + **/ + boolean create(SysDeptEntity dept); + + /** + * 修改部门 + * + * @param dept + * @return boolean + **/ + boolean update(SysDeptEntity dept); + + /** + * 批量删除部门 + * + * @param ids + * @return boolean + **/ + boolean delete(List ids); + + /** + * 是否存在部门子节点 + * + * @param deptId + * 部门ID + * @return 结果 + */ + boolean hasChildByDeptId(Long deptId); + + /** + * 构建前端所需要树结构 + * + * @param depts + * 部门列表 + * @return 树结构列表 + */ + List buildDeptTreeSelect(List depts); + + /** + * 根据角色ID查询部门树信息 + * + * @param roleId + * 角色ID + * @return 选中部门列表 + */ + List selectDeptListByRoleId(Long roleId); + + /** + * 查询部门树结构信息 + * + * @param dept + * 部门信息 + * @return 部门树信息集合 + */ + List selectDeptTreeList(SysDeptEntity dept); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/service/SysMenuService.java --- +package com.starry.admin.modules.system.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.common.domain.TreeSelect; +import com.starry.admin.modules.system.module.entity.SysMenuEntity; +import com.starry.admin.modules.system.vo.RouterVo; +import com.starry.admin.modules.system.vo.SimpleMenu; +import java.util.List; +import java.util.Set; + +/** + *

+ * 菜单表 服务类 + *

+ * + * @author admin + * @since 2022-07-03 + */ +public interface SysMenuService extends IService { + + /** + * 添加菜单 + * + * @param menu + * @return boolean + **/ + boolean create(SysMenuEntity menu); + + /** + * 根据用户查询系统菜单列表 + * + * @param menu + * 菜单 + * @param userId + * 用户ID + * @param pageSize + * 页大小 + * @param pageNum + * 页数 + * @return 分页菜单列表 + */ + Page listPage(SysMenuEntity menu, String userId, Integer pageSize, Integer pageNum); + + /** + * 根据用户查询系统菜单列表 + * + * @param menu + * 菜单 + * @param userId + * 用户ID + * @return 菜单列表 + */ + List selectMenuList(SysMenuEntity menu, String userId); + + /** + * 根据用户查询系统菜单列表 + * + * @param userId + * 用户ID + * @return 菜单列表 + */ + List selectMenuList(String userId); + + /** + * 校验菜单名称是否唯一 + * + * @param menu + * 菜单信息 + * @return 结果 + */ + String checkMenuNameUnique(SysMenuEntity menu); + + /** + * 是否存在菜单子节点 + * + * @param menuId + * 菜单ID + * @return 结果 true 存在 false 不存在 + */ + boolean hasChildByMenuId(Long menuId); + + /** + * 构建前端所需要下拉树结构 + * + * @param menus + * 菜单列表 + * @return 下拉树结构列表 + */ + List buildMenuTreeSelect(List menus); + + /** + * 根据菜单ID查询信息 + * + * @param menuId + * 菜单ID + * @return 菜单信息 + */ + SysMenuEntity selectMenuById(Long menuId); + + /** + * 根据角色ID查询菜单树信息 + * + * @param roleId + * 角色ID + * @return 选中菜单列表 + */ + List selectMenuListByRoleId(Long roleId); + + /** + * 根据用户ID查询权限 + * + * @param userId + * 用户ID + * @return 权限列表 + */ + Set selectMenuPermsByUserId(String userId); + + /** + * 根据用户ID查询菜单树信息 + * + * @param userId + * 用户ID + * @return 菜单列表 + */ + List selectMenuTreeByUserId(String userId); + + /** + * 构建前端路由所需要的菜单 + * + * @param menus + * 菜单列表 + * @return 路由列表 + */ + List buildMenus(List menus); + + /** + * 查询所有开启状态菜单精简信息 + * + * @return 菜单列表 + */ + List selectSimpleMenuList(); + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/service/SysRoleMenuService.java --- +package com.starry.admin.modules.system.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.system.module.entity.SysRoleMenuEntity; + +/** + *

+ * 角色和菜单关联表 服务类 + *

+ * + * @author admin + * @since 2022-07-06 + */ +public interface SysRoleMenuService extends IService { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/service/SysRoleService.java --- +package com.starry.admin.modules.system.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.system.module.entity.SysRoleEntity; +import com.starry.admin.modules.system.module.entity.SysUserRoleEntity; +import java.util.List; +import java.util.Set; + +/** + *

+ * 角色表 服务类 + *

+ * + * @author admin + * @since 2022-07-01 + */ +public interface SysRoleService extends IService { + + /** + * 根据roleId 查询角色 + * + * @param roleId + * 角色ID + * @return 角色 + */ + SysRoleEntity selectByRoleId(String roleId); + + /** + * 根据roleKey 查询角色 + * + * @param roleKey + * 角色标识 + * @return 角色 + */ + SysRoleEntity selectByRoleKey(String roleKey); + /** + * 校验角色名称是否唯一 + * + * @param role + * 角色信息 + * @return 结果 + */ + String checkRoleNameUnique(SysRoleEntity role); + + /** + * 校验角色权限是否唯一 + * + * @param role + * 角色信息 + * @return 结果 + */ + String checkRoleKeyUnique(SysRoleEntity role); + + /** + * 添加角色 + * + * @param role + * @return boolean + **/ + boolean create(SysRoleEntity role); + + /** + * 修改角色 + * + * @param role + * @return boolean + **/ + boolean updateRole(SysRoleEntity role); + + /** + * 通过角色ID查询角色使用数量 + * + * @param roleId + * 角色ID + * @return 结果 + */ + int countUserRoleByRoleId(Long roleId); + + /** + * 批量删除角色 + * + * @param roleIds + * @return boolean + **/ + boolean delete(Long[] roleIds); + + /** + * 分页获取角色列表 + * + * @param keyword + * @param pageSize + * @param pageNum + * @return Page + **/ + Page list(String keyword, Integer pageSize, Integer pageNum); + + /** + * 分配菜单权限信息 + * + * @param role + * 角色信息 + * @return 结果 + */ + boolean authRoleMenu(SysRoleEntity role); + + /** + * 根据用户ID查询角色权限 + * + * @param userId + * 用户ID + * @return 权限列表 + */ + Set selectRolePermissionByUserId(String userId); + + /** + * 根据条件分页查询角色数据 + * + * @param role + * 角色信息 + * @return 角色数据集合信息 + */ + List selectRoleList(SysRoleEntity role); + + /** + * 校验角色是否允许操作 + * + * @param role + * 角色信息 + */ + void checkRoleAllowed(SysRoleEntity role); + + /** + * 校验角色是否有数据权限 + * + * @param roleId + * 角色id + */ + void checkRoleDataScope(Long roleId); + + /** + * 修改数据权限信息 + * + * @param role + * 角色信息 + * @return 结果 + */ + int authDataScope(SysRoleEntity role); + + /** + * 取消授权用户角色 + * + * @param userRole + * 用户和角色关联信息 + * @return 结果 + */ + int deleteAuthUser(SysUserRoleEntity userRole); + + /** + * 批量取消授权用户角色 + * + * @param roleId + * 角色ID + * @param userIds + * 需要取消授权的用户数据ID + * @return 结果 + */ + int deleteAuthUsers(Long roleId, String[] userIds); + + /** + * 批量选择授权用户角色 + * + * @param roleId + * 角色ID + * @param userIds + * 需要删除的用户数据ID + * @return 结果 + */ + int insertAuthUsers(Long roleId, String[] userIds); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/service/SysUserRoleService.java --- +package com.starry.admin.modules.system.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.system.module.entity.SysUserRoleEntity; + +/** + *

+ * 用户角色关联表 服务类 + *

+ * + * @author admin + * @since 2022-07-08 + */ +public interface SysUserRoleService extends IService { + + /** + * 删除用户角色信息 + * + * @param userId + * 用户ID + * @param roleId + * 角色ID + */ + void delUserRole(String userId, Long roleId); + + /** + * 新增用户角色信息 + * + * @param userId + * 用户ID + * @param roleId + * 角色ID + */ + void addUserRole(String userId, Long roleId); + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/service/SysUserService.java --- +package com.starry.admin.modules.system.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.admin.modules.personnel.module.vo.PlayPersonnelUserInfoQueryVo; +import com.starry.admin.modules.personnel.module.vo.PlayPersonnelUserInfoReturnVo; +import com.starry.admin.modules.system.module.entity.SysUserEntity; +import com.starry.admin.modules.system.vo.*; +import java.util.List; + +/** + *

+ * 后台用户表 服务类 + *

+ * + * @author admin + * @since 2021-09-03 + */ +public interface SysUserService extends IService { + + /** + * 注册功能 + * + * @param user + * @return SysUserEntity + */ + SysUserEntity register(SysUserEntity user); + + /** + * 查询用户 + * + * @param userCode + * @return SysUserEntity + */ + SysUserEntity getUserByCode(String userCode); + + /** + * 通过用户名查询用户 + * + * @param userName + * 用户名 + * @return 用户对象信息 + */ + SysUserEntity selectUserByUserName(String userName); + + SysUserEntity selectUserByUserNameAndTenantId(String userName, String tenantId); + + /** + * 查询所有账户 + * + * @return 查询所有账户 + */ + List selectAll(); + + /** + * 分页查询用户 + * + * @param vo + * 查询参数 + * @return page + */ + IPage selectByPage(PlayPersonnelUserInfoQueryVo vo); + + /** + * 获取列表。分页 + * + * @param queryVo + * 查询参数 + * @return page + */ + IPage listMemberPage(UserQueryVo queryVo); + + /** + * 校验用户名称是否唯一 + * + * @param userName + * 用户名称 + * @return 结果 + */ + String checkUserNameUnique(String userName); + + /** + * 添加用户 + * + * @param user + * @return boolean + **/ + boolean create(SysUserEntity user); + + /** + * 修改用户 + * + * @param user + * @return boolean + **/ + boolean update(SysUserEntity user); + + /** + * 批量删除用户 + * + * @param ids + * @return boolean + **/ + boolean delete(List ids); + + /** + * 通过用户ID查询用户 + * + * @param userId + * 用户ID + * @return 用户对象信息 + */ + SysUserEntity selectUserById(String userId); + + /** + * 根据用户ID查询用户所属角色组 + * + * @param userId + * 用户id + * @return 结果 + */ + String selectUserRoleGroup(String userId); + + /** + * 修改用户头像 + * + * @param userId + * 用户id + * @param avatar + * 头像地址 + * @return 结果 + */ + boolean updateUserAvatar(String userId, String avatar); + + /** + * 根据条件分页查询已配用户角色列表 + * + * @param user + * 用户信息 + * @return 用户信息集合信息 + */ + IPage selectAllocatedList(SysUserQueryVo user); + + /** + * 根据条件分页查询已配用户角色列表 + * + * @param user + * 用户信息 + * @return 用户信息集合信息 + */ + IPage selectUnallocatedList(SysUserQueryVo user); + + boolean addV1(UserAddParam param); + + List generatePageData(List records); + + void updatePassword(UpdateUserPasswordParam param); + + void updateMobile(UpdateUserMobileParam param); + + void logoutUser(String uid); + + void updatePasswordV2(UpdateUserPasswordParamV2 param); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/service/UserOnlineService.java --- +package com.starry.admin.modules.system.service; + +import com.starry.admin.common.domain.LoginUser; +import com.starry.admin.modules.system.module.entity.UserOnline; + +/** + * @author admin + * @since 2022/10/18 + */ +public interface UserOnlineService { + + /** + * 通过登录地址/用户名称查询信息 + * + * @param ipaddr + * 登录地址 + * @param userName + * 用户名称 + * @param user + * 用户信息 + * @return 在线用户信息 + */ + UserOnline selectOnlineByInfo(String ipaddr, String userName, LoginUser user); + + /** + * 通过登录地址查询信息 + * + * @param ipaddr + * 登录地址 + * @param user + * 用户信息 + * @return 在线用户信息 + */ + UserOnline selectOnlineByIpaddr(String ipaddr, LoginUser user); + + /** + * 通过用户名称查询信息 + * + * @param userName + * 用户名称 + * @param user + * 用户信息 + * @return 在线用户信息 + */ + UserOnline selectOnlineByUserName(String userName, LoginUser user); + + /** + * 设置在线用户信息 + * + * @param user + * 用户信息 + * @return 在线用户 + */ + UserOnline setUserOnline(LoginUser user); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/service/impl/LoginServiceImpl.java --- +package com.starry.admin.modules.system.service.impl; + +import cn.hutool.core.convert.Convert; +import com.starry.admin.common.component.JwtToken; +import com.starry.admin.common.domain.LoginUser; +import com.starry.admin.common.exception.ServiceException; +import com.starry.admin.common.security.entity.JwtUser; +import com.starry.admin.manager.AsyncManager; +import com.starry.admin.manager.factory.AsyncFactory; +import com.starry.admin.modules.system.module.entity.SysTenantEntity; +import com.starry.admin.modules.system.module.entity.SysUserEntity; +import com.starry.admin.modules.system.service.*; +import com.starry.admin.utils.SecurityUtils; +import com.starry.common.constant.Constants; +import com.starry.common.constant.UserConstants; +import com.starry.common.utils.StringUtils; +import java.util.Date; +import java.util.HashSet; +import java.util.Set; +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; + +/** + * @author admin + */ +@Slf4j +@Service +public class LoginServiceImpl implements LoginService { + + @Resource + private PasswordEncoder passwordEncoder; + @Resource + private UserDetailsService userDetailsService; + @Resource + private JwtToken jwtTokenUtil; + @Resource + private SysMenuService menuService; + @Resource + private SysRoleService roleService; + @Resource + private SysUserService sysUserService; + @Resource + private ISysTenantService SysTenantService; + + @Override + public String login(String username, String password) { + String token = null; + try { + UserDetails userDetails = userDetailsService.loadUserByUsername(username); + if (!passwordEncoder.matches(password, userDetails.getPassword())) { + throw new BadCredentialsException("密码不正确"); + } + UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, + null, userDetails.getAuthorities()); + SecurityContextHolder.getContext().setAuthentication(authentication); + // 登录成功记录日志 + AsyncManager.me().execute(AsyncFactory.recordLoginLog(username, Constants.LOGIN_SUCCESS, "登录成功")); + JwtUser jwtUser = (JwtUser) authentication.getPrincipal(); + token = jwtTokenUtil.createToken(jwtUser); + } catch (AuthenticationException e) { + log.warn("登录异常:{}", e.getMessage()); + // 登录失败记录日志 + AsyncManager.me().execute(AsyncFactory.recordLoginLog(username, Constants.LOGIN_FAIL, e.getMessage())); + } + return token; + } + + @Override + public Set getMenuPermission(SysUserEntity user) { + Set perms = new HashSet<>(); + // 超级管理员拥有所有权限 + if (SecurityUtils.isAdmin(user)) { + perms.add("*:*:*"); + } else { + perms = menuService.selectMenuPermsByUserId(user.getUserId()); + } + return perms; + } + + @Override + public Set getRolePermission(SysUserEntity user) { + Set roles = new HashSet<>(); + // 超级管理员拥有所有权限 + if (SecurityUtils.isAdmin(user)) { + roles.add("admin"); + } else { + roles = roleService.selectRolePermissionByUserId(user.getUserId()); + } + return roles; + } + + @Override + public LoginUser tenantLogin(String tenantId, String username, String password) { + // LoginUser userInfo = this.getLoginUserInfo(username); + return null; + } + + @Override + public LoginUser newLogin(String username, String password, String tenantKey) { + // 用户名或密码为空 错误 + if (StringUtils.isAnyBlank(username, password, tenantKey)) { + // 登录记录日志 + AsyncManager.me().execute(AsyncFactory.recordLoginLog(username, Constants.LOGIN_FAIL, "用户名/密码必须填写")); + throw new ServiceException("用户/密码必须填写"); + } + // 密码如果不在指定范围内 错误 + if (password.length() < UserConstants.PASSWORD_MIN_LENGTH + || password.length() > UserConstants.PASSWORD_MAX_LENGTH) { + // 登录记录日志 + AsyncManager.me().execute(AsyncFactory.recordLoginLog(username, Constants.LOGIN_FAIL, "用户密码不在指定范围")); + throw new ServiceException("用户密码不在指定范围"); + } + // 用户名不在指定范围内 错误 + if (username.length() < UserConstants.USERNAME_MIN_LENGTH + || username.length() > UserConstants.USERNAME_MAX_LENGTH) { + // 登录记录日志 + AsyncManager.me().execute(AsyncFactory.recordLoginLog(username, Constants.LOGIN_FAIL, "用户名不在指定范围")); + throw new ServiceException("用户名不在指定范围"); + } + SysTenantEntity tenant = SysTenantService.selectByTenantKey(tenantKey); + LoginUser userInfo = this.getLoginUserInfo(username, tenant.getTenantId()); + if (userInfo == null) { + // 登录记录日志 + AsyncManager.me().execute(AsyncFactory.recordLoginLog(username, Constants.LOGIN_FAIL, "用户名不存在")); + throw new ServiceException("用户名不存在"); + } + SysUserEntity user = userInfo.getUser(); + if (!SecurityUtils.matchesPassword(password, user.getPassWord())) { + // 登录记录日志 + AsyncManager.me().execute(AsyncFactory.recordLoginLog(username, Constants.LOGIN_FAIL, "密码错误")); + throw new ServiceException("密码错误"); + } + // 线程塞入租户ID + SecurityUtils.setTenantId(Convert.toStr(user.getTenantId())); + if (user.getStatus() == 1) { + // 登录记录日志 + AsyncManager.me().execute(AsyncFactory.recordLoginLog(username, Constants.LOGIN_FAIL, "用户已停用,请联系管理员")); + throw new ServiceException("对不起,您的账号:" + username + " 已停用,请联系管理员"); + } + // 先查询是否被停用了租户 + if (userInfo.getTenantStatus() != null && userInfo.getTenantStatus() == 1) { + // 登录记录日志 + AsyncManager.me().execute(AsyncFactory.recordLoginLog(username, Constants.LOGIN_FAIL, "当前租户已经被停用,请联系管理员")); + throw new ServiceException("当前租户已经被停用,请联系管理员"); + } + if (userInfo.getTenantEndDate() != null && userInfo.getTenantEndDate().compareTo(new Date()) < 0) { + // 登录记录日志 + AsyncManager.me() + .execute(AsyncFactory.recordLoginLog(username, Constants.LOGIN_FAIL, "当前租户已超过租赁日期,请联系管理员")); + throw new ServiceException("当前租户已超过租赁日期,请联系管理员"); + } + AsyncManager.me().execute(AsyncFactory.recordLoginLog(username, Constants.LOGIN_SUCCESS, "登录成功")); + return userInfo; + } + + @Override + public LoginUser getLoginUserInfo(String userName, String tenantId) { + SysUserEntity sysUser; + if (userName.equals("sysadmin")) { + sysUser = sysUserService.selectUserByUserNameAndTenantId(userName, tenantId); + } else { + sysUser = sysUserService.selectUserByUserNameAndTenantId(userName, tenantId); + } + + if (StringUtils.isNotNull(sysUser)) { + // SecurityUtils.setTenantId(sysUser.getTenantId()); + // 角色集合 + Set roles = this.getRolePermission(sysUser); + // 权限集合 + Set permissions = this.getMenuPermission(sysUser); + // 查询租户信息 + SysTenantEntity tenant = SysTenantService.selectSysTenantByTenantId(sysUser.getTenantId()); + LoginUser sysUserVo = new LoginUser(); + sysUserVo.setUser(sysUser); + sysUserVo.setRoles(roles); + sysUserVo.setPermissions(permissions); + if (tenant != null) { + sysUserVo.setTenantEndDate(tenant.getTenantTime()); + sysUserVo.setTenantStatus(Integer.valueOf(tenant.getTenantStatus())); + } + return sysUserVo; + } + return null; + } + + @Override + public LoginUser getLoginUserInfo(String userId) { + SysUserEntity sysUser = sysUserService.selectUserById(userId); + Set roles = this.getRolePermission(sysUser); + // 权限集合 + Set permissions = this.getMenuPermission(sysUser); + // 查询租户信息 + SysTenantEntity tenant = SysTenantService.selectSysTenantByTenantId(sysUser.getTenantId()); + LoginUser sysUserVo = new LoginUser(); + sysUserVo.setUser(sysUser); + sysUserVo.setRoles(roles); + sysUserVo.setPermissions(permissions); + if (tenant != null) { + sysUserVo.setTenantEndDate(tenant.getTenantTime()); + sysUserVo.setTenantStatus(Integer.valueOf(tenant.getTenantStatus())); + } + return sysUserVo; + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/service/impl/SysAdministrativeAreaDictInfoServiceImpl.java --- +package com.starry.admin.modules.system.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.starry.admin.modules.system.mapper.SysAdministrativeAreaDictInfoMapper; +import com.starry.admin.modules.system.module.entity.SysAdministrativeAreaDictInfoEntity; +import com.starry.admin.modules.system.service.ISysAdministrativeAreaDictInfoService; +import com.starry.admin.modules.system.vo.AdministrativeAreaQueryReturnVo; +import com.starry.common.utils.ConvertUtil; +import com.starry.common.utils.IdUtils; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 行政区域字典信息Service业务层处理 + * + * @author admin + * @since 2024-04-03 + */ +@Service +public class SysAdministrativeAreaDictInfoServiceImpl + extends + ServiceImpl + implements + ISysAdministrativeAreaDictInfoService { + @Resource + private SysAdministrativeAreaDictInfoMapper sysAdministrativeAreaDictInfoMapper; + + /** + * 查询行政区域字典信息 + * + * @param id + * 行政区域字典信息主键 + * @return 行政区域字典信息 + */ + @Override + public SysAdministrativeAreaDictInfoEntity selectPlayAdministrativeAreaDictInfoById(String id) { + return this.baseMapper.selectById(id); + } + + @Override + public List selectTree(String level) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.le(SysAdministrativeAreaDictInfoEntity::getLevel, level); + List list = this.baseMapper.selectList(lambdaQueryWrapper); + Map> collect = list.stream() + .filter(a -> a != null && a.getPCode() != null) + .collect(Collectors.groupingBy(SysAdministrativeAreaDictInfoEntity::getPCode)); + return this.assembleTree(collect, collect.get("00")); + } + + /** + * 组装数据 + * + * @param data + * 数据,key=区域编码,value=区域列表 + * @param list + * 区域略表 + * @return List + * @author admin + * @since 2024/4/10 15:14 + **/ + public List assembleTree( + Map> data, + List list) { + if (list == null) { + return new ArrayList<>(); + } + List result = ConvertUtil.entityToVoList(list, + AdministrativeAreaQueryReturnVo.class); + for (AdministrativeAreaQueryReturnVo entity : result) { + entity.setChild(assembleTree(data, data.get(entity.getCode()))); + } + return result; + } + + @Override + public List selectAll() { + return this.baseMapper.selectList(new LambdaQueryWrapper<>()); + } + + /** + * 查询行政区域字典信息列表 + * + * @param playAdministrativeAreaDictInfo + * 行政区域字典信息 + * @return 行政区域字典信息 + */ + @Override + public IPage selectPlayAdministrativeAreaDictInfoByPage( + SysAdministrativeAreaDictInfoEntity playAdministrativeAreaDictInfo) { + Page page = new Page<>(1, 10); + return this.baseMapper.selectPage(page, new LambdaQueryWrapper<>()); + } + + /** + * 新增行政区域字典信息 + * + * @param playAdministrativeAreaDictInfo + * 行政区域字典信息 + * @return 结果 + */ + @Override + public boolean create(SysAdministrativeAreaDictInfoEntity playAdministrativeAreaDictInfo) { + if (StrUtil.isBlankIfStr(playAdministrativeAreaDictInfo.getId())) { + playAdministrativeAreaDictInfo.setId(IdUtils.getUuid()); + } + return save(playAdministrativeAreaDictInfo); + } + + @Override + public boolean create(List list) { + return this.saveBatch(list); + } + + /** + * 修改行政区域字典信息 + * + * @param playAdministrativeAreaDictInfo + * 行政区域字典信息 + * @return 结果 + */ + @Override + public boolean update(SysAdministrativeAreaDictInfoEntity playAdministrativeAreaDictInfo) { + return updateById(playAdministrativeAreaDictInfo); + } + + /** + * 批量删除行政区域字典信息 + * + * @param ids + * 需要删除的行政区域字典信息主键 + * @return 结果 + */ + @Override + public int deletePlayAdministrativeAreaDictInfoByIds(String[] ids) { + return sysAdministrativeAreaDictInfoMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除行政区域字典信息信息 + * + * @param id + * 行政区域字典信息主键 + * @return 结果 + */ + @Override + public int deletePlayAdministrativeAreaDictInfoById(String id) { + return sysAdministrativeAreaDictInfoMapper.deleteById(id); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/service/impl/SysDeptServiceImpl.java --- +package com.starry.admin.modules.system.service.impl; + +import cn.hutool.core.collection.CollectionUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.starry.admin.common.domain.TreeSelect; +import com.starry.admin.modules.system.mapper.SysDeptMapper; +import com.starry.admin.modules.system.mapper.SysRoleMapper; +import com.starry.admin.modules.system.module.entity.SysDeptEntity; +import com.starry.admin.modules.system.module.entity.SysRoleEntity; +import com.starry.admin.modules.system.service.SysDeptService; +import com.starry.common.annotation.DataScope; +import com.starry.common.constant.UserConstants; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + *

+ * 部门表 服务实现类 + *

+ * + * @author admin + * @since 2022-07-12 + */ +@Service +public class SysDeptServiceImpl extends ServiceImpl implements SysDeptService { + + @Resource + private SysRoleMapper roleMapper; + + @Override + @DataScope(deptAlias = "d") + public List selectDeptList(SysDeptEntity dept) { + return baseMapper.selectDeptList(dept); + } + + @Override + public String checkDeptNameUnique(SysDeptEntity dept) { + Long deptId = dept.getDeptId() == null ? -1L : dept.getDeptId(); + List infos = list(new LambdaQueryWrapper() + .eq(SysDeptEntity::getDeptName, dept.getDeptName()).eq(SysDeptEntity::getParentId, dept.getParentId())); + // 查出有数据 并且不是自己,则不唯一 + if (CollectionUtil.isNotEmpty(infos) && infos.get(0).getDeptId().longValue() != deptId.longValue()) { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + @Override + public boolean create(SysDeptEntity dept) { + SysDeptEntity info = getById(dept.getParentId()); + // 若父节点不为正常状态,则不允许新增子节点 + if (!UserConstants.DEPT_NORMAL.equals(String.valueOf(info.getStatus()))) { + throw new RuntimeException("部门停用,不允许新增"); + } + dept.setAncestors(info.getAncestors() + "," + dept.getParentId()); + dept.setDeptLevel(info.getDeptLevel() == null ? 0 : info.getDeptLevel() + 1); + return save(dept); + } + + @Override + public boolean update(SysDeptEntity dept) { + // 新的上级部门 + SysDeptEntity newParentDept = getById(dept.getParentId()); + // 当前部门 + SysDeptEntity oldDept = getById(dept.getDeptId()); + if (newParentDept != null && oldDept != null) { + String newAncestors = newParentDept.getAncestors() + "," + newParentDept.getDeptId(); + String oldAncestors = oldDept.getAncestors(); + dept.setAncestors(newAncestors); + updateDeptChildren(dept.getDeptId(), newAncestors, oldAncestors); + } + return updateById(dept); + } + + @Override + public boolean delete(List ids) { + return removeBatchByIds(ids); + } + + @Override + public boolean hasChildByDeptId(Long deptId) { + List list = baseMapper + .selectList(new LambdaQueryWrapper().eq(SysDeptEntity::getParentId, deptId)); + if (CollectionUtil.isNotEmpty(list)) { + return true; + } + return false; + } + + @Override + public List buildDeptTreeSelect(List depts) { + List deptList = buildDeptTree(depts); + // 转换成树结构的list + return deptList.stream().map(TreeSelect::new).collect(Collectors.toList()); + } + + public List buildDeptTree(List depts) { + List returnList = new ArrayList<>(); + // 所有部门id + List tempList = new ArrayList<>(); + for (SysDeptEntity dept : depts) { + tempList.add(dept.getDeptId()); + } + for (SysDeptEntity dept : depts) { + // 如若是顶级节点,遍历该父节点下的所有子节点 + if (!tempList.contains(dept.getParentId())) { + recursionFn(depts, dept); + returnList.add(dept); + } + } + if (CollectionUtil.isEmpty(returnList)) { + returnList = depts; + } + return returnList; + } + + /** + * 修改子元素关系 + * + * @param deptId + * 被修改的部门ID + * @param newAncestors + * 新的父ID集合 + * @param oldAncestors + * 旧的父ID集合 + */ + public void updateDeptChildren(Long deptId, String newAncestors, String oldAncestors) { + List childrens = baseMapper.selectChildrenDeptById(deptId); + if (CollectionUtil.isNotEmpty(childrens)) { + for (SysDeptEntity child : childrens) { + child.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors)); + updateById(child); + } + } + } + + /** + * 递归列表 + */ + private void recursionFn(List list, SysDeptEntity t) { + List childList = getChildList(list, t); + t.setChildren(childList); + for (SysDeptEntity tChild : childList) { + if (hasChild(list, tChild)) { + recursionFn(list, tChild); + } + } + } + + /** + * 得到子节点列表 + */ + private List getChildList(List list, SysDeptEntity t) { + List tList = new ArrayList<>(); + for (SysDeptEntity n : list) { + if (n.getParentId() != null && n.getParentId().longValue() == t.getDeptId().longValue()) { + tList.add(n); + } + } + return tList; + } + + /** + * 判断是否还有子节点 + */ + private boolean hasChild(List list, SysDeptEntity t) { + return !getChildList(list, t).isEmpty(); + } + + /** + * 根据角色ID查询部门树信息 + * + * @param roleId + * 角色ID + * @return 选中部门列表 + */ + @Override + public List selectDeptListByRoleId(Long roleId) { + SysRoleEntity role = roleMapper.selectRoleById(roleId); + return baseMapper.selectDeptListByRoleId(roleId, role.isDeptCheckStrictly()); + } + + /** + * 查询部门树结构信息 + * + * @param dept + * 部门信息 + * @return 部门树信息集合 + */ + @Override + public List selectDeptTreeList(SysDeptEntity dept) { + List depts = this.selectDeptList(dept); + return buildDeptTreeSelect(depts); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/service/impl/SysDictDataServiceImpl.java --- +package com.starry.admin.modules.system.service.impl; + +import cn.hutool.core.collection.CollectionUtil; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.starry.admin.modules.system.mapper.SysDictDataMapper; +import com.starry.admin.modules.system.module.entity.SysDictDataEntity; +import com.starry.admin.modules.system.service.ISysDictDataService; +import com.starry.admin.modules.system.vo.SysDictDataVo; +import com.starry.admin.utils.DictUtils; +import java.util.Arrays; +import java.util.List; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 字典数据表Service业务层处理 + * + * @author admin + */ +@Service +public class SysDictDataServiceImpl extends ServiceImpl + implements + ISysDictDataService { + @Resource + private SysDictDataMapper sysDictDataMapper; + + /** + * 查询字典数据表 + * + * @param dictDataId + * 字典数据表主键 + * @return 字典数据表 + */ + @Override + public SysDictDataEntity selectXlDictDataByDictDataId(Long dictDataId) { + return sysDictDataMapper.selectXlDictDataByDictDataId(dictDataId); + } + + /** + * 查询字典数据表列表 + * + * @param sysDictDataEntity + * 字典数据表 + * @return 字典数据表 + */ + @Override + public IPage selectXlDictDataList(SysDictDataVo sysDictDataEntity) { + return sysDictDataMapper.selectXlDictDataList( + new Page<>(sysDictDataEntity.getPageNum(), sysDictDataEntity.getPageSize()), sysDictDataEntity); + } + + /** + * 新增字典数据表 + * + * @param sysDictDataEntity + * 字典数据表 + * @return 结果 + */ + @Override + public boolean create(SysDictDataEntity sysDictDataEntity) { + return save(sysDictDataEntity); + } + + /** + * 修改字典数据表 + * + * @param sysDictDataEntity + * 字典数据表 + * @return 结果 + */ + @Override + public boolean update(SysDictDataEntity sysDictDataEntity) { + return updateById(sysDictDataEntity); + } + + /** + * 批量删除字典数据表 + * + * @param dictDataIds + * 需要删除的字典数据表主键 + * @return 结果 + */ + @Override + public int deleteXlDictDataByDictDataIds(Long[] dictDataIds) { + return sysDictDataMapper.deleteBatchIds(Arrays.asList(dictDataIds)); + } + + /** + * 删除字典数据表信息 + * + * @param dictDataId + * 字典数据表主键 + * @return 结果 + */ + @Override + public int deleteXlDictDataByDictDataId(Long dictDataId) { + return sysDictDataMapper.deleteById(dictDataId); + } + + /** + * 根据字典类型查询字典数据 + * + * @param dictType + * 字典类型 + * @return 字典数据集合信息 + */ + @Override + public List selectDictDataByType(String dictType) { + List dictDataList = DictUtils.getDictCache(dictType); + if (CollectionUtil.isNotEmpty(dictDataList)) { + return dictDataList; + } + dictDataList = sysDictDataMapper.selectDictDataByType(dictType); + if (CollectionUtil.isNotEmpty(dictDataList)) { + DictUtils.setDictCache(dictType, dictDataList); + return dictDataList; + } + return null; + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/service/impl/SysDictServiceImpl.java --- +package com.starry.admin.modules.system.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.starry.admin.modules.system.mapper.SysDictDataMapper; +import com.starry.admin.modules.system.mapper.SysDictMapper; +import com.starry.admin.modules.system.module.entity.SysDictDataEntity; +import com.starry.admin.modules.system.module.entity.SysDictEntity; +import com.starry.admin.modules.system.service.ISysDictService; +import com.starry.admin.modules.system.vo.SysDictDataVo; +import com.starry.admin.modules.system.vo.SysDictVo; +import com.starry.admin.utils.DictUtils; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 字典表Service业务层处理 + * + * @author admin + */ +@Service +public class SysDictServiceImpl extends ServiceImpl implements ISysDictService { + @Resource + private SysDictMapper sysDictMapper; + @Resource + private SysDictDataMapper sysDictDataMapper; + + /** + * 查询字典表 + * + * @param dictId + * 字典表主键 + * @return 字典表 + */ + @Override + public SysDictEntity selectXlDictByDictId(Long dictId) { + return sysDictMapper.selectXlDictByDictId(dictId); + } + + /** + * 查询字典表列表 + * + * @param sysDictVo + * 字典表 + * @return 字典表 + */ + @Override + public Page selectXlDictList(SysDictVo sysDictVo) { + return sysDictMapper.selectXlDictList(new Page<>(sysDictVo.getPageNum(), sysDictVo.getPageSize()), sysDictVo); + } + + /** + * 新增字典表 + * + * @param sysDictEntity + * 字典表 + * @return 结果 + */ + @Override + public boolean create(SysDictEntity sysDictEntity) { + return save(sysDictEntity); + } + + /** + * 修改字典表 + * + * @param sysDictEntity + * 字典表 + * @return 结果 + */ + @Override + public boolean update(SysDictEntity sysDictEntity) { + return updateById(sysDictEntity); + } + + /** + * 批量删除字典表 + * + * @param dictIds + * 需要删除的字典表主键 + * @return 结果 + */ + @Override + public int deleteXlDictByDictIds(Long[] dictIds) { + return sysDictMapper.deleteBatchIds(Arrays.asList(dictIds)); + } + + /** + * 删除字典表信息 + * + * @param dictId + * 字典表主键 + * @return 结果 + */ + @Override + public int deleteXlDictByDictId(Long dictId) { + return sysDictMapper.deleteById(dictId); + } + + @Override + public List selectDictTypeAll() { + return sysDictMapper.selectList(new LambdaQueryWrapper<>()); + } + + /** + * 加载字典缓存数据 + */ + @Override + public void loadingDictCache() { + SysDictDataVo dictData = new SysDictDataVo(); + dictData.setStatus(0); + // 按字典编码分组,不分页,size < 0 + IPage iPage = sysDictDataMapper.selectXlDictDataList(new Page<>(1, -1), dictData); + Map> dictDataMap = iPage.getRecords().stream() + .collect(Collectors.groupingBy(SysDictDataEntity::getDictType)); + for (Map.Entry> entry : dictDataMap.entrySet()) { + DictUtils.setDictCache(entry.getKey(), entry.getValue().stream() + .sorted(Comparator.comparing(SysDictDataEntity::getSort)).collect(Collectors.toList())); + } + } + + /** + * 清空字典缓存数据 + */ + @Override + public void clearDictCache() { + DictUtils.clearDictCache(); + } + + /** + * 重置字典缓存数据 + */ + @Override + public void resetDictCache() { + clearDictCache(); + loadingDictCache(); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/service/impl/SysLoginLogServiceImpl.java --- +package com.starry.admin.modules.system.service.impl; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.starry.admin.modules.system.mapper.SysLoginLogMapper; +import com.starry.admin.modules.system.module.entity.SysLoginLogEntity; +import com.starry.admin.modules.system.module.entity.SysLoginLogVo; +import com.starry.admin.modules.system.service.ISysLoginLogService; +import java.util.Arrays; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 系统访问日志表Service业务层处理 + * + * @author admin + */ +@Service +public class SysLoginLogServiceImpl extends ServiceImpl + implements + ISysLoginLogService { + @Resource + private SysLoginLogMapper xlLoginLogMapper; + + /** + * 查询系统访问日志表 + * + * @param loginId + * 系统访问日志表主键 + * @return 系统访问日志表 + */ + @Override + public SysLoginLogEntity selectXlLoginLogByLoginId(Long loginId) { + return xlLoginLogMapper.selectXlLoginLogByLoginId(loginId); + } + + /** + * 查询系统访问日志表列表 + * + * @param vo + * 系统访问日志表 + * @return 系统访问日志表 + */ + @Override + public IPage selectXlLoginLogList(SysLoginLogVo vo) { + return xlLoginLogMapper.selectXlLoginLogList(new Page<>(vo.getPageNum(), vo.getPageSize()), vo); + } + + /** + * 新增系统访问日志表 + * + * @param sysLoginLogEntity + * 系统访问日志表 + * @return 结果 + */ + @Override + public boolean create(SysLoginLogEntity sysLoginLogEntity) { + return save(sysLoginLogEntity); + } + + /** + * 修改系统访问日志表 + * + * @param sysLoginLogEntity + * 系统访问日志表 + * @return 结果 + */ + @Override + public boolean update(SysLoginLogEntity sysLoginLogEntity) { + return updateById(sysLoginLogEntity); + } + + /** + * 批量删除系统访问日志表 + * + * @param loginIds + * 需要删除的系统访问日志表主键 + * @return 结果 + */ + @Override + public int deleteXlLoginLogByLoginIds(Long[] loginIds) { + return xlLoginLogMapper.deleteBatchIds(Arrays.asList(loginIds)); + } + + /** + * 删除系统访问日志表信息 + * + * @param loginId + * 系统访问日志表主键 + * @return 结果 + */ + @Override + public int deleteXlLoginLogByLoginId(Long loginId) { + return xlLoginLogMapper.deleteById(loginId); + } + + @Override + public void cleanLoginlog() { + xlLoginLogMapper.cleanLoginlog(); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/service/impl/SysMenuServiceImpl.java --- +package com.starry.admin.modules.system.service.impl; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.starry.admin.common.domain.TreeSelect; +import com.starry.admin.modules.system.mapper.SysMenuMapper; +import com.starry.admin.modules.system.mapper.SysRoleMapper; +import com.starry.admin.modules.system.module.entity.SysMenuEntity; +import com.starry.admin.modules.system.module.entity.SysRoleEntity; +import com.starry.admin.modules.system.module.entity.SysUserEntity; +import com.starry.admin.modules.system.service.SysMenuService; +import com.starry.admin.modules.system.service.SysUserService; +import com.starry.admin.modules.system.vo.MetaVo; +import com.starry.admin.modules.system.vo.RouterVo; +import com.starry.admin.modules.system.vo.SimpleMenu; +import com.starry.admin.utils.SecurityUtils; +import com.starry.common.constant.Constants; +import com.starry.common.constant.UserConstants; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.LongStream; +import javax.annotation.Resource; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +/** + *

+ * 菜单表 服务实现类 + *

+ * + * @author admin + * @since 2022-07-03 + */ +@Service +public class SysMenuServiceImpl extends ServiceImpl implements SysMenuService { + + @Resource + private SysRoleMapper roleMapper; + @Resource + private SysUserService userService; + + @Override + public boolean create(SysMenuEntity menu) { + return save(menu); + } + + @Override + public Page listPage(SysMenuEntity menu, String userId, Integer pageSize, Integer pageNum) { + Page page = new Page<>(pageNum, pageSize); + // 超级管理员显示所有菜单信息 + if (SecurityUtils.isAdmin(userService.selectUserById(userId))) { + return baseMapper.selectPage(page, new LambdaQueryWrapper().eq(SysMenuEntity::getStatus, 1)); + } else { + List menuList = baseMapper.selectMenuListByUserId(menu, userId, page); + return page.setRecords(menuList); + } + } + + @Override + public List selectMenuList(SysMenuEntity menu, String userId) { + List menuList; + // 超级管理员显示所有菜单信息 + if (SecurityUtils.isAdmin(userService.selectUserById(userId))) { + menuList = baseMapper.selectMenuList(menu); + List menuIds = LongStream.rangeClosed(1, 56).boxed().collect(Collectors.toList()); + menuIds.remove(1L); + menuIds.remove(6L); + menuIds.remove(17L); + menuIds.remove(42L); + menuIds.remove(43L); + menuIds.remove(44L); + menuIds.remove(45L); + menuIds.remove(46L); + menuList = menuList.stream().filter(ca -> !menuIds.contains(ca.getMenuId())).collect(Collectors.toList()); + + } else { + menuList = baseMapper.selectMenuListByUserId(menu, userId); + } + return menuList; + } + + @Override + public List selectMenuList(String userId) { + return selectMenuList(new SysMenuEntity(), userId); + } + + @Override + public String checkMenuNameUnique(SysMenuEntity menu) { + long menuId = menu.getMenuId() == null ? -1L : menu.getMenuId(); + List menus = baseMapper.selectList(new LambdaQueryWrapper() + .eq(SysMenuEntity::getMenuName, menu.getMenuName()).eq(SysMenuEntity::getParentId, menu.getParentId())); + if (CollectionUtil.isNotEmpty(menus) && menus.get(0).getMenuId() != menuId) { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + @Override + public boolean hasChildByMenuId(Long menuId) { + Long result = baseMapper + .selectCount(new LambdaQueryWrapper().eq(SysMenuEntity::getParentId, menuId)); + return result > 0; + } + + @Override + public List buildMenuTreeSelect(List menus) { + List returnList = new ArrayList<>(); + List tempList = new ArrayList<>(); + for (SysMenuEntity menu : menus) { + tempList.add(menu.getMenuId()); + } + for (SysMenuEntity menu : menus) { + // 如果是顶级节点,遍历该父节点所有的子节点 + if (!tempList.contains(menu.getParentId())) { + recursionList(menus, menu); + returnList.add(menu); + } + } + if (CollectionUtil.isEmpty(returnList)) { + returnList = menus; + } + return returnList.stream().map(TreeSelect::new).collect(Collectors.toList()); + } + + @Override + public SysMenuEntity selectMenuById(Long menuId) { + return baseMapper.selectById(menuId); + } + + @Override + public List selectMenuListByRoleId(Long roleId) { + SysRoleEntity role = roleMapper.selectRoleById(roleId); + return baseMapper.selectMenuListByRoleId(roleId, role.isMenuCheckStrictly()); + } + + @Override + public Set selectMenuPermsByUserId(String userId) { + // 获取菜单权限集合 + List perms = baseMapper.selectMenuPermsByUserId(userId); + Set permsSet = new HashSet<>(); + for (String perm : perms) { + if (StrUtil.isNotBlank(perm)) { + permsSet.addAll(Arrays.asList(perm.trim().split(","))); + } + } + return permsSet; + } + + @Override + public List selectMenuTreeByUserId(String userId) { + List menus; + SysUserEntity user = userService.selectUserById(userId); + if (SecurityUtils.isAdmin(user)) { + menus = baseMapper.selectMenuTreeAll(); + if (!user.getUserId().equals("6dcb2da45fef4768a6511f9c14e18072")) { + if (CollectionUtil.isNotEmpty(menus)) { + List menuIds = Arrays.asList(2L, 3L, 5L, 26L, 47L, 48L); + menus = menus.stream().filter(ca -> !menuIds.contains(ca.getMenuId())).collect(Collectors.toList()); + } + } + } else { + menus = baseMapper.selectMenuTreeByUserId(userId); + } + + return getChildPerms(menus, 0); + } + + @Override + public List buildMenus(List menus) { + List routers = new LinkedList<>(); + for (SysMenuEntity menu : menus) { + RouterVo router = new RouterVo(); + // 0:隐藏 + router.setHidden("0".equals(menu.getVisible().toString())); + router.setName(getRouteName(menu)); + router.setPath(getRouterPath(menu)); + router.setComponent(getComponent(menu)); + router.setRouterQuery(menu.getRouterQuery()); + router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), false, menu.getPath())); + List cMenus = menu.getChildren(); + // 有子路由 + if (CollectionUtil.isNotEmpty(cMenus) + && UserConstants.TYPE_DIR.equals(String.valueOf(menu.getMenuType()))) { + router.setAlwaysShow(true); + router.setRedirect("noRedirect"); + router.setChildren(buildMenus(cMenus)); + } else if (isMenuFrame(menu)) { + // 菜单内部跳转 + router.setMeta(null); + List childrenList = new ArrayList<>(); + RouterVo children = new RouterVo(); + children.setPath(menu.getPath()); + children.setComponent(menu.getComponent()); + children.setName(StringUtils.capitalize(menu.getPath())); + children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), false, menu.getPath())); + children.setRouterQuery(menu.getRouterQuery()); + childrenList.add(children); + router.setChildren(childrenList); + } else if (menu.getParentId().intValue() == 0 && isInnerLink(menu)) { + router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon())); + router.setPath("/"); + List childrenList = new ArrayList<>(); + RouterVo children = new RouterVo(); + String routerPath = innerLinkReplaceEach(menu.getPath()); + children.setPath(routerPath); + children.setComponent(UserConstants.INNER_LINK); + children.setName(StringUtils.capitalize(routerPath)); + children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), menu.getPath())); + childrenList.add(children); + router.setChildren(childrenList); + } + routers.add(router); + } + return routers; + } + + @Override + public List selectSimpleMenuList() { + return baseMapper.selectSimpleMenuList(); + } + + /** + * 递归列表 + * + * @param menus + * @param t + */ + private void recursionList(List menus, SysMenuEntity t) { + // 得到子节点 + List childList = getChildList(menus, t); + t.setChildren(childList); + for (SysMenuEntity tChild : childList) { + if (hasChild(menus, tChild)) { + recursionList(menus, tChild); + } + } + } + + /** + * 得到子节点列表 + */ + private List getChildList(List list, SysMenuEntity t) { + List tList = new ArrayList<>(); + for (SysMenuEntity n : list) { + if (n.getParentId().longValue() == t.getMenuId().longValue()) { + tList.add(n); + } + } + return tList; + } + + /** + * 判断是否有子节点 + */ + private boolean hasChild(List list, SysMenuEntity t) { + return !getChildList(list, t).isEmpty(); + } + + /** + * 获取路由名称 + */ + private String getRouteName(SysMenuEntity menu) { + // 首字母大写 + String routerName = StringUtils.capitalize(menu.getPath()); + // 非外链并且是一级目录(类型为菜单) + if (isMenuFrame(menu)) { + routerName = StringUtils.EMPTY; + } + return routerName; + } + + /** + * 获取路由地址 + */ + private String getRouterPath(SysMenuEntity menu) { + String routerPath = menu.getPath(); + // 内链打开外网方式 + if (menu.getParentId().intValue() != 0 && isInnerLink(menu)) { + // 内链域名特殊字符替换 + routerPath = innerLinkReplaceEach(routerPath); + } + // 非外链并且是一级目录(类型为目录) + if (menu.getParentId().intValue() == 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType()) + && UserConstants.NO_FRAME.equals(menu.getIsFrame())) { + routerPath = "/" + menu.getPath(); + } else if (isMenuFrame(menu)) { + routerPath = "/"; + } + return routerPath; + } + + /** + * 是否为菜单内部跳转 + */ + private boolean isMenuFrame(SysMenuEntity menu) { + return menu.getParentId().intValue() == 0 && UserConstants.TYPE_MENU.equals(menu.getMenuType()) + && menu.getIsFrame().equals(UserConstants.NO_FRAME); + } + + /** + * 是否为内链组件 + */ + private boolean isInnerLink(SysMenuEntity menu) { + // 判断是否为http(s)://开头 + return menu.getIsFrame().equals(UserConstants.NO_FRAME) + && StringUtils.startsWithAny(menu.getPath(), Constants.HTTP, Constants.HTTPS); + } + + /** + * 是否为parent_view组件 (有多级的菜单) + */ + private boolean isParentView(SysMenuEntity menu) { + return menu.getParentId().intValue() != 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType()); + } + + /** + * 内链域名特殊字符替换 + */ + private String innerLinkReplaceEach(String path) { + return StringUtils.replaceEach(path, new String[]{Constants.HTTP, Constants.HTTPS}, new String[]{"", ""}); + } + + private List getChildPerms(List list, int parentId) { + List returnList = new ArrayList<>(); + for (SysMenuEntity menu : list) { + if (menu.getParentId() == parentId) { + recursionList(list, menu); + returnList.add(menu); + } + } + return returnList; + } + + /** + * 获取组件信息 + * + * @param menu + * 菜单信息 + * @return 组件信息 + */ + public String getComponent(SysMenuEntity menu) { + String component = UserConstants.LAYOUT; + if (StrUtil.isNotBlank(menu.getComponent()) && !isMenuFrame(menu)) { + component = menu.getComponent(); + } else if (StringUtils.isEmpty(menu.getComponent()) && menu.getParentId().intValue() != 0 + && isInnerLink(menu)) { + component = UserConstants.INNER_LINK; + } else if (StringUtils.isEmpty(menu.getComponent()) && isParentView(menu)) { + component = UserConstants.PARENT_VIEW; + } + return component; + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/service/impl/SysOperationLogServiceImpl.java --- +package com.starry.admin.modules.system.service.impl; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.starry.admin.modules.system.mapper.SysOperationLogMapper; +import com.starry.admin.modules.system.module.entity.SysOperationLogEntity; +import com.starry.admin.modules.system.service.ISysOperationLogService; +import com.starry.admin.modules.system.vo.SysOperationLogVo; +import java.util.Arrays; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 操作日志表Service业务层处理 + * + * @author admin + */ +@Service +public class SysOperationLogServiceImpl extends ServiceImpl + implements + ISysOperationLogService { + + @Resource + private SysOperationLogMapper sysOperationLogMapper; + + /** + * 查询操作日志表 + * + * @param operId + * 操作日志表主键 + * @return 操作日志表 + */ + @Override + public SysOperationLogEntity selectXlOperLogByOperId(Long operId) { + return sysOperationLogMapper.selectXlOperLogByOperId(operId); + } + + /** + * 查询操作日志表列表 + * + * @param sysOperationLogEntity + * 操作日志表 + * @return 操作日志表 + */ + @Override + public IPage selectXlOperLogList(SysOperationLogVo sysOperationLogEntity) { + return sysOperationLogMapper.selectXlOperLogList( + new Page<>(sysOperationLogEntity.getPageNum(), sysOperationLogEntity.getPageSize()), + sysOperationLogEntity); + } + + /** + * 新增操作日志表 + * + * @param sysOperationLogEntity + * 操作日志表 + * @return 结果 + */ + @Override + public boolean create(SysOperationLogEntity sysOperationLogEntity) { + return save(sysOperationLogEntity); + } + + /** + * 修改操作日志表 + * + * @param sysOperationLogEntity + * 操作日志表 + * @return 结果 + */ + @Override + public boolean updateXlOperLog(SysOperationLogEntity sysOperationLogEntity) { + return updateById(sysOperationLogEntity); + } + + /** + * 批量删除操作日志表 + * + * @param operIds + * 需要删除的操作日志表主键 + * @return 结果 + */ + @Override + public int deleteXlOperLogByOperIds(Long[] operIds) { + return sysOperationLogMapper.deleteBatchIds(Arrays.asList(operIds)); + } + + /** + * 删除操作日志表信息 + * + * @param operId + * 操作日志表主键 + * @return 结果 + */ + @Override + public int deleteXlOperLogByOperId(Long operId) { + return sysOperationLogMapper.deleteById(operId); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/service/impl/SysRoleMenuServiceImpl.java --- +package com.starry.admin.modules.system.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.starry.admin.modules.system.mapper.SysRoleMenuMapper; +import com.starry.admin.modules.system.module.entity.SysRoleMenuEntity; +import com.starry.admin.modules.system.service.SysRoleMenuService; +import org.springframework.stereotype.Service; + +/** + *

+ * 角色和菜单关联表 服务实现类 + *

+ * + * @author admin + * @since 2022-07-06 + */ +@Service +public class SysRoleMenuServiceImpl extends ServiceImpl + implements + SysRoleMenuService { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/service/impl/SysRoleServiceImpl.java --- +package com.starry.admin.modules.system.service.impl; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.starry.admin.common.exception.ServiceException; +import com.starry.admin.modules.system.mapper.SysRoleDeptMapper; +import com.starry.admin.modules.system.mapper.SysRoleMapper; +import com.starry.admin.modules.system.mapper.SysRoleMenuMapper; +import com.starry.admin.modules.system.mapper.SysUserRoleMapper; +import com.starry.admin.modules.system.module.entity.*; +import com.starry.admin.modules.system.service.SysRoleMenuService; +import com.starry.admin.modules.system.service.SysRoleService; +import com.starry.admin.modules.system.service.SysUserRoleService; +import com.starry.admin.modules.system.service.SysUserService; +import com.starry.admin.utils.SecurityUtils; +import com.starry.common.constant.UserConstants; +import com.starry.common.utils.StringUtils; +import java.util.*; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + *

+ * 角色表 服务实现类 + *

+ * + * @author admin + * @since 2022-07-01 + */ +@Service +public class SysRoleServiceImpl extends ServiceImpl implements SysRoleService { + + @Resource + private SysRoleMenuService roleMenuService; + @Resource + private SysRoleDeptMapper roleDeptMapper; + @Resource + private SysRoleMenuMapper roleMenuMapper; + @Resource + private SysUserRoleService userRoleService; + @Resource + private SysUserRoleMapper userRoleMapper; + @Resource + private SysUserService userService; + + @Override + public SysRoleEntity selectByRoleId(String roleId) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(SysRoleEntity::getRoleId, roleId); + return this.baseMapper.selectOne(lambdaQueryWrapper); + } + + @Override + public SysRoleEntity selectByRoleKey(String roleKey) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(SysRoleEntity::getRoleKey, roleKey); + return this.baseMapper.selectOne(lambdaQueryWrapper); + } + + /** + * 校验角色名称是否唯一 + * + * @param role + * 角色信息 + * @return 结果 + */ + @Override + public String checkRoleNameUnique(SysRoleEntity role) { + Long roleId = StringUtils.isNull(role.getRoleId()) ? -1L : role.getRoleId(); + SysRoleEntity info = baseMapper.checkRoleNameUnique(role.getRoleName()); + if (StringUtils.isNotNull(info) && info.getRoleId().longValue() != roleId.longValue()) { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 校验角色权限是否唯一 + * + * @param role + * 角色信息 + * @return 结果 + */ + @Override + public String checkRoleKeyUnique(SysRoleEntity role) { + Long roleId = StringUtils.isNull(role.getRoleId()) ? -1L : role.getRoleId(); + SysRoleEntity info = baseMapper.checkRoleKeyUnique(role.getRoleKey()); + if (StringUtils.isNotNull(info) && info.getRoleId().longValue() != roleId.longValue()) { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean create(SysRoleEntity role) { + // 先新增角色 + save(role); + return insertRoleMenu(role); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean updateRole(SysRoleEntity role) { + // 先修改角色 + updateById(role); + // 再删除角色菜单信息 + roleMenuService + .remove(new LambdaQueryWrapper().eq(SysRoleMenuEntity::getRoleId, role.getRoleId())); + // 再新增 + return insertRoleMenu(role); + } + + @Override + public int countUserRoleByRoleId(Long roleId) { + return baseMapper.countUserRoleByRoleId(roleId); + } + + @Override + public boolean delete(Long[] roleIds) { + for (Long roleId : roleIds) { + checkRoleAllowed(new SysRoleEntity(roleId)); + checkRoleDataScope(roleId); + SysRoleEntity role = getById(roleId); + if (countUserRoleByRoleId(roleId) > 0) { + throw new ServiceException(String.format("%1$s已分配,不能删除", role.getRoleName())); + } + } + // 删除角色与菜单关联 + roleMenuMapper.deleteRoleMenu(roleIds); + // 删除角色与部门关联 + roleDeptMapper.deleteRoleDept(roleIds); + return removeByIds(Arrays.asList(roleIds)); + } + + @Override + public Page list(String keyword, Integer pageSize, Integer pageNum) { + Page page = new Page<>(pageNum, pageSize); + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + if (StrUtil.isNotBlank(keyword)) { + wrapper.like(SysRoleEntity::getRoleName, keyword); + } + return page(page, wrapper); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public boolean authRoleMenu(SysRoleEntity role) { + // 先删除 + roleMenuService + .remove(new LambdaQueryWrapper().eq(SysRoleMenuEntity::getRoleId, role.getRoleId())); + // 在新增 + return insertRoleMenu(role); + } + + @Override + public Set selectRolePermissionByUserId(String userId) { + List list = baseMapper.selectRolePermissionByUserId(userId); + Set permsSet = new HashSet<>(); + if (CollectionUtil.isNotEmpty(list)) { + for (SysRoleEntity role : list) { + permsSet.addAll(Arrays.asList(role.getRoleKey().trim().split(","))); + } + } + return permsSet; + } + + @Override + public List selectRoleList(SysRoleEntity role) { + return baseMapper.selectRoleList(role); + } + + /** + * 新增角色菜单信息 + * + * @param role + * 角色对象 + */ + public boolean insertRoleMenu(SysRoleEntity role) { + // 新增角色与菜单管理 + List list = new ArrayList<>(); + for (Long menuId : role.getMenuIds()) { + SysRoleMenuEntity rm = new SysRoleMenuEntity(); + rm.setRoleId(role.getRoleId()); + rm.setMenuId(menuId); + list.add(rm); + } + if (!list.isEmpty()) { + return roleMenuService.saveBatch(list); + } + return true; + } + + /** + * 校验角色是否允许操作 + * + * @param role + * 角色信息 + */ + @Override + public void checkRoleAllowed(SysRoleEntity role) { + if (StringUtils.isNotNull(role.getRoleId()) && role.isAdmin()) { + throw new ServiceException("不允许操作超级管理员角色"); + } + } + + /** + * 校验角色是否有数据权限 + * + * @param roleId + * 角色id + */ + @Override + public void checkRoleDataScope(Long roleId) { + if (!SysUserEntity.isAdmin(userService.selectUserById(SecurityUtils.getUserId()))) { + SysRoleEntity role = new SysRoleEntity(); + role.setRoleId(roleId); + List roles = this.selectRoleList(role); + if (CollectionUtil.isEmpty(roles)) { + throw new ServiceException("没有权限访问角色数据!"); + } + } + } + + /** + * 修改数据权限信息 + * + * @param role + * 角色信息 + * @return 结果 + */ + @Transactional(rollbackFor = Exception.class) + @Override + public int authDataScope(SysRoleEntity role) { + // 修改角色信息 + this.updateById(role); + // 删除角色与部门关联 + roleDeptMapper.deleteRoleDeptByRoleId(role.getRoleId()); + // 新增角色和部门信息(数据权限) + return insertRoleDept(role); + } + + /** + * 新增角色部门信息(数据权限) + * + * @param role + * 角色对象 + */ + public int insertRoleDept(SysRoleEntity role) { + int rows = 1; + // 新增角色与部门(数据权限)管理 + List list = new ArrayList<>(); + for (Long deptId : role.getDeptIds()) { + SysRoleDeptEntity rd = new SysRoleDeptEntity(); + rd.setRoleId(role.getRoleId()); + rd.setDeptId(deptId); + list.add(rd); + } + if (!list.isEmpty()) { + rows = roleDeptMapper.batchRoleDept(list); + } + return rows; + } + + /** + * 取消授权用户角色 + * + * @param userRole + * 用户和角色关联信息 + * @return 结果 + */ + @Override + public int deleteAuthUser(SysUserRoleEntity userRole) { + return userRoleMapper.deleteUserRoleInfo(userRole); + } + + /** + * 批量取消授权用户角色 + * + * @param roleId + * 角色ID + * @param userIds + * 需要取消授权的用户数据ID + * @return 结果 + */ + @Override + public int deleteAuthUsers(Long roleId, String[] userIds) { + return userRoleMapper.deleteUserRoleInfos(roleId, userIds); + } + + /** + * 批量选择授权用户角色 + * + * @param roleId + * 角色ID + * @param userIds + * 需要授权的用户数据ID + * @return 结果 + */ + @Override + public int insertAuthUsers(Long roleId, String[] userIds) { + // 新增用户与角色管理 + List list = new ArrayList<>(); + for (String userId : userIds) { + SysUserRoleEntity ur = new SysUserRoleEntity(); + ur.setUserId(userId); + ur.setRoleId(roleId); + list.add(ur); + } + return userRoleService.saveBatch(list) ? 1 : 0; + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/service/impl/SysTenantPackageServiceImpl.java --- +package com.starry.admin.modules.system.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.system.mapper.SysTenantPackageMapper; +import com.starry.admin.modules.system.module.entity.SysTenantPackageEntity; +import com.starry.admin.modules.system.service.ISysTenantPackageService; +import com.starry.admin.modules.system.service.ISysTenantService; +import com.starry.admin.modules.system.vo.SimplePackage; +import com.starry.admin.modules.system.vo.SysTenantPackageVo; +import com.starry.common.utils.IdUtils; +import java.util.Arrays; +import java.util.List; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 租户套餐表Service业务层处理 + * + * @author admin + */ +@Service +public class SysTenantPackageServiceImpl extends ServiceImpl + implements + ISysTenantPackageService { + @Resource + private SysTenantPackageMapper sysTenantPackageMapper; + + @Resource + private ISysTenantService tenantService; + + /** + * 查询租户套餐表 + * + * @param packageId + * 租户套餐表主键 + * @return 租户套餐表 + */ + @Override + public SysTenantPackageEntity selectSysTenantPackageByPackageId(String packageId) { + return this.baseMapper.selectById(packageId); + } + + /** + * 查询租户套餐表列表 + * + * @param sysTenantPackageEntity + * 租户套餐表 + * @return 租户套餐表 + */ + @Override + public IPage selectSysTenantPackageList(SysTenantPackageVo sysTenantPackageEntity) { + return sysTenantPackageMapper.selectSysTenantPackageList( + new Page<>(sysTenantPackageEntity.getPageNum(), sysTenantPackageEntity.getPageSize()), + sysTenantPackageEntity); + } + + /** + * 新增租户套餐表 + * + * @param entity + * 租户套餐表 + * @return 结果 + */ + @Override + public boolean create(SysTenantPackageEntity entity) { + if (StrUtil.isBlankIfStr(entity.getPackageId())) { + entity.setPackageId(IdUtils.getUuid()); + } + return save(entity); + } + + /** + * 修改租户套餐表 + * + * @param sysTenantPackageEntity + * 租户套餐表 + * @return 结果 + */ + @Override + public boolean update(SysTenantPackageEntity sysTenantPackageEntity) { + return updateById(sysTenantPackageEntity); + } + + /** + * 批量删除租户套餐表 + * + * @param packageIds + * 需要删除的租户套餐表主键 + * @return 结果 + */ + @Override + public int deleteSysTenantPackageByPackageIds(String[] packageIds) { + // 删除前,看套餐是否被租户引用 + for (String packageId : packageIds) { + if (!tenantService.queryByPackage(packageId).isEmpty()) { + throw new CustomException("套餐背应用,无法删除"); + } + } + return sysTenantPackageMapper.deleteBatchIds(Arrays.asList(packageIds)); + } + + /** + * 删除租户套餐表信息 + * + * @param packageId + * 租户套餐表主键 + * @return 结果 + */ + @Override + public int deleteSysTenantPackageByPackageId(Long packageId) { + return sysTenantPackageMapper.deleteById(packageId); + } + + @Override + public List getSimpleList() { + return sysTenantPackageMapper.getSimpleList(); + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/service/impl/SysTenantRechargeInfoServiceImpl.java --- +package com.starry.admin.modules.system.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.github.yulichang.wrapper.MPJLambdaWrapper; +import com.starry.admin.modules.system.mapper.SysTenantRechargeInfoMapper; +import com.starry.admin.modules.system.module.entity.SysTenantEntity; +import com.starry.admin.modules.system.module.entity.SysTenantRechargeInfoEntity; +import com.starry.admin.modules.system.module.vo.SysTenantRechargeInfoQueryVo; +import com.starry.admin.modules.system.module.vo.SysTenantRechargeInfoReturnVo; +import com.starry.admin.modules.system.service.ISysTenantRechargeInfoService; +import com.starry.common.utils.IdUtils; +import java.util.Arrays; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 租户充值信息Service业务层处理 + * + * @author admin + * @since 2024-09-05 + */ +@Service +public class SysTenantRechargeInfoServiceImpl + extends + ServiceImpl + implements + ISysTenantRechargeInfoService { + @Resource + private SysTenantRechargeInfoMapper sysTenantRechargeInfoMapper; + + /** + * 查询租户充值信息 + * + * @param id + * 租户充值信息主键 + * @return 租户充值信息 + */ + @Override + public SysTenantRechargeInfoEntity selectSysTenantRechargeInfoById(String id) { + return this.baseMapper.selectById(id); + } + + /** + * 查询租户充值信息列表 + * + * @param queryVo + * 租户充值信息 + * @return 租户充值信息 + */ + @Override + public IPage selectByPage(SysTenantRechargeInfoQueryVo queryVo) { + MPJLambdaWrapper lambdaQueryWrapper = new MPJLambdaWrapper<>(); + lambdaQueryWrapper.selectAll(SysTenantRechargeInfoEntity.class); + lambdaQueryWrapper.selectAs(SysTenantEntity::getTenantName, "rechargeName"); + lambdaQueryWrapper.leftJoin(SysTenantEntity.class, SysTenantEntity::getTenantId, + SysTenantRechargeInfoEntity::getRechargeUser); + return this.baseMapper.selectJoinPage(new Page<>(queryVo.getPageNum(), queryVo.getPageSize()), + SysTenantRechargeInfoReturnVo.class, lambdaQueryWrapper); + } + + /** + * 新增租户充值信息 + * + * @param sysTenantRechargeInfo + * 租户充值信息 + * @return 结果 + */ + @Override + public boolean create(SysTenantRechargeInfoEntity sysTenantRechargeInfo) { + if (StrUtil.isBlankIfStr(sysTenantRechargeInfo.getId())) { + sysTenantRechargeInfo.setId(IdUtils.getUuid()); + } + return save(sysTenantRechargeInfo); + } + + /** + * 修改租户充值信息 + * + * @param sysTenantRechargeInfo + * 租户充值信息 + * @return 结果 + */ + @Override + public boolean update(SysTenantRechargeInfoEntity sysTenantRechargeInfo) { + return updateById(sysTenantRechargeInfo); + } + + /** + * 批量删除租户充值信息 + * + * @param ids + * 需要删除的租户充值信息主键 + * @return 结果 + */ + @Override + public int deleteSysTenantRechargeInfoByIds(String[] ids) { + return sysTenantRechargeInfoMapper.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 删除租户充值信息信息 + * + * @param id + * 租户充值信息主键 + * @return 结果 + */ + @Override + public int deleteSysTenantRechargeInfoById(String id) { + return sysTenantRechargeInfoMapper.deleteById(id); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/service/impl/SysTenantServiceImpl.java --- +package com.starry.admin.modules.system.service.impl; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.RandomUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson2.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.starry.admin.common.domain.LoginUser; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.clerk.service.IPlayClerkLevelInfoService; +import com.starry.admin.modules.custom.service.IPlayCustomLevelInfoService; +import com.starry.admin.modules.shop.service.IPlayCommodityInfoService; +import com.starry.admin.modules.system.mapper.*; +import com.starry.admin.modules.system.module.entity.*; +import com.starry.admin.modules.system.service.ISysTenantService; +import com.starry.admin.modules.system.service.SysRoleMenuService; +import com.starry.admin.modules.system.vo.SysTenantQueryVo; +import com.starry.admin.utils.SecurityUtils; +import com.starry.common.constant.CacheConstants; +import com.starry.common.redis.RedisCache; +import com.starry.common.result.R; +import com.starry.common.utils.IdUtils; +import com.tencentcloudapi.common.Credential; +import com.tencentcloudapi.common.exception.TencentCloudSDKException; +import com.tencentcloudapi.dnspod.v20210323.DnspodClient; +import com.tencentcloudapi.dnspod.v20210323.models.CreateRecordRequest; +import com.tencentcloudapi.dnspod.v20210323.models.CreateRecordResponse; +import java.util.*; +import java.util.stream.Collectors; +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * 租户表Service业务层处理 + * + * @author admin + * @since 2023-03-03 + */ +@Slf4j +@Service +public class SysTenantServiceImpl extends ServiceImpl implements ISysTenantService { + @Resource + private SysTenantMapper sysTenantMapper; + @Resource + private SysTenantPackageMapper tenantPackageMapper; + @Resource + private SysUserMapper sysUserMapper; + @Resource + private SysDeptMapper deptMapper; + @Resource + private SysRoleMapper roleMapper; + @Resource + private SysRoleMenuService roleMenuService; + @Resource + private SysUserRoleMapper userRoleMapper; + @Resource + private SysRoleMenuMapper sysRoleMenuMapper; + @Resource + private RedisCache redisCache; + + @Resource + private IPlayCustomLevelInfoService playCustomLevelInfoService; + + @Resource + private IPlayClerkLevelInfoService playClerkLevelInfoService; + + @Resource + private IPlayCommodityInfoService playCommodityInfoService; + + @Override + public List listAll() { + return this.baseMapper.selectList(new LambdaQueryWrapper<>()); + } + + @Override + public SysTenantEntity selectByTenantKey(String tenantKey) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(SysTenantEntity::getTenantKey, tenantKey); + SysTenantEntity tenant = this.baseMapper.selectOne(lambdaQueryWrapper); + if (Objects.isNull(tenant)) { + throw new RuntimeException("租户信息异常"); + } + if (DateUtil.compare(tenant.getTenantTime(), new Date()) < 0) { + throw new RuntimeException("当前租户已过期,无法继续使用"); + } + if ("1".equals(tenant.getTenantStatus())) { + throw new RuntimeException("当前租户已被禁用"); + } + return tenant; + } + + /** + * 查询租户表 + * + * @param tenantId + * 租户表主键 + * @return 租户表 + */ + @Override + public SysTenantEntity selectSysTenantByTenantId(String tenantId) { + SysTenantEntity entity = this.baseMapper.selectById(tenantId); + if (entity == null) { + throw new CustomException("租户对象为空"); + } + return entity; + } + + /** + * 查询租户表列表 + * + * @param vo + * 租户表 + * @return 租户表 + */ + @Override + public IPage selectSysTenantList(SysTenantQueryVo vo) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.orderByDesc(SysTenantEntity::getCreatedTime); + + if (StrUtil.isNotBlank(vo.getTenantName())) { + wrapper.like(SysTenantEntity::getTenantName, vo.getTenantName()); + } + // if (StrUtil.isNotBlank(vo.getBeginTime())) { + // wrapper.ge(SysTenantEntity::getTenantTime, vo.getBeginTime()); + // } + // if (StrUtil.isNotBlank(vo.getEndTime())) { + // wrapper.le(SysTenantEntity::getTenantTime, vo.getEndTime()); + // } + return this.baseMapper.selectPage(new Page<>(vo.getPageNum(), vo.getPageSize()), wrapper); + } + + /** + * 新增租户表 + * + * @param sysTenantEntity + * 租户表 + * @return 结果 + */ + @Override + public boolean create(SysTenantEntity sysTenantEntity) { + return save(sysTenantEntity); + } + + /** + * 修改租户表 + * + * @param sysTenantEntity + * 租户表 + * @return 结果 + */ + @Override + public boolean update(SysTenantEntity sysTenantEntity) { + return updateById(sysTenantEntity); + } + + /** + * 批量删除租户表 + * + * @param tenantIds + * 需要删除的租户表主键 + * @return 结果 + */ + @Transactional(rollbackFor = Exception.class) + @Override + public int deleteSysTenantByTenantIds(String[] tenantIds) { + int num = sysTenantMapper.deleteTenantByIds(tenantIds); + if (num > 0) { + // 下面才会进行子模块数据的删除 + // 部门模块 + deptMapper.deleteDeptByTenantId(tenantIds); + // 权限 + roleMapper.deleteRoleByTenantId(tenantIds); + sysRoleMenuMapper.deleteRoleMenuByTenantIds(tenantIds); + // 账号 + sysUserMapper.deleteUserByTenantId(tenantIds); + userRoleMapper.deleteUserRoleByTenantId(tenantIds); + } else { + throw new RuntimeException("当前租户已被删除不存在!"); + } + return 1; + } + + /** + * 删除租户表信息 + * + * @param tenantId + * 租户表主键 + * @return 结果 + */ + @Override + public int deleteSysTenantByTenantId(Long tenantId) { + return sysTenantMapper.deleteById(tenantId); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public R addTenant(SysTenantEntity sysTenantEntity) { + // 判断账号是否存在 + if (sysUserMapper.checkUserNameUnique(sysTenantEntity.getUserName()) > 0) { + return R.error("管理员账号已存在,请重新设置!"); + } + if (sysTenantEntity.getProfitsharingRate() < 0 || sysTenantEntity.getProfitsharingRate() > 30) { + throw new RuntimeException("分账抽成参数不得小于0,不得大于30"); + } + if (StrUtil.isBlankIfStr(sysTenantEntity.getTenantId())) { + sysTenantEntity.setTenantId(IdUtils.getUuid()); + } + if (StrUtil.isBlankIfStr(sysTenantEntity.getTenantCode())) { + sysTenantEntity.setTenantCode(IdUtils.getUuid()); + } + // 生成随机key,用来生成域名,关键! + sysTenantEntity.setTenantKey(RandomUtil.randomString(8).toLowerCase()); + // 创建租户 + sysTenantEntity.setCreatedTime(new Date()); + sysTenantMapper.insert(sysTenantEntity); + // 创建默认账号 + createUser(sysTenantEntity); + // 创建域名 + this.createDomainAndDns(sysTenantEntity.getTenantKey()); + this.initRole(sysTenantEntity); + // 初始化店铺等级数据和用户等级数据 + playCustomLevelInfoService.initDefaultLevel(sysTenantEntity); + playClerkLevelInfoService.initDefaultLevel(sysTenantEntity); + // 初始化店铺服务信息 + playCommodityInfoService.initPlayCommodityInfo(sysTenantEntity.getTenantId()); + return R.ok("租户创建成功!"); + } + + /** + * 目前为单套餐,跟租户绑定,解耦防止套餐变动影响多个租户 + **/ + private void createRoleMenu(SysTenantEntity sysTenantEntity, SysRoleEntity role) { + SysTenantPackageEntity sysTenantPackage = tenantPackageMapper.selectById(sysTenantEntity.getPackageId()); + List subMeuns = Arrays.asList(sysTenantPackage.getMenuIds().split(",")); + + List roleMenuList = subMeuns.stream().map(menuid -> { + SysRoleMenuEntity entity = new SysRoleMenuEntity(); + entity.setRoleId(role.getRoleId()); + entity.setMenuId(Long.valueOf(menuid)); + entity.setTenantId(sysTenantEntity.getTenantId()); + return entity; + }).collect(Collectors.toList()); + roleMenuService.saveBatch(roleMenuList); + } + + private void createUser(SysTenantEntity sysTenant) { + SysUserEntity user = new SysUserEntity(); + user.setUserCode(sysTenant.getUserName()); + user.setRealName(sysTenant.getTenantName()); + user.setUserNickname(sysTenant.getTenantName()); + user.setUserType(1); + user.setUserEmail(sysTenant.getEmail()); + user.setMobile(sysTenant.getPhone()); + user.setCreatedTime(new Date()); + String password = SecurityUtils.encryptPassword(sysTenant.getUserPwd()); + user.setPassWord(password); + user.setTenantId(sysTenant.getTenantId()); + user.setUserId(IdUtils.getUuid()); + user.setSuperAdmin(true); + sysUserMapper.insert(user); + + SysUserEntity superUser = new SysUserEntity(); + superUser.setUserCode("sysadmin"); + superUser.setRealName("超级管理员"); + superUser.setUserNickname("超级管理员"); + superUser.setUserType(1); + superUser.setMobile("0000"); + superUser.setCreatedTime(new Date()); + superUser.setPassWord(SecurityUtils.encryptPassword("123456")); + superUser.setTenantId(sysTenant.getTenantId()); + superUser.setUserId(IdUtils.getUuid()); + superUser.setSuperAdmin(true); + sysUserMapper.insert(superUser); + // createUserRole(sysTenant.getTenantId(), user.getUserId(), roleId); + } + + @Override + public R updateTenant(SysTenantEntity sysTenantEntity) { + // 判断最新的租户套餐是否改变 重新授权 租户二级管理员账号需重新分配三级账号权限 + SysTenantEntity newTenant = sysTenantMapper.selectById(sysTenantEntity.getTenantId()); + if (sysTenantEntity.getPackageId() != null + && !sysTenantEntity.getPackageId().equals(newTenant.getPackageId())) { + List roleList = roleMapper.queryAdminRole(sysTenantEntity.getTenantId()); + // 正常逻辑下每个租户只有一个二级管理员账号 + SysRoleEntity tRole = roleList.get(0); + if (tRole != null) { + // 删除原租户下所有的角色-菜单信息 + sysRoleMenuMapper.deleteRoleMenuByTenantId(sysTenantEntity.getTenantId()); + // 新增默认角色-菜单信息 + createRoleMenu(sysTenantEntity, tRole); + // 原登录租户账号退出重登 + Collection keys = redisCache.keys(CacheConstants.LOGIN_TOKEN_KEY + "*"); + if (CollectionUtil.isNotEmpty(keys)) { + for (String key : keys) { + LoginUser onlineUser = redisCache.getCacheObject(key); + if (onlineUser.getUser().getTenantId() != null + && onlineUser.getUser().getTenantId().equals(sysTenantEntity.getTenantId())) { + redisCache.deleteObject(key); + } + } + } + } + } + sysTenantMapper.updateById(sysTenantEntity); + return R.ok(); + } + + @Override + public List queryByPackage(String packageId) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(SysTenantEntity::getTenantId, packageId); + return this.baseMapper.selectList(queryWrapper); + } + + public void createDomainAndDns(String tenentKey) { + Credential cred = new Credential("AKIDxypW8arxqY5ThleNyTtAFUYWM0ShnjSC", "kMo3RhnjV6XowxqaNN9mCTbYP8iDVdWG"); + DnspodClient dnspodClient = new DnspodClient(cred, ""); + CreateRecordRequest req = new CreateRecordRequest(); + req.setDomain("julyharbor.com"); + req.setRecordType("A"); + req.setRecordLine("默认"); + req.setValue("122.51.20.105"); + req.setSubDomain(tenentKey); + CreateRecordResponse createRecordResponse; + try { + createRecordResponse = dnspodClient.CreateRecord(req); + } catch (TencentCloudSDKException e) { + throw new RuntimeException(e); + } + log.info("腾讯云域名映射结果:{}", JSONObject.toJSONString(createRecordResponse)); + } + + @Override + public void initRole(SysTenantEntity sysTenantEntity) { + + SysRoleEntity operator = new SysRoleEntity(); + operator.setRoleName("管理员"); + operator.setRoleKey("operator"); + operator.setDescription("管理员角色系统默认创建"); + operator.setDataScope("1"); + operator.setMenuCheckStrictly(true); + operator.setDeptCheckStrictly(true); + operator.setTenantId(sysTenantEntity.getTenantId()); + roleMapper.insert(operator); + + SysTenantPackageEntity sysTenantPackage = tenantPackageMapper.selectById(sysTenantEntity.getPackageId()); + List subMeuns = new ArrayList<>(Arrays.asList(sysTenantPackage.getMenuIds().split(","))); + if (CollectionUtil.isEmpty(subMeuns)) { + subMeuns = new ArrayList<>(); + } + subMeuns.remove("2089"); + subMeuns.remove("2088"); + subMeuns.remove("2093"); + subMeuns.remove("6"); + List roleMenuEntityList = subMeuns.stream().map(menu -> { + SysRoleMenuEntity rm = new SysRoleMenuEntity(); + rm.setRoleId(operator.getRoleId()); + rm.setMenuId(Long.valueOf(menu)); + return rm; + }).collect(Collectors.toList()); + roleMenuService.saveBatch(roleMenuEntityList); + + SysRoleEntity waiter = new SysRoleEntity(); + waiter.setRoleName("客服"); + waiter.setRoleKey("waiter"); + waiter.setDataScope("1"); + waiter.setDescription("客服角色系统默认创建"); + waiter.setMenuCheckStrictly(true); + waiter.setDeptCheckStrictly(true); + waiter.setTenantId(sysTenantEntity.getTenantId()); + roleMapper.insert(waiter); + + List waiterMenuIdList = Arrays.asList(102, 1100, 1101, 1103, 1104, 1105); + List waiterMenuList = waiterMenuIdList.stream().map(menu -> { + SysRoleMenuEntity rm = new SysRoleMenuEntity(); + rm.setRoleId(waiter.getRoleId()); + rm.setMenuId(Long.valueOf(menu)); + return rm; + }).collect(Collectors.toList()); + roleMenuService.saveBatch(waiterMenuList); + + SysRoleEntity leader = new SysRoleEntity(); + leader.setRoleName("组长"); + leader.setRoleKey("leader"); + leader.setDescription("组长角色系统默认创建"); + leader.setDataScope("3"); + leader.setMenuCheckStrictly(true); + leader.setDeptCheckStrictly(true); + leader.setTenantId(sysTenantEntity.getTenantId()); + roleMapper.insert(leader); + + List leaderMenuIdList = Arrays.asList(101, 102, 1000, 2095, 2096, 2097, 2087, 1001, 1100, 1101, 105, + 2094); + List leaderMenuList = leaderMenuIdList.stream().map(menu -> { + SysRoleMenuEntity rm = new SysRoleMenuEntity(); + rm.setRoleId(leader.getRoleId()); + rm.setMenuId(Long.valueOf(menu)); + return rm; + }).collect(Collectors.toList()); + roleMenuService.saveBatch(leaderMenuList); + + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/service/impl/SysUserRoleServiceImpl.java --- +package com.starry.admin.modules.system.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.starry.admin.modules.system.mapper.SysUserRoleMapper; +import com.starry.admin.modules.system.module.entity.SysUserRoleEntity; +import com.starry.admin.modules.system.service.SysUserRoleService; +import com.starry.admin.modules.system.service.SysUserService; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + *

+ * 用户角色关联表 服务实现类 + *

+ * + * @author admin + * @since 2022-07-08 + */ +@Service +public class SysUserRoleServiceImpl extends ServiceImpl + implements + SysUserRoleService { + + @Resource + private SysUserService userService; + + @Override + public void delUserRole(String userId, Long roleId) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(SysUserRoleEntity::getUserId, userId); + queryWrapper.eq(SysUserRoleEntity::getRoleId, roleId); + this.remove(queryWrapper); + // 强制退出指定用户 + userService.logoutUser(userId); + } + + @Override + public void addUserRole(String userId, Long roleId) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(SysUserRoleEntity::getUserId, userId); + queryWrapper.eq(SysUserRoleEntity::getRoleId, roleId); + SysUserRoleEntity userRole = this.baseMapper.selectOne(queryWrapper); + if (userRole == null) { + userRole = new SysUserRoleEntity(); + userRole.setUserId(userId); + userRole.setRoleId(roleId); + this.baseMapper.insert(userRole); + } else { + userRole.setUserId(userId); + userRole.setRoleId(roleId); + this.baseMapper.updateById(userRole); + } + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/service/impl/SysUserServiceImpl.java --- +package com.starry.admin.modules.system.service.impl; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.github.yulichang.wrapper.MPJLambdaWrapper; +import com.starry.admin.manager.AsyncManager; +import com.starry.admin.manager.factory.AsyncFactory; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity; +import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService; +import com.starry.admin.modules.personnel.module.entity.PlayPersonnelAdminInfoEntity; +import com.starry.admin.modules.personnel.module.entity.PlayPersonnelGroupInfoEntity; +import com.starry.admin.modules.personnel.module.entity.PlayPersonnelWaiterInfoEntity; +import com.starry.admin.modules.personnel.module.vo.PlayPersonnelUserInfoQueryVo; +import com.starry.admin.modules.personnel.module.vo.PlayPersonnelUserInfoReturnVo; +import com.starry.admin.modules.personnel.service.IPlayPersonnelAdminInfoService; +import com.starry.admin.modules.personnel.service.IPlayPersonnelGroupInfoService; +import com.starry.admin.modules.personnel.service.IPlayPersonnelWaiterInfoService; +import com.starry.admin.modules.system.mapper.SysRoleMapper; +import com.starry.admin.modules.system.mapper.SysUserMapper; +import com.starry.admin.modules.system.module.entity.SysRoleEntity; +import com.starry.admin.modules.system.module.entity.SysUserEntity; +import com.starry.admin.modules.system.module.entity.SysUserRoleEntity; +import com.starry.admin.modules.system.service.SysUserRoleService; +import com.starry.admin.modules.system.service.SysUserService; +import com.starry.admin.modules.system.vo.*; +import com.starry.admin.utils.SecurityUtils; +import com.starry.admin.utils.SmsUtils; +import com.starry.common.annotation.DataScope; +import com.starry.common.constant.Constants; +import com.starry.common.constant.UserConstants; +import com.starry.common.redis.RedisCache; +import com.starry.common.utils.IdUtils; +import com.starry.common.utils.StringUtils; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + *

+ * 后台用户表 服务实现类 + *

+ * + * @author admin + * @since 2021-09-03 + */ +@Slf4j +@Service +public class SysUserServiceImpl extends ServiceImpl implements SysUserService { + + @Resource + private PasswordEncoder passwordEncoder; + @Resource + private SysUserRoleService userRoleService; + @Resource + private SysRoleMapper sysRoleMapper; + @Resource + private IPlayClerkUserInfoService clerkUserInfoService; + @Resource + private IPlayPersonnelAdminInfoService playPersonnelAdminInfoService; + @Resource + private IPlayPersonnelGroupInfoService playClerkGroupInfoService; + @Resource + private IPlayPersonnelWaiterInfoService playClerkWaiterInfoService; + @Resource + private RedisCache redisCache; + @Resource + private SmsUtils smsUtils; + + @Override + public List selectAll() { + LambdaQueryWrapper lambdaWrapper = new LambdaQueryWrapper<>(); + lambdaWrapper.select(SysUserEntity::getUserId, SysUserEntity::getUserCode); + return this.baseMapper.selectList(lambdaWrapper); + + } + + @Override + public IPage selectByPage(PlayPersonnelUserInfoQueryVo vo) { + MPJLambdaWrapper lambdaWrapper = new MPJLambdaWrapper<>(); + lambdaWrapper.selectAll(SysUserEntity.class); + // 店员表 + lambdaWrapper.selectAs(PlayClerkUserInfoEntity::getId, "clerkId") + .selectAs(PlayClerkUserInfoEntity::getAvatar, "clerkAvatar") + .selectAs(PlayClerkUserInfoEntity::getNickname, "clerkNickname"); + lambdaWrapper.leftJoin(PlayClerkUserInfoEntity.class, PlayClerkUserInfoEntity::getId, SysUserEntity::getUserId); + if (StrUtil.isNotBlank(vo.getSysUserId())) { + lambdaWrapper.eq(SysUserEntity::getUserId, vo.getSysUserId()); + } + if (StrUtil.isNotBlank(vo.getUserCode())) { + lambdaWrapper.eq(SysUserEntity::getUserCode, vo.getUserCode()); + } + if (StrUtil.isNotBlank(vo.getRuleType())) { + if ("0".equals(vo.getRuleType())) { + lambdaWrapper.leftJoin(PlayClerkUserInfoEntity.class, PlayClerkUserInfoEntity::getSysUserId, + SysUserEntity::getUserId); + } else if ("1".equals(vo.getRuleType())) { + lambdaWrapper.leftJoin(PlayPersonnelWaiterInfoEntity.class, PlayPersonnelWaiterInfoEntity::getSysUserId, + SysUserEntity::getUserId); + } else if ("2".equals(vo.getRuleType())) { + lambdaWrapper.leftJoin(PlayPersonnelGroupInfoEntity.class, PlayPersonnelGroupInfoEntity::getSysUserId, + SysUserEntity::getUserId); + } + } + if (vo.getAddTime() != null && vo.getAddTime().size() == 2) { + lambdaWrapper.between(SysUserEntity::getAddTime, vo.getAddTime().get(0), vo.getAddTime().get(1)); + } + + return this.baseMapper.selectJoinPage(new Page<>(vo.getPageNum(), vo.getPageSize()), + PlayPersonnelUserInfoReturnVo.class, lambdaWrapper); + } + + @Override + public SysUserEntity register(SysUserEntity user) { + SysUserEntity newSysUserEntity = new SysUserEntity(); + BeanUtils.copyProperties(user, newSysUserEntity); + // 查询是否有相同用户名的用户 + List sysUserEntities = this.baseMapper.selectList( + new LambdaQueryWrapper().eq(SysUserEntity::getUserCode, newSysUserEntity.getUserCode())); + if (CollectionUtil.isNotEmpty(sysUserEntities)) { + return null; + } + // 将密码进行加密操作 + String encodePassword = passwordEncoder.encode(user.getPassWord()); + newSysUserEntity.setPassWord(encodePassword); + this.baseMapper.insert(newSysUserEntity); + return newSysUserEntity; + } + + @Override + public SysUserEntity getUserByCode(String userCode) { + List users = baseMapper + .selectList(new LambdaQueryWrapper().eq(SysUserEntity::getUserCode, userCode)); + if (CollectionUtil.isNotEmpty(users)) { + return users.get(0); + } + return null; + } + + @Override + public SysUserEntity selectUserByUserName(String userName) { + return baseMapper.selectUserByUserName(userName); + } + + @Override + public SysUserEntity selectUserByUserNameAndTenantId(String userName, String tenantId) { + return baseMapper.selectUserByUserNameAndTenantId(userName, tenantId); + } + + @Override + public IPage listMemberPage(UserQueryVo queryVo) { + Page page = new Page<>(queryVo.getPageNum(), queryVo.getPageSize()); + return baseMapper.selectUserList(page, queryVo); + } + + @Override + public String checkUserNameUnique(String userCode) { + // 查询是否有相同用户名的用户 + List userList = this.baseMapper + .selectList(new LambdaQueryWrapper().eq(SysUserEntity::getUserCode, userCode)); + if (CollectionUtil.isNotEmpty(userList)) { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public boolean create(SysUserEntity user) { + // 将密码进行加密操作 + String encodePassword = passwordEncoder.encode(user.getPassWord()); + user.setPassWord(encodePassword); + if (StrUtil.isBlankIfStr(user.getUserId())) { + user.setUserId(IdUtils.getUuid()); + } + boolean flag = save(user); + if (flag) { + // 新增用户角色信息 + flag = insertUserRole(user); + } + return flag; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public boolean update(SysUserEntity user) { + boolean flag = updateById(user); + if (flag) { + // 删除用户角色信息 + userRoleService.remove( + new LambdaQueryWrapper().eq(SysUserRoleEntity::getUserId, user.getUserId())); + // 新增用户角色信息 + flag = insertUserRole(user); + } + return flag; + + } + + @Transactional(rollbackFor = Exception.class) + @Override + public boolean delete(List ids) { + if (CollectionUtil.isNotEmpty(ids)) { + boolean flag = this.removeBatchByIds(ids); + if (flag) { + // 删除用户角色表 + userRoleService + .remove(new LambdaQueryWrapper().in(SysUserRoleEntity::getUserId, ids)); + } + } + return true; + } + + @Override + public SysUserEntity selectUserById(String userId) { + if (StringUtils.isEmpty(userId)) { + userId = SecurityUtils.getUserId(); + } + baseMapper.selectById(userId); + SysUserEntity data = baseMapper.selectUserById(userId); + if (Objects.isNull(data)) { + throw new RuntimeException("未查询到指定用户或该用户状态异常"); + } + return data; + } + + @Override + public String selectUserRoleGroup(String userId) { + List list = sysRoleMapper.selectRolePermissionByUserId(userId); + if (CollectionUtil.isEmpty(list)) { + return StringUtils.EMPTY; + } + return list.stream().map(SysRoleEntity::getRoleName).collect(Collectors.joining(",")); + } + + @Override + public boolean updateUserAvatar(String userId, String avatar) { + SysUserEntity user = getById(userId); + if (user != null) { + user.setAvatar(avatar); + return updateById(user); + } + return false; + } + + /** + * 新增用户角色信息 + * + * @param user + * 用户对象 + */ + public boolean insertUserRole(SysUserEntity user) { + if (user.getRoleIds() != null && user.getRoleIds().length > 0) { + // 新增用户与角色管理 + List list = new ArrayList<>(user.getRoleIds().length); + for (Long roleId : user.getRoleIds()) { + SysUserRoleEntity ur = new SysUserRoleEntity(); + ur.setUserId(user.getUserId()); + ur.setRoleId(roleId); + list.add(ur); + } + return userRoleService.saveBatch(list); + } + return true; + } + + /** + * 根据条件分页查询已分配用户角色列表 + * + * @param userQueryVo + * 用户信息 + * @return 用户信息集合信息 + */ + @Override + @DataScope(deptAlias = "d", userAlias = "u") + public IPage selectAllocatedList(SysUserQueryVo userQueryVo) { + return baseMapper.selectAllocatedList(new Page<>(userQueryVo.getPageNum(), userQueryVo.getPageSize()), + userQueryVo); + } + + /** + * 根据条件分页查询未分配用户角色列表 + * + * @param user + * 用户信息 + * @return 用户信息集合信息 + */ + @Override + @DataScope(deptAlias = "d", userAlias = "u") + public IPage selectUnallocatedList(SysUserQueryVo user) { + return baseMapper.selectUnallocatedList(new Page<>(user.getPageNum(), user.getPageSize()), user); + } + + @Override + public boolean addV1(UserAddParam param) { + long count = this + .count(Wrappers.lambdaQuery(SysUserEntity.class).eq(SysUserEntity::getClerkId, param.getClerkId())); + if (count > 0) { + throw new RuntimeException("该店员已经成为员工了,无法再次添加~"); + } + smsUtils.checkSmsCode(param.getMobile(), param.getSmsCode()); + PlayClerkUserInfoEntity clerk = clerkUserInfoService.selectById(param.getClerkId()); + SysUserEntity user = new SysUserEntity().setClerkId(param.getClerkId()).setMobile(param.getMobile()) + .setPassWord(SecurityUtils.encryptPassword(param.getMobile())).setUserCode(param.getMobile()) + .setUserNickname(clerk.getNickname()).setRealName(clerk.getNickname()); + user.setUserId(IdUtils.getUuid()); + user.setSuperAdmin(false); + this.save(user); + clerkUserInfoService.update(null, + Wrappers.lambdaUpdate(PlayClerkUserInfoEntity.class) + .eq(PlayClerkUserInfoEntity::getId, param.getClerkId()) + .set(PlayClerkUserInfoEntity::getSysUserId, user.getUserId())); + return true; + } + + @Override + public List generatePageData(List records) { + return records.stream().map(ca -> { + SysUserEntityListVo vo = new SysUserEntityListVo(); + BeanUtils.copyProperties(ca, vo); + if (StringUtils.isNotEmpty(ca.getClerkId())) { + vo.setClerkUserInfo(clerkUserInfoService.selectById(ca.getClerkId())); + } + // 查询角色 + List roleList = new ArrayList<>(); + PlayPersonnelAdminInfoEntity adminInfoEntity = playPersonnelAdminInfoService.selectByUserId(ca.getUserId()); + if (Objects.nonNull(adminInfoEntity)) { + roleList.add(new SysUserEntityListVo.RoleVo("管理员", adminInfoEntity.getAdminName())); + } + PlayPersonnelGroupInfoEntity groupInfoEntity = playClerkGroupInfoService.selectByUserId(ca.getUserId()); + if (Objects.nonNull(groupInfoEntity)) { + roleList.add(new SysUserEntityListVo.RoleVo("组长", groupInfoEntity.getLeaderName())); + } + PlayPersonnelWaiterInfoEntity waiterInfoEntity = playClerkWaiterInfoService.selectByUserId(ca.getUserId()); + if (Objects.nonNull(waiterInfoEntity)) { + roleList.add(new SysUserEntityListVo.RoleVo("客服", waiterInfoEntity.getWaiterName())); + } + + vo.setRoleVoList(roleList); + return vo; + }).collect(Collectors.toList()); + } + + @Override + public void updatePassword(UpdateUserPasswordParam param) { + selectUserById(param.getUserId()); + this.update(Wrappers.lambdaUpdate(SysUserEntity.class).eq(SysUserEntity::getUserId, param.getUserId()) + .set(SysUserEntity::getPassWord, SecurityUtils.encryptPassword(param.getPassword()))); + } + + @Override + public void updateMobile(UpdateUserMobileParam param) { + SysUserEntity user = selectUserById(param.getUserId()); + if (user.getMobile().equals(param.getMobile())) { + throw new RuntimeException("新旧手机号不能相同~"); + } + // 查询是否已有相同手机号 + long count = this.count(Wrappers.lambdaQuery(SysUserEntity.class) + .eq(SysUserEntity::getMobile, param.getMobile()).ne(SysUserEntity::getUserId, param.getUserId())); + if (count > 0) { + throw new RuntimeException("系统中已有该手机号,无法录入~"); + } + this.update(Wrappers.lambdaUpdate(SysUserEntity.class).eq(SysUserEntity::getUserId, param.getUserId()) + .set(SysUserEntity::getUserCode, param.getMobile()).set(SysUserEntity::getMobile, param.getMobile())); + } + + @Override + public void logoutUser(String uid) { + String key = "login:resource:" + uid; + Object object = redisCache.getCacheObject(key); + if (Objects.isNull(object)) + return; + + String key2 = object.toString(); + redisCache.deleteObject(key2); + } + + @Override + public void updatePasswordV2(UpdateUserPasswordParamV2 param) { + String userId = SecurityUtils.getUserId(); + SysUserEntity user = selectUserById(userId); + if (!passwordEncoder.matches(param.getOldPassword(), user.getPassWord())) { + throw new BadCredentialsException("旧密码不正确"); + } + this.update(Wrappers.lambdaUpdate(SysUserEntity.class).eq(SysUserEntity::getUserId, userId) + .set(SysUserEntity::getPassWord, SecurityUtils.encryptPassword(param.getNewPassword()))); + AsyncManager.me().execute(AsyncFactory.recordLoginLog(user.getUserCode(), Constants.LOGIN_SUCCESS, "修改密码")); + logoutUser(userId); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/service/impl/UserOnlineServiceImpl.java --- +package com.starry.admin.modules.system.service.impl; + +import com.starry.admin.common.domain.LoginUser; +import com.starry.admin.modules.system.module.entity.UserOnline; +import com.starry.admin.modules.system.service.UserOnlineService; +import com.starry.common.utils.StringUtils; +import org.springframework.stereotype.Service; + +/** + * @author admin + * @since 2022/10/18 + */ +@Service +public class UserOnlineServiceImpl implements UserOnlineService { + + @Override + public UserOnline selectOnlineByInfo(String ipaddr, String userName, LoginUser user) { + if (StringUtils.equals(ipaddr, user.getIpaddr()) && StringUtils.equals(userName, user.getUsername())) { + return setUserOnline(user); + } + return null; + } + + @Override + public UserOnline selectOnlineByIpaddr(String ipaddr, LoginUser user) { + if (StringUtils.equals(ipaddr, user.getIpaddr())) { + return setUserOnline(user); + } + return null; + } + + @Override + public UserOnline selectOnlineByUserName(String userName, LoginUser user) { + if (StringUtils.equals(userName, user.getUsername())) { + return setUserOnline(user); + } + return null; + } + + @Override + public UserOnline setUserOnline(LoginUser user) { + if (StringUtils.isNull(user) || StringUtils.isNull(user.getUser())) { + return null; + } + UserOnline userOnline = new UserOnline(); + userOnline.setTokenId(user.getToken()); + userOnline.setUserName(user.getUsername()); + userOnline.setIpaddr(user.getIpaddr()); + userOnline.setLoginLocation(user.getLoginLocation()); + userOnline.setBrowser(user.getBrowser()); + userOnline.setOs(user.getOs()); + userOnline.setLoginTime(user.getLoginTime()); + if (StringUtils.isNotNull(user.getUser().getDept())) { + userOnline.setDeptName(user.getUser().getDept().getDeptName()); + } + return userOnline; + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/vo/AdministrativeAreaQueryReturnVo.java --- +package com.starry.admin.modules.system.vo; + +import java.util.ArrayList; +import java.util.List; +import lombok.Data; + +/** + * 行政区域信息集合 play_administrative_area_dict_info + * + * @author admin + * @since 2024-04-03 + */ +@Data +public class AdministrativeAreaQueryReturnVo { + + /** + * 编码 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 区域集合 + **/ + private List child = new ArrayList<>(); + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/vo/LoginVo.java --- +package com.starry.admin.modules.system.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import lombok.Data; + +/** + * @author huoqiang + * @since 2021/9/6 + */ +@Data +@ApiModel(value = "登录参数", description = "用户登录的请求参数") +public class LoginVo implements Serializable { + + @ApiModelProperty(value = "用户名", required = true, example = "admin", notes = "登录账号") + private String userName; + + @ApiModelProperty(value = "密码", required = true, example = "123456", notes = "登录密码") + private String passWord; + + @ApiModelProperty(value = "验证码随机字符串", example = "abc123", notes = "验证码请求时返回的唯一标识") + private String nonceStr; + + @ApiModelProperty(value = "验证码", example = "1234", notes = "用户输入的验证码") + private String value; + + @ApiModelProperty(value = "租户标识", example = "tenant1", notes = "多租户模式下的租户唯一标识") + private String tenantKey; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/vo/MemberQueryVo.java --- +package com.starry.admin.modules.system.vo; + +import com.starry.common.domain.BasePageEntity; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @author admin + * @since 2021/9/2 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class MemberQueryVo extends BasePageEntity { + + @ApiModelProperty(value = "用户名") + private String userName; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/vo/MetaVo.java --- +package com.starry.admin.modules.system.vo; + +import com.starry.common.constant.Constants; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.apache.commons.lang3.StringUtils; + +/** + * @author admin 路由显示信息 + * @since 2022/7/6 + */ +@Data +@ApiModel(value = "路由元数据", description = "路由显示信息配置") +public class MetaVo { + + /** + * 设置该路由在侧边栏和面包屑中展示的名字 + */ + @ApiModelProperty(value = "路由标题", example = "系统管理", notes = "设置该路由在侧边栏和面包屑中展示的名字") + private String title; + + /** + * 设置该路由的图标,对应路径src/assets/icons/svg + */ + @ApiModelProperty(value = "路由图标", example = "system", notes = "设置该路由的图标,对应路径src/assets/icons/svg") + private String icon; + + /** + * 设置为true,则不会被 缓存 + */ + @ApiModelProperty(value = "是否缓存", example = "false", notes = "设置为true,则不会被缓存") + private boolean noCache; + + /** + * 内链地址(http(s)://开头) + */ + @ApiModelProperty(value = "内链地址", example = "https://www.example.com", notes = "内链地址(http(s)://开头)") + private String link; + + public MetaVo(String title, String icon) { + this.title = title; + this.icon = icon; + } + + public MetaVo(String title, String icon, String link) { + this.title = title; + this.icon = icon; + this.link = link; + } + + public MetaVo(String title, String icon, boolean noCache, String link) { + this.title = title; + this.icon = icon; + this.noCache = noCache; + if (StringUtils.startsWithAny(link, Constants.HTTP, Constants.HTTPS)) { + this.link = link; + } + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/vo/RoleUserResultVo.java --- +package com.starry.admin.modules.system.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.Date; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * @author admin 角色分配用户精简信息Vo + * @since 2023/3/10 + */ +@ApiModel("管理后台 - 角色分配用户返回信息") +@Data +public class RoleUserResultVo { + + @ApiModelProperty(value = "用户ID") + private Long userId; + + @ApiModelProperty(value = "用户类型;1:admin;2:会员") + private Integer userType; + + @ApiModelProperty(value = "用户名") + private String userCode; + + @ApiModelProperty(value = "姓名") + private String realName; + + @ApiModelProperty(value = "用户昵称") + private String userNickname; + + @ApiModelProperty(value = "邮箱") + private String userEmail; + + @ApiModelProperty(value = "中国手机不带国家代码,国际手机号格式为:国家代码-手机号") + private String mobile; + + @ApiModelProperty(value = "用户状态;0正常 1停用") + private Integer status; + + @ApiModelProperty(value = "所属部门id") + private Long deptId; + + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "创建时间") + private Date createdTime; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/vo/RouterVo.java --- +package com.starry.admin.modules.system.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import lombok.Data; + +/** + * @author admin 路由配置信息 + * @since 2022/7/6 + */ +@Data +@ApiModel(value = "路由信息", description = "前端路由配置信息") +public class RouterVo { + + @ApiModelProperty(value = "路由名字", example = "System", notes = "路由的唯一标识名称") + private String name; + + @ApiModelProperty(value = "路由地址", example = "/system", notes = "URL路径") + private String path; + + @ApiModelProperty(value = "是否隐藏路由", example = "false", notes = "当设置为true时该路由不会在侧边栏出现") + private boolean hidden; + + @ApiModelProperty(value = "重定向地址", example = "noRedirect", notes = "当设置noRedirect时该路由在面包屑导航中不可被点击") + private String redirect; + + @ApiModelProperty(value = "组件地址", example = "Layout", notes = "对应的前端组件路径") + private String component; + + /** + * 路由参数:如 {"id": 1, "name": "ry"} + */ + @ApiModelProperty(value = "路由参数", example = "{\"id\": 1, \"name\": \"admin\"}", notes = "路由参数,JSON格式") + private String routerQuery; + + @ApiModelProperty(value = "是否总是显示", example = "true", notes = "当一个路由下面的children声明的路由大于1个时,自动会变成嵌套的模式") + private Boolean alwaysShow; + + @ApiModelProperty(value = "路由元信息", notes = "路由的其他配置信息") + private MetaVo meta; + + @ApiModelProperty(value = "子路由", notes = "子路由配置信息") + private List children; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/vo/SimpleMenu.java --- +package com.starry.admin.modules.system.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author admin + */ +@ApiModel("管理后台 - 菜单精简信息") +@Data +@NoArgsConstructor +@AllArgsConstructor +public class SimpleMenu { + + @ApiModelProperty(value = "菜单编号", required = true, example = "1024") + private Long id; + + @ApiModelProperty(value = "菜单名称", required = true, example = "菜单管理") + private String name; + + @ApiModelProperty(value = "父菜单 ID", required = true, example = "1024") + private Long parentId; + + @ApiModelProperty(value = "类型", required = true, example = "1", notes = "参见 MenuTypeEnum 枚举类") + @NotNull(message = "菜单类型不能为空") + private Integer type; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/vo/SimplePackage.java --- +package com.starry.admin.modules.system.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author admin + * @since 2023/3/5 20:53 + */ +@ApiModel("管理后台 - 租户套餐精简信息") +@Data +public class SimplePackage { + + @ApiModelProperty(value = "套餐编号", required = true, example = "1024") + private String id; + + @ApiModelProperty(value = "套餐名称", required = true, example = "希留") + private String name; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/vo/StatusConverter.java --- +package com.starry.admin.modules.system.vo; + +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.metadata.CellData; +import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.property.ExcelContentProperty; + +/** + * @author huoqiang 状态字符串处理 + * @since 2022/10/25 + */ +public class StatusConverter implements Converter { + + @Override + public Class supportJavaTypeKey() { + return Integer.class; + } + + @Override + public CellDataTypeEnum supportExcelTypeKey() { + return CellDataTypeEnum.STRING; + } + + @Override + public Integer convertToJavaData(CellData cellData, ExcelContentProperty excelContentProperty, + GlobalConfiguration globalConfiguration) throws Exception { + return "失败".equals(cellData.getStringValue()) ? 1 : 0; + } + + @Override + public CellData convertToExcelData(Integer value, ExcelContentProperty excelContentProperty, + GlobalConfiguration globalConfiguration) throws Exception { + return new CellData(0 == value ? "成功" : "失败"); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/vo/SysDictDataVo.java --- +package com.starry.admin.modules.system.vo; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.starry.common.domain.BasePageEntity; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 字典数据表对象 sys_dict_data + * + * @author admin + */ +@Data +@EqualsAndHashCode(callSuper = true) + +public class SysDictDataVo extends BasePageEntity { + + private static final long serialVersionUID = 1L; + + /** + * 主键ID + */ + @ApiModelProperty("主键ID") + @TableId(value = "dict_data_id", type = IdType.AUTO) + private Long dictDataId; + + /** + * 字典类型 + */ + private String dictType; + + /** + * 字典名称 + */ + private String dictLabel; + + /** + * 字典值 + */ + private String dictValue; + + /** + * 显示顺序 + */ + private Long sort; + + /** + * 是否默认(Y是 N否) + */ + private String isDefault; + + /** + * 表格回显样式 + */ + private String listClass; + + /** + * 状态(0正常 1停用) + */ + private Integer status; + + /** + * 备注 + */ + private String remark; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/vo/SysDictVo.java --- +package com.starry.admin.modules.system.vo; + +import com.starry.common.domain.BasePageEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @author admin + * @since 2024/3/15 13:58 + **/ +@EqualsAndHashCode(callSuper = true) +@Data +public class SysDictVo extends BasePageEntity { + + /** + * 主键ID + */ + private Long dictId; + + /** + * 字典类型 + */ + private String dictType; + + /** + * 字典名称 + */ + private String dictName; + + /** + * 状态(0正常 1停用) + */ + private Integer status; + + /** + * 备注 + */ + private String remark; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/vo/SysOperationLogVo.java --- +package com.starry.admin.modules.system.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.starry.common.domain.BasePageEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.Date; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 操作日志表对象 sys_operation_log + * + * @author admin + */ +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel(value = "操作日志查询参数", description = "系统操作日志查询条件") +public class SysOperationLogVo extends BasePageEntity { + + private static final long serialVersionUID = 1L; + + /** + * 主键ID + */ + @ApiModelProperty(value = "日志ID", example = "1", notes = "主键ID") + @TableId(value = "oper_id", type = IdType.AUTO) + private Long operId; + + /** + * 模块标题 + */ + @ApiModelProperty(value = "模块标题", example = "用户管理", notes = "操作的系统模块") + @ExcelProperty(value = "系统模块") + private String title; + + /** + * 业务类型(0其它 1新增 2修改 3删除) + */ + @ApiModelProperty(value = "业务类型", example = "1", notes = "0:其它 1:新增 2:修改 3:删除") + private Integer businessType; + + /** + * 业务类型数组 + */ + @ApiModelProperty(value = "业务类型数组", notes = "多个业务类型的集合") + @TableField(exist = false) + private Integer[] businessTypes; + + /** + * 方法名称 + */ + @ApiModelProperty(value = "方法名称", example = "com.starry.admin.modules.system.controller.SysUserController.create", notes = "调用的方法名") + @ExcelProperty(value = "方法名称") + private String method; + + /** + * 请求方式 + */ + @ApiModelProperty(value = "请求方式", example = "POST", notes = "HTTP请求方式") + private String requestMethod; + + /** + * 操作类别(0其它 1后台用户 2手机端用户) + */ + @ApiModelProperty(value = "操作类别", example = "1", notes = "0:其它 1:后台用户 2:手机端用户") + private Integer operatorType; + + /** + * 操作人员 + */ + @ApiModelProperty(value = "操作人员", example = "admin", notes = "执行操作的用户账号") + private String operName; + + /** + * 请求URL + */ + @ApiModelProperty(value = "请求URL", example = "/system/user/create", notes = "请求的接口地址") + private String operUrl; + + /** + * 主机地址 + */ + @ApiModelProperty(value = "主机地址", example = "127.0.0.1", notes = "请求的IP地址") + private String operIp; + + /** + * 操作地点 + */ + @ApiModelProperty(value = "操作地点", example = "北京", notes = "根据IP解析的地理位置") + private String operLocation; + + /** + * 请求参数 + */ + @ApiModelProperty(value = "请求参数", notes = "请求的参数内容") + private String operParam; + + /** + * 返回参数 + */ + @ApiModelProperty(value = "返回参数", notes = "接口返回的结果") + private String jsonResult; + + /** + * 操作状态(0正常 1异常) + */ + @ApiModelProperty(value = "操作状态", example = "0", notes = "0:正常 1:异常") + private Integer status; + + /** + * 错误消息 + */ + @ApiModelProperty(value = "错误消息", example = "权限不足", notes = "操作失败时的错误信息") + private String errorMsg; + + /** + * 操作时间 + */ + @ApiModelProperty(value = "操作时间", example = "2023-01-01 00:00:00", notes = "操作的时间") + private Date operTime; + + /** + * 部门名称 + */ + @ApiModelProperty(value = "部门名称", example = "研发部", notes = "操作人员所属部门") + private String deptName; + + /** + * 部门id + */ + @ApiModelProperty(value = "部门ID", example = "1", notes = "操作人员所属部门ID") + private Long deptId; + + /** + * 租户ID + */ + @ApiModelProperty(value = "租户ID", example = "1", notes = "所属租户ID") + private Long tenantId; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/vo/SysRoleAddVo.java --- +package com.starry.admin.modules.system.vo; + +import com.starry.admin.modules.system.module.entity.SysRoleEntity; +import com.starry.common.domain.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.Set; +import javax.validation.constraints.NotBlank; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @author admin + */ +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel(value = "角色添加参数", description = "新增系统角色的请求参数") +public class SysRoleAddVo extends BaseEntity { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "角色ID", hidden = true, notes = "新增时无需填写,系统自动生成") + private Long roleId; + + @NotBlank(message = "角色名称不能为空") + @ApiModelProperty(value = "角色名称", required = true, example = "管理员", notes = "角色显示名称") + private String roleName; + + @ApiModelProperty(value = "角色描述", example = "系统管理员", notes = "角色的详细描述") + private String description; + + @ApiModelProperty(value = "角色状态", example = "0", notes = "0-正常,1-停用") + private Integer status; + + @ApiModelProperty(value = "数据权限范围", example = "1", notes = "1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限 5:仅本人数据权限") + private String dataScope; + + @ApiModelProperty(value = "菜单树选择项是否关联显示", example = "true") + private boolean menuCheckStrictly; + + @ApiModelProperty(value = "部门树选择项是否关联显示", example = "true") + private boolean deptCheckStrictly; + + @ApiModelProperty(value = "权限字符", required = true, example = "admin", notes = "角色权限字符串") + private String roleKey; + + @ApiModelProperty(value = "租户ID", example = "1", notes = "角色所属租户ID") + private Long tenantId; + + /** + * 菜单组 + */ + @ApiModelProperty(value = "菜单ID数组", notes = "角色关联的菜单ID列表") + private Long[] menuIds; + + /** + * 部门组(数据权限) + */ + @ApiModelProperty(value = "部门ID数组", notes = "角色关联的部门ID列表,用于数据权限") + private Long[] deptIds; + + /** + * 角色菜单权限 + */ + @ApiModelProperty(value = "角色权限集合", notes = "角色拥有的菜单权限列表") + private Set permissions; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/vo/SysTenantAddVo.java --- +package com.starry.admin.modules.system.vo; + +import com.starry.common.domain.BaseEntity; +import java.util.Date; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 租户表对象 sys_tenant + * + * @author admin + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class SysTenantAddVo extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * 租户类型;0:公司;1:部门;2:个人;3:其他 + */ + @NotBlank(message = "租户类型不能为空") + private String tenantType = "0"; + + /** + * 用户状态;0:正常,1:停用 + */ + @NotBlank(message = "租户状态不能为空") + private String tenantStatus; + + /** + * 名称 + */ + @NotBlank(message = "租户名称不能为空") + private String tenantName; + + /** + * logo图 + */ + private String tenantLogo; + + /** + * 显示顺序 + */ + private String sortOrder; + + /** + * 官方地址 + */ + private String homeUrl; + + /** + * 电话 + */ + @NotBlank(message = "手机号码不能为空") + private String phone; + + /** + * 传真 + */ + private String fax; + + /** + * 邮箱 + */ + private String email; + + /** + * 地址 + */ + private String address; + + /** + * 管理员账号 + */ + @NotBlank(message = "管理员账号不能为空") + private String userName; + + /** + * 管理员密码 + */ + @NotBlank(message = "管理员账号密码不能为空") + private String userPwd; + + /** + * 租户套餐 + */ + private String packageId; + + /** + * 租赁到期时间 + */ + @NotNull(message = "租赁到期时间不能为空") + private Date tenantTime; + + /** + * 微信公众号ID + */ + @NotBlank(message = "微信公众号ID不能为空") + private String appId; + + /** + * 微信公众号的app secret + */ + @NotBlank(message = "微信公众号secret不能为空") + private String secret; + + /** + * 设置微信公众号的token + */ + @NotBlank(message = "微信商户Key不能为空") + private String mchKey; + + /** + * 设置微信公众号的EncodingAESKey + */ + @NotBlank(message = "微信商户秘钥不能为空") + private String mchId; + + /** + * 证书路径 + */ + private String certificatePath; + + /** + * 备注 + */ + private String remarks; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/vo/SysTenantPackageAddVo.java --- +package com.starry.admin.modules.system.vo; + +import com.starry.common.domain.BaseEntity; +import javax.validation.constraints.NotBlank; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 租户套餐表对象 sys_tenant_package + * + * @author admin + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class SysTenantPackageAddVo extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @NotBlank(message = "套餐名称不能为空") + private String packageName; + + /** + * 关联菜单id + */ + private String menuIds; + + /** + * 状态;0:正常,1:停用 + */ + @NotBlank(message = "套餐状态不能为空") + private String status; + + /** + * 备注 + */ + private String remarks; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/vo/SysTenantPackageVo.java --- +package com.starry.admin.modules.system.vo; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.starry.common.domain.BasePageEntity; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 租户套餐表对象 sys_tenant_package + * + * @author admin + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class SysTenantPackageVo extends BasePageEntity { + + private static final long serialVersionUID = 1L; + + /** + * 套餐id + */ + @ApiModelProperty("主键ID") + @TableId(value = "package_id", type = IdType.AUTO) + private Long packageId; + + /** + * 名称 + */ + private String packageName; + + /** + * 关联菜单id + */ + private String menuIds; + + /** + * 状态;0:正常,1:停用 + */ + private String status; + + /** + * 备注 + */ + private String remarks; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/vo/SysTenantQueryVo.java --- +package com.starry.admin.modules.system.vo; + +import com.starry.common.domain.BasePageEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 租户表对象 sys_tenant + * + * @author admin + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class SysTenantQueryVo extends BasePageEntity { + + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + private String tenantName; + + /** + * 用户状态;0:正常,1:停用 + */ + private String tenantStatus; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/vo/SysTenantReturnVo.java --- +package com.starry.admin.modules.system.vo; + +import java.math.BigDecimal; +import java.util.Date; +import lombok.Data; + +/** + * 租户表对象 sys_tenant + * + * @author admin + */ +@Data +public class SysTenantReturnVo { + + private String tenantId; + + /** + * 租户类型;0:公司;1:部门;2:个人;3:其他 + */ + private String tenantType; + + /** + * 用户状态;0:正常,1:停用 + */ + private String tenantStatus; + + /** + * 编码 + */ + private String tenantCode; + + /** + * 名称 + */ + private String tenantName; + + /** + * logo图 + */ + private String tenantLogo; + + /** + * 显示顺序 + */ + private Long sortOrder; + + /** + * 官方地址 + */ + private String homeUrl; + + /** + * 电话 + */ + private String phone; + + /** + * 传真 + */ + private String fax; + + /** + * 邮箱 + */ + private String email; + + /** + * 地址 + */ + private String address; + + /** + * 管理员账号 + */ + private String userName; + + /** + * 管理员密码 + */ + private String userPwd; + + /** + * 租户套餐 + */ + private String packageId; + + /** + * 租赁到期时间 + */ + private Date tenantTime; + + private Date createdTime; + + /** + * 租户权限标识 + */ + private String tenantKey; + + /** + * 微信公众号ID + */ + private String appId; + + /** + * 微信公众号的app secret + */ + private String secret; + + /** + * 微信商户ID + */ + private String mchId; + + /** + * 设置微信公众号的token + */ + private String mchKey; + + /** + * 商户秘钥 + */ + private String certificatePath; + + /** + * 备注 + */ + private String remarks; + + /** + * 店员数 + */ + private Long clerkNumber; + + /** + * 订单总数 + */ + private Long orderNumber; + + /** + * 总充值金额 + */ + private BigDecimal rechargeAmount; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/vo/SysUserEntityListVo.java --- +package com.starry.admin.modules.system.vo; + +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity; +import com.starry.admin.modules.system.module.entity.SysUserEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @Author: huchuansai + * @Date: 2024/6/14 2:49 PM + * @Description: + */ +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel(value = "用户列表展示对象", description = "系统用户列表格式化展示的对象") +public class SysUserEntityListVo extends SysUserEntity { + + @ApiModelProperty(value = "角色列表", notes = "用户拥有的角色信息列表") + private List roleVoList; + + @ApiModelProperty(value = "店员信息", notes = "关联的店员详细信息") + private PlayClerkUserInfoEntity clerkUserInfo; + + @Data + @AllArgsConstructor + @ApiModel(value = "角色信息对象", description = "用户所属角色的简要信息") + public static class RoleVo { + + @ApiModelProperty(value = "角色名称", example = "管理员") + private String roleName; + + @ApiModelProperty(value = "角色对应的用户名", example = "admin") + private String roleUserName; + + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/vo/SysUserQueryVo.java --- +package com.starry.admin.modules.system.vo; + +import com.starry.admin.modules.system.module.entity.SysDeptEntity; +import com.starry.admin.modules.system.module.entity.SysRoleEntity; +import com.starry.common.domain.BasePageEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.Date; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 用户查询对象 + * + * @author admin + */ +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel(value = "系统用户查询参数", description = "查询系统用户的条件参数") +public class SysUserQueryVo extends BasePageEntity { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "用户ID", example = "1") + private Long userId; + + @ApiModelProperty(value = "用户类型", example = "1", notes = "1:admin;2:会员") + private Integer userType; + + @ApiModelProperty(value = "用户名", example = "admin", notes = "登录账号,支持模糊查询") + private String userCode; + + @ApiModelProperty(value = "密码", hidden = true) + private String passWord; + + @ApiModelProperty(value = "姓名", example = "张三", notes = "用户真实姓名,支持模糊查询") + private String realName; + + @ApiModelProperty(value = "用户昵称", example = "小张", notes = "用户昵称,支持模糊查询") + private String userNickname; + + @ApiModelProperty(value = "邮箱", example = "test@example.com") + private String userEmail; + + @ApiModelProperty(value = "头像", example = "https://example.com/avatar.jpg") + private String avatar; + + @ApiModelProperty(value = "手机号码", example = "13800138000") + private String mobile; + + @ApiModelProperty(value = "性别", example = "1", notes = "1:男;2:女;0:未知") + private Integer sex; + + @ApiModelProperty(value = "出生日期", example = "1990-01-01") + private Date birthday; + + @ApiModelProperty(value = "状态", example = "0", notes = "0:正常;1:停用") + private Integer status; + + @ApiModelProperty(value = "最后登录时间") + private Date lastLoginTime; + + @ApiModelProperty(value = "最后登录IP", example = "192.168.1.1") + private String lastLoginIp; + + @ApiModelProperty(value = "部门ID", example = "1") + private Long deptId; + + @ApiModelProperty(value = "租户ID", example = "1") + private Long tenantId; + + @ApiModelProperty(value = "角色列表", notes = "用户关联的角色信息") + private List roles; + + @ApiModelProperty(value = "角色ID数组", notes = "用户关联的角色ID列表") + private Long[] roleIds; + + @ApiModelProperty(value = "部门信息", notes = "用户所属部门详情") + private SysDeptEntity dept; + + @ApiModelProperty(value = "角色ID", example = "1", notes = "用于查询已分配或未分配指定角色的用户") + private Long roleId; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/vo/TenantLoginVo.java --- +package com.starry.admin.modules.system.vo; + +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotNull; +import lombok.Data; + +/** + * @author huoqiang + * @since 2021/9/6 + */ +@Data +public class TenantLoginVo implements Serializable { + + /** + * 租户ID + */ + @NotNull(message = "租户标识不能为空") + private String tenantkey; + + @ApiModelProperty(value = "用户名") + private String userName; + + @ApiModelProperty(value = "密码") + private String passWord; + + @ApiModelProperty(value = "验证码随机字符串") + private String nonceStr; + + @ApiModelProperty(value = "验证值") + private String value; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/vo/TenantResultVo.java --- +package com.starry.admin.modules.system.vo; + +import io.swagger.annotations.ApiModel; +import java.util.Date; +import lombok.Data; + +/** + * @author 租户列表返回结果VO + * @since 2023/3/7 + */ +@ApiModel("管理后台 - 租户列表返回信息") +@Data +public class TenantResultVo { + + private String tenantId; + + /** + * 租户类型;0:公司;1:部门;2:个人;3:其他 + */ + private String tenantType; + + /** + * 用户状态;0:正常,1:停用 + */ + private String tenantStatus; + + /** + * 名称 + */ + private String tenantName; + + /** + * logo图 + */ + private String tenantLogo; + + /** + * 管理员账号 + */ + private String userName; + + /** + * 租户套餐Id + */ + private String packageId; + + /** + * 租赁到期时间 + */ + private Date tenantTime; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/vo/UpdateUserMobileParam.java --- +package com.starry.admin.modules.system.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Pattern; +import lombok.Data; + +/** + * @Author: huchuansai + * @Date: 2024/6/14 3:05 PM + * @Description: + */ +@Data +@ApiModel(value = "修改手机号参数", description = "用户修改手机号的请求参数") +public class UpdateUserMobileParam { + + @ApiModelProperty(value = "用户ID", notes = "要修改手机号的用户ID,不传则修改当前登录用户") + private String userId; + + @NotBlank(message = "手机号不能为空") + @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确") + @ApiModelProperty(value = "新手机号", required = true, example = "13800138000", notes = "用户的新手机号") + private String mobile; + + @NotBlank(message = "验证码不能为空") + @ApiModelProperty(value = "短信验证码", required = true, example = "123456", notes = "发送到新手机号的验证码") + private String smsCode; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/vo/UpdateUserPasswordParam.java --- +package com.starry.admin.modules.system.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +/** + * @Author: huchuansai + * @Date: 2024/6/14 3:05 PM + * @Description: + */ +@Data +@ApiModel(value = "修改密码参数", description = "用户修改密码的请求参数") +public class UpdateUserPasswordParam { + + @ApiModelProperty(value = "用户ID", notes = "要修改密码的用户ID,不传则修改当前登录用户") + private String userId; + + @NotBlank(message = "密码不能为空") + @ApiModelProperty(value = "新密码", required = true, notes = "用户的新密码") + private String password; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/vo/UpdateUserPasswordParamV2.java --- +package com.starry.admin.modules.system.vo; + +import io.swagger.annotations.ApiModel; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +/** + * @Author: huchuansai + * @Date: 2024/6/14 3:05 PM + * @Description: + */ +@Data +@ApiModel(value = "修改密码参数", description = "用户修改密码的请求参数") +public class UpdateUserPasswordParamV2 { + + @NotBlank(message = "新密码不能为空") + private String newPassword; + + @NotBlank(message = "旧密码不能为空") + private String oldPassword; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/vo/UserAddParam.java --- +package com.starry.admin.modules.system.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Pattern; +import lombok.Data; + +/** + * @Author: huchuansai + * @Date: 2024/6/14 11:27 AM + * @Description: + */ +@Data +@ApiModel(value = "用户添加参数", description = "新增系统用户的请求参数") +public class UserAddParam { + + @NotEmpty(message = "请指定店员") + @ApiModelProperty(value = "店员ID", required = true, notes = "关联的店员ID") + private String clerkId; + + @NotEmpty(message = "请指定手机号") + @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确") + @ApiModelProperty(value = "手机号", required = true, example = "13800138000", notes = "用户手机号,作为登录账号") + private String mobile; + + @NotEmpty(message = "请指定短信验证码") + @ApiModelProperty(value = "短信验证码", required = true, example = "123456", notes = "发送到手机的验证码") + private String smsCode; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/system/vo/UserQueryVo.java --- +package com.starry.admin.modules.system.vo; + +import com.starry.common.domain.BasePageEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @author admin + * @since 2021/9/26 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel(value = "用户查询参数", description = "系统用户分页查询的条件参数") +public class UserQueryVo extends BasePageEntity { + + @ApiModelProperty(value = "用户ID", example = "1", notes = "用户唯一标识") + private String userId; + + @ApiModelProperty(value = "用户名", example = "admin", notes = "登录账号,支持模糊查询") + private String userCode; + + @ApiModelProperty(value = "姓名", example = "张三", notes = "用户真实姓名,支持模糊查询") + private String realName; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/constant/ConfigConstant.java --- +package com.starry.admin.modules.weichat.constant; + +/** + * 全局常量 + * + * @author admin 2019年1月21日 + */ +public interface ConfigConstant { + + // 订阅状态(0:已订阅;1:未订阅;2:网页授权用户) + /** + * 0:未订阅,取消订阅 + */ + String SUBSCRIBE_TYPE_NO = "0"; + /** + * 1:已订阅 + */ + String SUBSCRIBE_TYPE_YES = "1"; + /** + * 2:网页授权用户 + */ + String SUBSCRIBE_TYPE_WEBLIEN = "2"; + + /** + * 应用类型 1:微信 + */ + String WX_APP_TYPE_1 = "1"; + /** + * 应用类型 2:公众号 + */ + String WX_APP_TYPE_2 = "2"; + + /** + * 消息自动回复类型(1、关注时回复;2、消息回复;3、关键词回复) + */ + String WX_AUTO_REPLY_TYPE_1 = "1"; + String WX_AUTO_REPLY_TYPE_2 = "2"; + String WX_AUTO_REPLY_TYPE_3 = "3"; + + /** + * 回复类型文本匹配类型(1、全匹配,2、半匹配) + */ + String WX_REP_MATE_1 = "1"; + String WX_REP_MATE_2 = "2"; + + /** + * 消息分类(1、用户发给公众号;2、公众号发给用户;) + */ + String WX_MSG_TYPE_1 = "1"; + String WX_MSG_TYPE_2 = "2"; + + /** + * 群发消息发送类型(1、分组发;2、选择用户发) + */ + String WX_MASS_SEND_TYPE_1 = "1"; + String WX_MASS_SEND_TYPE_2 = "2"; + + /** + * 群发消息发送后的状态(SUB_SUCCESS:提交成功,SUB_FAIL:提交失败,SEND_SUCCESS:发送成功,SENDING:发送中,SEND_FAIL:发送失败,DELETE:已删除) + */ + String WX_MASS_STATUS_SUB_SUCCESS = "SUB_SUCCESS"; + String WX_MASS_STATUS_SUB_FAIL = "SUB_FAIL"; + String WX_MASS_STATUS_SEND_SUCCESS = "SEND_SUCCESS"; + String WX_MASS_STATUS_SENDING = "SENDING"; + String WX_MASS_STATUS_SEND_FAIL = "SEND_FAIL"; + String WX_MASS_STATUS_DELETE = "DELETE"; + + /** + * 菜单类型(1:普通菜单,2:个性化菜单) + */ + String WX_MENU_TYPE_1 = "1"; + String WX_MENU_TYPE_2 = "2"; + + /** + * header中的app-id + */ + String HEADER_APP_ID = "app-id"; + + /** + * header中的third-session + */ + String HEADER_THIRDSESSION = "third-session"; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/constant/MyReturnCode.java --- +package com.starry.admin.modules.weichat.constant; + +/** + * 全局返回码 微信用6开头,例60001 + * + * @author admin 2019年7月25日 + */ +public enum MyReturnCode { + + // 其它错误 + ERR_60000(60000, "系统错误,请稍候再试") { + }, + ERR_60001(60001, "登录超时,请重新登录") { + }, + ERR_60002(60002, "session不能为空") { + }, + + ERR_70001(70001, "该状态订单不允许操作") { + }, + ERR_70002(70002, "请选择付款方式") { + }, + ERR_70003(70003, "没有符合下单条件的规格商品,商品已下架或库存不足") { + }, + ERR_70004(70004, "只有未支付的详单能发起支付") { + }, + ERR_70005(70005, "无效订单") { + }, + + ERR_80004(80004, "该商品已删除") { + }, + + ; + + private int code; + private String msg; + + MyReturnCode(int code, String msg) { + this.code = code; + this.msg = msg; + } + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + @Override + public String toString() { + return "MyReturnCode{" + "code='" + code + '\'' + "msg='" + msg + '\'' + '}'; + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/constant/WebSocketConstant.java --- +package com.starry.admin.modules.weichat.constant; + +/** + * @author admin + */ +public interface WebSocketConstant { + + String USER_DESTINATION_PREFIX = "/weixin/"; + String WX_MSG = "wx_msg"; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/constant/WxMaConstants.java --- +package com.starry.admin.modules.weichat.constant; + +/** + * @author admin + */ +public interface WxMaConstants { + + /** + * redis中3rd_session过期时间(单位:小时) + */ + long TIME_OUT_SESSION = 6; + /** + * redis中3rd_session拼接前缀 + */ + String THIRD_SESSION_BEGIN = "wx:ma:3rd_session"; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/constant/WxReturnCode.java --- +package com.starry.admin.modules.weichat.constant; + +/** + * 微信接口全局返回码 + * + * @author admin + */ + +@SuppressWarnings("") +public enum WxReturnCode { + + SUC_0("0", "请求成功") { + }, + ERR_1("-1", "系统繁忙,此时请开发者稍候再试") { + }, + ERR_10001("10001", "涉嫌广告 ") { + }, + ERR_20001("20001", "涉嫌政治 ") { + }, + ERR_20002("20002", "涉嫌色情 ") { + }, + ERR_20004("20004", "涉嫌社会 ") { + }, + ERR_20006("20006", "涉嫌违法犯罪 ") { + }, + ERR_20008("20008", "涉嫌欺诈 ") { + }, + ERR_20013("20013", "涉嫌版权 ") { + }, + ERR_21000("21000", "涉嫌其他 ") { + }, + ERR_22000("22000", "涉嫌互推(互相宣传) ") { + }, + ERR_30001("30001", "原创校验出现系统错误且用户选择了被判为转载就不群发 ") { + }, + ERR_30002("30002", "原创校验被判定为不能群发 ") { + }, + ERR_30003("30003", "原创校验被判定为转载文且用户选择了被判为转载就不群发 ") { + }, + ERR_40001("40001", "获取access_token时AppSecret错误,或者access_token无效。请开发者认真比对AppSecret的正确性,或查看是否正在为恰当的公众号调用接口") { + }, + ERR_40002("40002", "不合法的凭证类型") { + }, + ERR_40003("40003", "不合法的OpenID,请开发者确认OpenID(该用户)是否已关注公众号,或是否是其他公众号的OpenID") { + }, + ERR_40004("40004", "不合法的媒体文件类型") { + }, + ERR_40005("40005", "不合法的文件类型") { + }, + ERR_40006("40006", "不合法的文件大小") { + }, + ERR_40007("40007", "不合法的媒体文件id") { + }, + ERR_40008("40008", "不合法的消息类型") { + }, + ERR_40009("40009", "不合法的图片文件大小") { + }, + ERR_40010("40010", "不合法的语音文件大小") { + }, + ERR_40011("40011", "不合法的视频文件大小") { + }, + ERR_40012("40012", "不合法的缩略图文件大小") { + }, + ERR_40013("40013", "不合法的AppID,请开发者检查AppID的正确性,避免异常字符,注意大小写") { + }, + ERR_40014("40014", "不合法的access_token,请开发者认真比对access_token的有效性(如是否过期),或查看是否正在为恰当的公众号调用接口") { + }, + ERR_40015("40015", "不合法的菜单类型") { + }, + ERR_40016("40016", "不合法的按钮个数") { + }, + ERR_40017("40017", "不合法的按钮个数") { + }, + ERR_40018("40018", "不合法的按钮名字长度") { + }, + ERR_40019("40019", "不合法的按钮KEY长度") { + }, + ERR_40020("40020", "不合法的按钮URL长度") { + }, + ERR_40021("40021", "不合法的菜单版本号") { + }, + ERR_40022("40022", "不合法的子菜单级数") { + }, + ERR_40023("40023", "不合法的子菜单按钮个数") { + }, + ERR_40024("40024", "不合法的子菜单按钮类型") { + }, + ERR_40025("40025", "不合法的子菜单按钮名字长度") { + }, + ERR_40026("40026", "不合法的子菜单按钮KEY长度") { + }, + ERR_40027("40027", "不合法的子菜单按钮URL长度") { + }, + ERR_40028("40028", "不合法的自定义菜单使用用户") { + }, + ERR_40029("40029", "不合法的oauth_code") { + }, + ERR_40030("40030", "不合法的refresh_token") { + }, + ERR_40031("40031", "不合法的openid列表") { + }, + ERR_40032("40032", "不合法的openid列表个数") { + }, + ERR_40033("40033", "不合法的请求字符,不能包含xxxx格式的字符") { + }, + ERR_40035("40035", "不合法的参数") { + }, + ERR_40055("40055", "不完整的url,前面要加http://") { + }, + ERR_40037("40037", "template_id不正确") { + }, + ERR_40038("40038", "不合法的请求格式") { + }, + ERR_40039("40039", "不合法的URL长度") { + }, + ERR_40050("40050", "不合法的分组id") { + }, + ERR_40051("40051", "分组名字不合法") { + }, + ERR_40062("40062", "标题长度不合法") { + }, + ERR_40097("40097", "参数不合法") { + }, + ERR_40113("40113", "文件名称不合法,需包含正确后缀") { + }, + ERR_40117("40117", "分组名字不合法") { + }, + ERR_40118("40118", "media_id大小不合法") { + }, + ERR_40119("40119", "button类型错误") { + }, + ERR_40120("40120", "button类型错误") { + }, + ERR_40121("40121", "不合法的media_id类型") { + }, + ERR_40125("40125", "不合法的AppSecret,请开发者检查AppSecret的正确性,避免异常字符,注意大小写") { + }, + ERR_40130("40130", "至少需要同时发送两个用户") { + }, + ERR_40132("40132", "微信号不合法") { + }, + ERR_40137("40137", "不支持的图片格式") { + }, + ERR_40164("40164", "调用接口的IP地址不在白名单中,请在接口IP白名单中进行设置") { + }, + ERR_41001("41001", "缺少access_token参数") { + }, + ERR_41002("41002", "缺少appid参数") { + }, + ERR_41003("41003", "缺少refresh_token参数") { + }, + ERR_41004("41004", "缺少secret参数") { + }, + ERR_41005("41005", "缺少多媒体文件数据") { + }, + ERR_41006("41006", "缺少media_id参数") { + }, + ERR_41007("41007", "缺少子菜单数据") { + }, + ERR_41008("41008", "缺少oauth code") { + }, + ERR_41009("41009", "缺少openid") { + }, + ERR_41028("41028", "form_id不正确,或者过期") { + }, + ERR_41029("41029", "form_id已被使用") { + }, + ERR_41030("41030", "page不正确") { + }, + ERR_42001("42001", "access_token超时,请检查access_token的有效期,请参考基础支持-获取access_token中,对access_token的详细机制说明") { + }, + ERR_42002("42002", "refresh_token超时") { + }, + ERR_42003("42003", "oauth_code超时") { + }, + ERR_43001("43001", "需要GET请求") { + }, + ERR_43002("43002", "需要POST请求") { + }, + ERR_43003("43003", "需要HTTPS请求") { + }, + ERR_43004("43004", "需要接收者关注") { + }, + ERR_43005("43005", "需要好友关系") { + }, + ERR_44001("44001", "多媒体文件为空") { + }, + ERR_44002("44002", "POST的数据包为空") { + }, + ERR_44003("44003", "图文消息内容为空") { + }, + ERR_44004("44004", "文本消息内容为空") { + }, + ERR_45001("45001", "多媒体文件大小超过限制") { + }, + ERR_45002("45002", "消息内容超过限制") { + }, + ERR_45003("45003", "标题字段超过限制") { + }, + ERR_45004("45004", "描述字段超过限制") { + }, + ERR_45005("45005", "链接字段超过限制") { + }, + ERR_45006("45006", "图片链接字段超过限制") { + }, + ERR_45007("45007", "语音播放时间超过限制") { + }, + ERR_45008("45008", "图文消息超过限制") { + }, + ERR_45009("45009", "接口调用超过限制") { + }, + ERR_45010("45010", "创建菜单个数超过限制") { + }, + ERR_45015("45015", "回复时间超过限制") { + }, + ERR_45016("45016", "系统分组,不允许修改") { + }, + ERR_45017("45017", "分组名字过长") { + }, + ERR_45018("45018", "分组数量超过上限") { + }, + ERR_45028("45028", "没有群发的配额,配额已经用完") { + }, + ERR_45047("45047", "客服下行消息超过上限") { + }, + ERR_45157("45157", "标签名非法,请注意不能和其他标签重名") { + }, + ERR_45158("45158", "标签名长度超过30个字节") { + }, + ERR_45056("45056", "创建的标签数过多,请注意不能超过100个") { + }, + ERR_45058("45058", "不能修改0/1/2这三个系统默认保留的标签") { + }, + ERR_45057("45057", "该标签下粉丝数超过10w,不允许直接删除") { + }, + ERR_45059("45059", "有粉丝身上的标签数已经超过限制") { + }, + ERR_45159("45159", "非法的tag_id") { + }, + ERR_46001("46001", "不存在媒体数据") { + }, + ERR_46002("46002", "不存在的菜单版本") { + }, + ERR_46003("46003", "不存在的菜单数据") { + }, + ERR_46004("46004", "不存在的用户") { + }, + ERR_47001("47001", "解析JSON/XML内容错误") { + }, + ERR_48001("48001", "api功能未授权,请确认公众号已获得该接口,可以在公众平台官网-开发者中心页中查看接口权限") { + }, + ERR_48002("48002", "粉丝拒收消息(粉丝在公众号选项中,关闭了 “ 接收消息 ” )") { + }, + ERR_48004("48004", "api 接口被封禁,请登录 admin.weixin.qq.com 查看详情") { + }, + ERR_48005("48005", "api 禁止删除被自动回复和自定义菜单引用的素材") { + }, + ERR_48006("48006", "api 禁止清零调用次数,因为清零次数达到上限") { + }, + ERR_48008("48008", "没有该类型消息的发送权限") { + }, + ERR_49003("49003", "传入的openid不属于此AppID") { + }, + ERR_50001("50001", "用户未授权该api") { + }, + ERR_50002("50002", "用户受限,可能是违规后接口被封禁") { + }, + ERR_50005("50005", "用户未关注公众号") { + }, + ERR_61003("61003", "请确认是否取消授权(第三方平台授权)") { + }, + ERR_61004("61004", "当前ip未在白名单中,直接获取本地ip添加") { + }, + ERR_61005("61005", " 组件 ticket已失效,重新接受授权url反馈的ticket") { + }, + ERR_61006("61006", "获取componentTicket为null") { + }, + ERR_61007("61007", "当前公众号或者微信已在公众平台解绑") { + }, + ERR_61009("61009", "授权码失效,重新授权") { + }, + ERR_61451("61451", "参数错误(invalid parameter)") { + }, + ERR_61452("61452", "无效客服账号(invalid kf_account)") { + }, + ERR_61453("61453", "客服帐号已存在(kf_account exsited)") { + }, + ERR_61454("61454", "客服帐号名长度超过限制(仅允许10个英文字符,不包括@及@后的公众号的微信号)(invalid kf_acount length)") { + }, + ERR_61455("61455", "客服帐号名包含非法字符(仅允许英文+数字)(illegal character in kf_account)") { + }, + ERR_61456("61456", "客服帐号个数超过限制(10个客服账号)(kf_account count exceeded)") { + }, + ERR_61457("61457", "无效头像文件类型(invalid file type)") { + }, + ERR_61450("61450", "系统错误(system error)") { + }, + ERR_61500("61500", "日期格式错误") { + }, + ERR_61501("61501", "日期范围错误") { + }, + ERR_65400("65400", "API不可用,即没有开通/升级到新版客服功能") { + }, + ERR_65401("65401", "无效客服帐号") { + }, + ERR_65403("65403", "客服昵称不合法") { + }, + ERR_65404("65404", "客服帐号不合法") { + }, + ERR_65405("65405", "帐号数目已达到上限,不能继续添加") { + }, + ERR_65406("65406", "已经存在的客服帐号") { + }, + ERR_65407("65407", "邀请对象已经是该公众号客服") { + }, + ERR_65408("65408", "本公众号已经有一个邀请给该微信") { + }, + ERR_65409("65409", "无效的微信号") { + }, + ERR_65410("65410", "邀请对象绑定公众号客服数达到上限(目前每个微信号可以绑定5个公众号客服帐号)") { + }, + ERR_65411("65411", "该帐号已经有一个等待确认的邀请,不能重复邀请") { + }, + ERR_65412("65412", "该帐号已经绑定微信号,不能进行邀请") { + }, + ERR_99999("99999", "无法获取到文件名") { + }, + ERR_9001001("9001001", "POST数据参数不合法") { + }, + ERR_9001002("9001002", "远端服务不可用") { + }, + ERR_9001003("9001003", "Ticket不合法") { + }, + ERR_9001004("9001004", "获取摇周边用户信息失败") { + }, + ERR_9001005("9001005", "获取商户信息失败") { + }, + ERR_9001006("9001006", "获取OpenID失败") { + }, + ERR_9001007("9001007", "上传文件缺失") { + }, + ERR_9001008("9001008", "上传素材的文件类型不合法") { + }, + ERR_9001009("9001009", "上传素材的文件尺寸不合法") { + }, + ERR_9001010("9001010", "上传失败") { + }, + ERR_9001020("9001020", "帐号不合法") { + }, + ERR_9001021("9001021", "已有设备激活率低于50%,不能新增设备") { + }, + ERR_9001022("9001022", "设备申请数不合法,必须为大于0的数字") { + }, + ERR_9001023("9001023", "已存在审核中的设备ID申请") { + }, + ERR_9001024("9001024", "一次查询设备ID数量不能超过50") { + }, + ERR_9001025("9001025", "设备ID不合法") { + }, + ERR_9001026("9001026", "页面ID不合法") { + }, + ERR_9001027("9001027", "页面参数不合法") { + }, + ERR_9001028("9001028", "一次删除页面ID数量不能超过10") { + }, + ERR_9001029("9001029", "页面已应用在设备中,请先解除应用关系再删除") { + }, + ERR_9001030("9001030", "一次查询页面ID数量不能超过50") { + }, + ERR_9001031("9001031", "时间区间不合法") { + }, + ERR_9001032("9001032", "保存设备与页面的绑定关系参数错误") { + }, + ERR_9001033("9001033", "门店ID不合法") { + }, + ERR_9001034("9001034", "设备备注信息过长") { + }, + ERR_9001035("9001035", "设备申请参数不合法") { + }, + ERR_9001036("9001036", "查询起始值begin不合法") { + }; + + private String code; + private String msg; + + WxReturnCode(String code, String msg) { + this.code = code; + this.msg = msg; + } + + /** + * 通过code获取msg + * + * @param code + * @return + */ + public static String getMsg(String code) { + try { + return WxReturnCode.valueOf(code).getMsg(); + } catch (IllegalArgumentException e) { + return "未定义的返回码:" + code; + } + } + + 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; + } + + @Override + public String toString() { + return "WxReturnCode{" + "code='" + code + '\'' + "msg='" + msg + '\'' + '}'; + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/controller/WxArticleController.java --- +package com.starry.admin.modules.weichat.controller; + +import com.starry.admin.common.aspect.ClerkUserLogin; +import com.starry.admin.common.aspect.CustomUserLogin; +import com.starry.admin.common.conf.ThreadLocalRequestDetail; +import com.starry.admin.modules.clerk.module.entity.PlayClerkArticleInfoEntity; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity; +import com.starry.admin.modules.clerk.module.entity.PlayCustomArticleInfoEntity; +import com.starry.admin.modules.clerk.module.vo.PlayClerkArticleQueryVo; +import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService; +import com.starry.admin.modules.clerk.service.impl.PlayClerkArticleInfoServiceImpl; +import com.starry.admin.modules.clerk.service.impl.PlayCustomArticleInfoServiceImpl; +import com.starry.admin.modules.weichat.entity.article.PlayClerkAddArticleVo; +import com.starry.admin.modules.weichat.entity.article.PlayClerkArticleCustomQueryVo; +import com.starry.admin.modules.weichat.entity.article.PlayClerkArticleFollowCustomFollowStateEditStateVo; +import com.starry.admin.modules.weichat.entity.article.PlayClerkArticleFollowCustomGreedStateEditStateVo; +import com.starry.admin.modules.weichat.service.WxCustomUserService; +import com.starry.common.result.R; +import com.starry.common.utils.ConvertUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.time.LocalDateTime; +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 动态接口 + * + * @author admin + * @since 2024/5/20 下午11:19 + **/ +@Api(tags = "微信文章动态接口", description = "微信端文章动态相关接口") +@Slf4j +@RestController +@RequestMapping("/wx/article") +public class WxArticleController { + + @Resource + private PlayClerkArticleInfoServiceImpl playClerkArticleInfoService; + + @Resource + private PlayCustomArticleInfoServiceImpl playCustomArticleInfoService; + + @Resource + private IPlayClerkUserInfoService playClerkUserInfoService; + + @Resource + private WxCustomUserService customUserService; + + /** + * 店员新增动态 + */ + @ApiOperation(value = "店员新增动态", notes = "店员发布新的动态文章") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @ClerkUserLogin + @PostMapping("/clerk/add") + public R clerkAdd(@ApiParam(value = "动态信息", required = true) @Validated @RequestBody PlayClerkAddArticleVo vo) { + vo.setClerkId(ThreadLocalRequestDetail.getClerkUserInfo().getId()); + playClerkArticleInfoService.create(ConvertUtil.entityToVo(vo, PlayClerkArticleInfoEntity.class)); + return R.ok("成功"); + } + + /** + * 店员删除 + */ + @ApiOperation(value = "店员删除动态", notes = "店员删除自己发布的动态") + @ApiImplicitParam(name = "id", value = "动态ID", required = true, dataType = "String", paramType = "query") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @ClerkUserLogin + @GetMapping("/clerk/deleteById") + public R clerkDeleteById(@RequestParam("id") String id) { + playClerkArticleInfoService.deletePlayClerkArticleInfoById(id); + playCustomArticleInfoService.deleteByArticleId(id); + return R.ok("成功"); + } + + /** + * 店员分页查询本人动态列表 + */ + @ApiOperation(value = "店员查询动态", notes = "店员分页查询自己的动态列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayClerkArticleInfoEntity.class, responseContainer = "Page")}) + @ClerkUserLogin + @PostMapping("/clerk/listByPage") + public R clerkListByPage( + @ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayClerkArticleQueryVo vo) { + vo.setClerkId(ThreadLocalRequestDetail.getClerkUserInfo().getId()); + return R.ok(playClerkArticleInfoService.selectByPage(vo, true)); + } + + /** + * 顾客查询动态列表 + */ + @ApiOperation(value = "顾客查询动态列表", notes = "顾客分页查询所有动态列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayClerkArticleInfoEntity.class, responseContainer = "Page")}) + @PostMapping("/custom/listByPage") + public R customListByPage( + @ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayClerkArticleCustomQueryVo vo) { + vo.setFollowState("0"); + return R.ok(playClerkArticleInfoService.customSelectByPage(vo, customUserService.getLoginUserId())); + } + + /** + * 顾客查询已收藏动态列表 + */ + @ApiOperation(value = "查询收藏动态", notes = "顾客查询已收藏的动态列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayClerkArticleInfoEntity.class, responseContainer = "Page")}) + @CustomUserLogin + @PostMapping("/custom/listFollowByPage") + public R customListFollowByPage( + @ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayClerkArticleCustomQueryVo vo) { + vo.setFollowState("1"); + return R.ok(playClerkArticleInfoService.customSelectByPage(vo, customUserService.getLoginUserId())); + } + + /** + * 分页获取店员动态 + * + * @param id + * 店员ID + * @return 店员动态 + */ + @ApiOperation(value = "获取店员动态", notes = "根据店员ID查询该店员的动态") + @ApiImplicitParam(name = "id", value = "店员ID", required = true, dataType = "String", paramType = "query") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayClerkArticleInfoEntity.class, responseContainer = "Page")}) + @GetMapping("/custom/queryByClerkId") + public R queryTrendsById(@RequestParam("id") String id) { + PlayClerkUserInfoEntity entity = playClerkUserInfoService.selectById(id); + PlayClerkArticleCustomQueryVo vo = new PlayClerkArticleCustomQueryVo(); + vo.setClerkId(entity.getId()); + return R.ok(playClerkArticleInfoService.customSelectByPage(vo, customUserService.getLoginUserId())); + } + + /** + * 顾客查询已收藏动态列表 + */ + @ApiOperation(value = "更新点赞状态", notes = "顾客更新对动态的点赞状态") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @CustomUserLogin + @PostMapping("/custom/updateGreedState") + public R customUpdateGreedState( + @ApiParam(value = "点赞信息", required = true) @Validated @RequestBody PlayClerkArticleFollowCustomGreedStateEditStateVo vo) { + PlayClerkArticleInfoEntity articleInfoEntity = playClerkArticleInfoService + .selectPlayClerkArticleInfoById(vo.getId()); + PlayCustomArticleInfoEntity entity = playCustomArticleInfoService.selectByArticleId(articleInfoEntity.getId(), + ThreadLocalRequestDetail.getCustomUserInfo().getId(), "0"); + if (entity == null) { + entity = new PlayCustomArticleInfoEntity(); + entity.setArticleId(articleInfoEntity.getId()); + entity.setCustomId(ThreadLocalRequestDetail.getCustomUserInfo().getId()); + entity.setEndorseType("1"); + entity.setClerkId(articleInfoEntity.getClerkId()); + } + entity.setEndorseTime(LocalDateTime.now()); + entity.setEndorseState(vo.getGreedState()); + playCustomArticleInfoService.saveOrUpdate(entity); + return R.ok("成功"); + } + + @ApiOperation(value = "更新收藏状态", notes = "顾客更新对动态的收藏状态") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @CustomUserLogin + @PostMapping("/custom/updateFollowState") + public R customUpdateFollowState( + @ApiParam(value = "收藏信息", required = true) @Validated @RequestBody PlayClerkArticleFollowCustomFollowStateEditStateVo vo) { + PlayClerkArticleInfoEntity articleInfoEntity = playClerkArticleInfoService + .selectPlayClerkArticleInfoById(vo.getId()); + PlayCustomArticleInfoEntity entity = playCustomArticleInfoService.selectByArticleId(articleInfoEntity.getId(), + ThreadLocalRequestDetail.getCustomUserInfo().getId(), "1"); + if (entity == null) { + entity = new PlayCustomArticleInfoEntity(); + entity.setArticleId(articleInfoEntity.getId()); + entity.setCustomId(ThreadLocalRequestDetail.getCustomUserInfo().getId()); + entity.setEndorseType("0"); + entity.setClerkId(articleInfoEntity.getClerkId()); + } + entity.setEndorseTime(LocalDateTime.now()); + entity.setEndorseState(vo.getFollowState()); + playCustomArticleInfoService.saveOrUpdate(entity); + return R.ok("成功"); + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/controller/WxClerkCommodityController.java --- +package com.starry.admin.modules.weichat.controller; + +import com.starry.admin.common.aspect.ClerkUserLogin; +import com.starry.admin.common.conf.ThreadLocalRequestDetail; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.clerk.module.entity.PlayClerkCommodityEntity; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity; +import com.starry.admin.modules.clerk.service.IPlayClerkCommodityService; +import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService; +import com.starry.admin.modules.shop.module.entity.PlayCommodityAndLevelInfoEntity; +import com.starry.admin.modules.shop.service.IPlayCommodityAndLevelInfoService; +import com.starry.admin.modules.shop.service.IPlayCommodityInfoService; +import com.starry.admin.modules.weichat.entity.PlayCommodityReturnVo; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +/** + * 店员等级 + * + * @author admin + * @since 2024/5/29 上午6:24 + **/ +@Api(tags = "微信店员商品接口", description = "微信端店员商品相关接口") +@Slf4j +@RestController +@RequestMapping("/wx/commodity/") +public class WxClerkCommodityController { + + @Resource + private IPlayCommodityInfoService playCommodityInfoService; + + @Resource + private IPlayCommodityAndLevelInfoService iPlayCommodityAndLevelInfoService; + + @Resource + private IPlayClerkUserInfoService clerkUserInfoService; + + @Resource + IPlayClerkCommodityService playClerkCommodityService; + + @ApiOperation(value = "根据等级查询商品", notes = "根据等级ID查询对应等级的所有商品") + @ApiImplicitParam(name = "id", value = "等级ID", dataType = "String", paramType = "query") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayCommodityReturnVo.class, responseContainer = "List")}) + @GetMapping("/custom/queryClerkAllCommodityByLevel") + public R queryClerkAllCommodityByLevel(@RequestParam("id") String levelId) { + List levelInfoEntities = iPlayCommodityAndLevelInfoService.selectAll(); + List tree = playCommodityInfoService.selectTree(); + if (levelId == null || levelId.isEmpty()) { + return R.ok(tree); + } + tree = formatPlayCommodityReturnVoTree(tree, levelInfoEntities, levelId); + tree = formatPlayCommodityReturnVoTree(tree, null); + return R.ok(tree); + } + + /** + * 顾客查询当前店员所有服务项目 + * + * @return 店员所有服务项目 + */ + @ApiOperation(value = "查询店员商品", notes = "根据店员ID查询该店员提供的所有商品服务") + @ApiImplicitParam(name = "id", value = "店员ID", required = true, dataType = "String", paramType = "query") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayCommodityReturnVo.class, responseContainer = "List"), + @ApiResponse(code = 500, message = "请求参数异常,id不能为空")}) + @GetMapping("/custom/queryClerkAllCommodity") + public R customQueryClerkAllCommodity(@RequestParam("id") String clerkId) { + if (clerkId == null || clerkId.isEmpty()) { + throw new CustomException("请求参数异常,id不能为空"); + } + PlayClerkUserInfoEntity clerkUserInfo = clerkUserInfoService.selectById(clerkId); + Map> clerkCommodityEntities = playClerkCommodityService + .selectCommodityTypeByUser(clerkId, "1").stream() + .collect(Collectors.groupingBy(PlayClerkCommodityEntity::getCommodityId)); + List levelInfoEntities = iPlayCommodityAndLevelInfoService.selectAll(); + List tree = playCommodityInfoService.selectTree(); + tree = formatPlayCommodityReturnVoTree(tree, levelInfoEntities, clerkUserInfo.getLevelId()); + tree = formatPlayCommodityReturnVoTree(tree, clerkCommodityEntities); + return R.ok(tree); + } + + /** + * 店员查询自己的服务项目 + * + * @return 店员所有服务项目 + */ + @ApiOperation(value = "店员查询自己的商品", notes = "当前登录店员查询自己提供的所有商品服务") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayCommodityReturnVo.class, responseContainer = "List")}) + @ClerkUserLogin + @GetMapping("/clerk/queryAllCommodity") + public R clerkQueryAllCommodity() { + String levelId = ThreadLocalRequestDetail.getClerkUserInfo().getLevelId(); + List levelInfoEntities = iPlayCommodityAndLevelInfoService.selectAll(); + Map> clerkCommodityEntities = playClerkCommodityService + .selectCommodityTypeByUser(ThreadLocalRequestDetail.getClerkUserInfo().getId(), "1").stream() + .collect(Collectors.groupingBy(PlayClerkCommodityEntity::getCommodityId)); + + List tree = playCommodityInfoService.selectTree(); + tree = formatPlayCommodityReturnVoTree(tree, levelInfoEntities, levelId); + tree = formatPlayCommodityReturnVoTree(tree, clerkCommodityEntities); + return R.ok(tree); + } + + public List formatPlayCommodityReturnVoTree(List tree, + List levelInfoEntities, String levelId) { + Iterator it = tree.iterator(); + while (it.hasNext()) { + PlayCommodityReturnVo item = it.next(); + // 查找当前服务项目对应的价格 + for (PlayCommodityAndLevelInfoEntity levelInfoEntity : levelInfoEntities) { + if (item.getId().equals(levelInfoEntity.getCommodityId()) + && levelId.equals(levelInfoEntity.getLevelId())) { + item.setPrice(levelInfoEntity.getPrice()); + } + } + // 如果未设置价格,删除元素 + if (!"00".equals(item.getPId()) && item.getPrice() == null) { + it.remove(); + } + formatPlayCommodityReturnVoTree(item.getChild(), levelInfoEntities, levelId); + } + return tree; + } + + public List formatPlayCommodityReturnVoTree(List tree, + Map> clerkCommodityEntities) { + Iterator it = tree.iterator(); + while (it.hasNext()) { + PlayCommodityReturnVo item = it.next(); + if ("00".equals(item.getPId()) && item.getChild().isEmpty()) { + it.remove(); + } else if (clerkCommodityEntities != null && "00".equals(item.getPId()) + && !clerkCommodityEntities.containsKey(item.getId())) { + it.remove(); + } + formatPlayCommodityReturnVoTree(item.getChild(), clerkCommodityEntities); + } + return tree; + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/controller/WxClerkController.java --- +package com.starry.admin.modules.weichat.controller; + +import cn.hutool.crypto.SecureUtil; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.common.aspect.ClerkUserLogin; +import com.starry.admin.common.conf.ThreadLocalRequestDetail; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.clerk.module.entity.*; +import com.starry.admin.modules.clerk.module.vo.PlayClerkCommodityEditVo; +import com.starry.admin.modules.clerk.module.vo.PlayClerkCommodityQueryVo; +import com.starry.admin.modules.clerk.service.*; +import com.starry.admin.modules.clerk.service.impl.PlayClerkUserInfoServiceImpl; +import com.starry.admin.modules.clerk.service.impl.PlayClerkUserReviewInfoServiceImpl; +import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity; +import com.starry.admin.modules.order.module.vo.PlayOrderEvaluateQueryVo; +import com.starry.admin.modules.order.module.vo.PlayOrderStateEditVo; +import com.starry.admin.modules.order.service.IPlayOrderEvaluateInfoService; +import com.starry.admin.modules.order.service.IPlayOrderInfoService; +import com.starry.admin.modules.personnel.module.entity.PlayPersonnelGroupInfoEntity; +import com.starry.admin.modules.personnel.service.IPlayPersonnelGroupInfoService; +import com.starry.admin.modules.shop.module.entity.PlayGiftInfoEntity; +import com.starry.admin.modules.shop.service.IPlayGiftInfoService; +import com.starry.admin.modules.statistics.service.IPlayClerkPerformanceService; +import com.starry.admin.modules.weichat.entity.*; +import com.starry.admin.modules.weichat.entity.clerk.PlayClerkLevelAndRankingVo; +import com.starry.admin.modules.weichat.entity.clerk.PlayClerkLevelInfoReturnVo; +import com.starry.admin.modules.weichat.entity.clerk.PlayClerkUserInfoQueryVo; +import com.starry.admin.modules.weichat.entity.clerk.PlayClerkUserInfoResultVo; +import com.starry.admin.modules.weichat.entity.gift.PlayClerkGiftReturnVo; +import com.starry.admin.modules.weichat.entity.order.PlayClerkOrderDetailsReturnVo; +import com.starry.admin.modules.weichat.entity.order.PlayClerkOrderInfoQueryVo; +import com.starry.admin.modules.weichat.entity.order.PlayClerkOrderListReturnVo; +import com.starry.admin.modules.weichat.service.WxCustomMpService; +import com.starry.admin.modules.weichat.service.WxCustomUserService; +import com.starry.admin.utils.SecurityUtils; +import com.starry.admin.utils.SmsUtils; +import com.starry.common.redis.RedisCache; +import com.starry.common.result.R; +import com.starry.common.utils.ConvertUtil; +import com.starry.common.utils.VerificationCodeUtils; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * @author admin + */ +@Api(tags = "微信店员接口", description = "微信端店员相关接口") +@Slf4j +@RestController +@RequestMapping("/wx/clerk/") +public class WxClerkController { + + @Resource + RedisCache redisCache; + + @Resource + private PlayClerkUserInfoServiceImpl playClerkUserInfoService; + + @Resource + private IPlayClerkLevelInfoService playClerkLevelInfoService; + + @Resource + private IPlayClerkUserInfoService clerkUserInfoService; + + @Resource + private IPlayClerkCommodityService playClerkCommodityService; + + @Resource + private WxCustomUserService customUserService; + + @Resource + private IPlayOrderInfoService playOrderInfoService; + + @Resource + private IPlayOrderEvaluateInfoService playOrderEvaluateInfoService; + + @Resource + private PlayClerkUserReviewInfoServiceImpl playClerkUserReviewInfoService; + + @Resource + private IPlayClerkDataReviewInfoService playClerkDataReviewInfoService; + + @Resource + private IPlayClerkClassificationInfoService playClerkClassificationInfoService; + + @Resource + private IPlayGiftInfoService giftInfoService; + + @Resource + private IPlayClerkPerformanceService playClerkPerformanceService; + + @Resource + private IPlayPersonnelGroupInfoService playPersonnelGroupInfoService; + @Resource + private SmsUtils smsUtils; + @Resource + private WxCustomMpService wxCustomMpService; + + /** + * 店员获取个人业绩信息 + */ + @ApiOperation(value = "查询店员业绩", notes = "店员获取个人业绩信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @ClerkUserLogin + @PostMapping("/user/queryPerformanceInfo") + public R queryPerformanceInfo( + @ApiParam(value = "业绩查询条件", required = true) @Validated @RequestBody PlayClerkWxPerformanceInfoQueryVo vo) { + PlayClerkUserInfoEntity entity = clerkUserInfoService + .selectById(ThreadLocalRequestDetail.getClerkUserInfo().getId()); + List clerkLevelInfoEntity = playClerkLevelInfoService.selectAll(); + List orderInfoEntities = playOrderInfoService.clerkSelectOrderInfoList(entity.getId(), + vo.getStartTime(), vo.getEndTime()); + List groupInfoEntities = playPersonnelGroupInfoService.selectAll(); + return R.ok(playClerkPerformanceService.getClerkPerformanceInfo(entity, orderInfoEntities, clerkLevelInfoEntity, + groupInfoEntities)); + } + + /** + * 店员获取个人等级信息 + */ + @ApiOperation(value = "查询店员等级", notes = "店员获取个人等级信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = PlayClerkLevelInfoReturnVo.class)}) + @ClerkUserLogin + @GetMapping("/user/queryLevelInfo") + public R queryLevelInfo() { + PlayClerkUserInfoEntity entity = clerkUserInfoService + .selectById(ThreadLocalRequestDetail.getClerkUserInfo().getId()); + PlayClerkLevelInfoEntity level = playClerkLevelInfoService.selectPlayClerkLevelInfoById(entity.getLevelId()); + PlayClerkLevelInfoReturnVo returnVo = new PlayClerkLevelInfoReturnVo(); + returnVo.setLevelName(level.getName()); + returnVo.setLevelId(level.getId()); + List levelAndRanking = new ArrayList<>(); + levelAndRanking.add(new PlayClerkLevelAndRankingVo("女神", 0, 0, 0)); + levelAndRanking.add(new PlayClerkLevelAndRankingVo("男神", 0, 0, 1)); + levelAndRanking.add(new PlayClerkLevelAndRankingVo("首席", 1, 2, 2)); + levelAndRanking.add(new PlayClerkLevelAndRankingVo("镇店", 3, 8, 3)); + levelAndRanking.add(new PlayClerkLevelAndRankingVo("金牌", 9, 18, 4)); + levelAndRanking.add(new PlayClerkLevelAndRankingVo("普通", 19, 150, 5)); + returnVo.setLevelAndRanking(levelAndRanking); + return R.ok(returnVo); + } + + /** + * 店员获取个人信息 + */ + @ApiOperation(value = "查询店员信息", notes = "店员获取个人详细信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = PlayClerkUserInfoResultVo.class), + @ApiResponse(code = 500, message = "用户不存在")}) + @ClerkUserLogin + @GetMapping("/user/queryById") + public R queryById() { + PlayClerkUserInfoEntity entity = clerkUserInfoService + .selectById(ThreadLocalRequestDetail.getClerkUserInfo().getId()); + if (entity == null) { + throw new CustomException("用户不存在"); + } + return R.ok(clerkUserInfoService.getVo(entity)); + } + + @ApiOperation(value = "发送验证码", notes = "店员绑定手机号发送验证码") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = String.class)}) + @ClerkUserLogin + @PostMapping("/user/sendCode") + public R sendCode( + @ApiParam(value = "发送验证码信息", required = true) @Validated @RequestBody PlayClerkUserSendCodeVo vo) { + String codeKey = "login_codes:" + SecurityUtils.getTenantId() + "_" + + SecureUtil.md5(vo.getAreaCode() + vo.getPhone()); + String code = VerificationCodeUtils.getVerificationCode(4); + redisCache.setCacheObject(codeKey, code, 5L, TimeUnit.MINUTES); + // 发送验证码, + return R.ok(code); + } + + @ApiOperation(value = "绑定手机号", notes = "店员绑定手机号") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "验证码错误")}) + @ClerkUserLogin + @PostMapping("/user/bindCode") + public R bindCode( + @ApiParam(value = "绑定验证码信息", required = true) @Validated @RequestBody PlayClerkUserBindCodeVo vo) { + String codeKey = "login_codes:" + SecurityUtils.getTenantId() + "_" + + SecureUtil.md5(vo.getAreaCode() + vo.getPhone()); + String code = redisCache.getCacheObject(codeKey); + if (code == null || !code.equals(vo.getCode())) { + throw new CustomException("验证码错误"); + } + // 账号绑定操作 + String id = ThreadLocalRequestDetail.getClerkUserInfo().getId(); + PlayClerkUserInfoEntity clerkUserInfoEntity = new PlayClerkUserInfoEntity(); + clerkUserInfoEntity.setId(id); + clerkUserInfoEntity.setPhone(vo.getPhone()); + playClerkUserInfoService.update(clerkUserInfoEntity); + // 删除验证码缓存 + redisCache.deleteObject(codeKey); + + return R.ok("成功"); + } + + @ApiOperation(value = "店员申请", notes = "用户申请成为店员") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "系统错误,用户不存在"), + @ApiResponse(code = 500, message = "当前用户已经是店员"), @ApiResponse(code = 500, message = "已有申请未审核")}) + @ClerkUserLogin + @PostMapping("/user/add") + @Transactional(rollbackFor = Exception.class) + public R userAdd(@ApiParam(value = "店员申请信息", required = true) @Validated @RequestBody PlayClerkUserByWxAddVo vo) { + String clerkId = ThreadLocalRequestDetail.getClerkUserInfo().getId(); + PlayClerkUserInfoEntity userInfo = playClerkUserInfoService.selectById(clerkId); + if (userInfo == null) { + throw new CustomException("系统错误,用户不存在"); + } + if ("1".equals(userInfo.getClerkState())) { + throw new CustomException("当前用户已经是店员"); + } + PlayClerkUserReviewInfoEntity entity = playClerkUserReviewInfoService.queryByClerkId(userInfo.getId(), "0"); + if (entity != null) { + throw new CustomException("已有申请未审核"); + } + smsUtils.checkSmsCode(vo.getPhone(), vo.getSmsCode()); + + entity = ConvertUtil.entityToVo(vo, PlayClerkUserReviewInfoEntity.class); + entity.setReviewState("0"); + entity.setClerkId(clerkId); + entity.setAddTime(LocalDateTime.now()); + playClerkUserReviewInfoService.create(entity); + wxCustomMpService.sendClerkApplyNoticeForAdmin(entity, userInfo.getTenantId()); + return R.ok("申请成功"); + } + + @ApiOperation(value = "更新头像", notes = "店员更新头像") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @ClerkUserLogin + @PostMapping("/user/updateAvatar") + public R updateAvatar(@ApiParam(value = "头像信息", required = true) @Validated @RequestBody PlayClerkUserAvatarVo vo) { + PlayClerkUserInfoEntity userInfo = ThreadLocalRequestDetail.getClerkUserInfo(); + // PlayClerkDataReviewInfoEntity entity = + // playClerkDataReviewInfoService.queryByClerkId(userInfo.getId(), "1", "0"); + // if (entity != null) { + // throw new CustomException("已有申请未审核"); + // } + PlayClerkDataReviewInfoEntity entity = new PlayClerkDataReviewInfoEntity(); + entity.setClerkId(userInfo.getId()); + entity.setDataType("1"); + entity.setReviewState("0"); + List list = new ArrayList<>(); + list.add(vo.getAvatar()); + entity.setDataContent(list); + playClerkDataReviewInfoService.create(entity); + return R.ok("提交成功,等待审核~"); + } + + @ClerkUserLogin + @PostMapping("/user/updateAlbum") + public R updateAlbum(@Validated @RequestBody PlayClerkUserAlbumVo vo) { + PlayClerkUserInfoEntity userInfo = ThreadLocalRequestDetail.getClerkUserInfo(); + // PlayClerkDataReviewInfoEntity entity = + // playClerkDataReviewInfoService.queryByClerkId(userInfo.getId(), "2", "0"); + // if (entity != null) { + // throw new CustomException("已有申请未审核"); + // } + PlayClerkDataReviewInfoEntity entity = new PlayClerkDataReviewInfoEntity(); + entity.setClerkId(userInfo.getId()); + entity.setDataType("2"); + entity.setReviewState("0"); + entity.setDataContent(vo.getAlbum()); + playClerkDataReviewInfoService.create(entity); + return R.ok("提交成功,等待审核~"); + } + + @ClerkUserLogin + @PostMapping("/user/updateAudio") + public R updateAudio(@Validated @RequestBody PlayClerkUserAudioVo vo) { + PlayClerkUserInfoEntity userInfo = ThreadLocalRequestDetail.getClerkUserInfo(); + // PlayClerkDataReviewInfoEntity entity = + // playClerkDataReviewInfoService.queryByClerkId(userInfo.getId(), "3", "0"); + // if (entity != null) { + // throw new CustomException("已有申请未审核"); + // } + PlayClerkDataReviewInfoEntity entity = new PlayClerkDataReviewInfoEntity(); + entity.setClerkId(userInfo.getId()); + entity.setDataType("3"); + entity.setReviewState("0"); + List list = new ArrayList<>(); + list.add(vo.getAudio()); + entity.setDataContent(list); + playClerkDataReviewInfoService.create(entity); + return R.ok("提交成功,等待审核~"); + } + + @ClerkUserLogin + @PostMapping("/user/updateOnlineState") + public R updateAudio(@Validated @RequestBody PlayClerkUserOnlineStateVo vo) { + String userId = ThreadLocalRequestDetail.getClerkUserInfo().getId(); + PlayClerkUserInfoEntity entity = new PlayClerkUserInfoEntity(); + entity.setOnlineState(vo.getOnlineState()); + entity.setId(userId); + playClerkUserInfoService.update(entity); + return R.ok("修改成功"); + } + + @ClerkUserLogin + @PostMapping("/user/updateCommodity") + public R updateAudio(@Validated @RequestBody PlayClerkCommodityEditVo vo) { + playClerkCommodityService.startStopClerkItem(vo.getCommodityType(), vo.getEnablingState(), + ThreadLocalRequestDetail.getClerkUserInfo().getId()); + return R.ok("成功"); + } + + @ClerkUserLogin + @PostMapping("/user/updateOther") + public R updateOther(@Validated @RequestBody PlayClerkUserOtherVo vo) { + PlayClerkUserInfoEntity userInfo = ConvertUtil.entityToVo(vo, PlayClerkUserInfoEntity.class); + userInfo.setId(ThreadLocalRequestDetail.getClerkUserInfo().getId()); + playClerkUserInfoService.update(userInfo); + return R.ok("申请成功"); + } + + /** + * 查询陪聊服务项目列表 + */ + @GetMapping("/user/listAllCommodity") + public R listAllCommodity() { + List list = playClerkCommodityService.selectAll(); + return R.ok(ConvertUtil.entityToVoList(list, PlayClerkCommodityQueryVo.class)); + } + + /** + * 分页获取店员列表 + * + * @param vo + * PlayClerkUserInfoQueryVo + * @return 店员列表 + */ + @PostMapping("/user/queryByPage") + public R queryByPage(@RequestBody PlayClerkUserInfoQueryVo vo) { + IPage page = playClerkUserInfoService.selectByPage(vo, + customUserService.getLoginUserId()); + return R.ok(page); + } + + /** + * 获取推荐用户列表 + * + * @return 店员列表 + */ + @PostMapping("/user/queryByRecommend") + public R queryByRecommend() { + PlayClerkUserInfoQueryVo vo = new PlayClerkUserInfoQueryVo(); + vo.setPageNum(1); + vo.setPageSize(9999); + vo.setRecommendationState("1"); + IPage page = playClerkUserInfoService.selectByPage(vo, ""); + return R.ok(page); + } + + /** + * 获取店员礼物信息 + * + * @param id + * 店员ID + * @return 店员礼物 + */ + + @GetMapping("/user/queryGiftById") + public R queryGiftById(@RequestParam("id") String id) { + PlayClerkUserInfoEntity entity = clerkUserInfoService.selectById(id); + if (entity == null) { + throw new CustomException("用户不存在"); + } + // 获取所有礼物列表 + List giftInfoEntities = giftInfoService.listByAll(); + // 获取已点亮礼物 + List clerkListByAll = giftInfoService.clerkListByAll(id, "1"); + // 组装数据 + List result = new ArrayList<>(); + for (PlayGiftInfoEntity giftInfoEntity : giftInfoEntities) { + PlayClerkGiftReturnVo item = ConvertUtil.entityToVo(giftInfoEntity, PlayClerkGiftReturnVo.class); + for (PlayClerkGiftReturnVo playClerkGiftReturnVo : clerkListByAll) { + if (giftInfoEntity.getId().equals(playClerkGiftReturnVo.getId())) { + item.setGiffNumber(playClerkGiftReturnVo.getGiffNumber()); + } + } + result.add(item); + } + Map resuleMap = new HashMap<>(); + resuleMap.put("list", result); + resuleMap.put("obtainedGift", clerkListByAll.size()); + resuleMap.put("totalGift", giftInfoEntities.size()); + return R.ok(resuleMap); + } + + /** + * 获取店员价格 + * + * @param id + * 店员ID + * @return 店员价格 + */ + @GetMapping("/user/queryPriceById") + public R queryDetailById(@RequestParam("id") String id) { + return R.ok(); + } + + /** + * 店员分页查询本人订单列表 + * + * @param vo + * 订单列表分页查询对象 + * @return com.starry.common.result.R + * @author admin + * @since 2024/5/8 15:57 + **/ + @ClerkUserLogin + @PostMapping("/order/queryByPage") + public R queryOrderByPage(@Validated @RequestBody PlayClerkOrderInfoQueryVo vo) { + vo.setAcceptBy(ThreadLocalRequestDetail.getClerkUserInfo().getId()); + IPage iPage = playOrderInfoService.clerkSelectOrderInfoByPage(vo); + return R.ok(iPage); + } + + /** + * 店员查询本人订单详情 + * + * @param id + * 订单ID + * @return com.starry.common.result.R + * @author admin + * @since 2024/5/8 15:57 + **/ + @ClerkUserLogin + @GetMapping("/order/queryById") + public R queryById(@RequestParam("id") String id) { + PlayClerkOrderDetailsReturnVo orderInfo = playOrderInfoService + .clerkSelectOrderDetails(ThreadLocalRequestDetail.getClerkUserInfo().getId(), id); + return R.ok(orderInfo); + } + + /** + * 店员-接单 + * + * @param id + * 订单ID + * @return com.starry.common.result.R + * @author admin + * @since 2024/5/8 15:57 + **/ + @ClerkUserLogin + @GetMapping("/order/accept") + public R acceptOrder(@RequestParam("id") String id) { + playOrderInfoService.updateStateTo1("1", ThreadLocalRequestDetail.getClerkUserInfo().getId(), + ThreadLocalRequestDetail.getClerkUserInfo().getId(), id); + return R.ok("成功"); + } + + /** + * 店员-开始订单 + * + * @param id + * 订单ID + * @return com.starry.common.result.R + * @author admin + * @since 2024/5/8 15:57 + **/ + @ClerkUserLogin + @GetMapping("/order/start") + public R startOrder(@RequestParam("id") String id) { + playOrderInfoService.updateStateTo23("1", ThreadLocalRequestDetail.getClerkUserInfo().getId(), "2", id); + return R.ok("成功"); + } + + /** + * 店员-取消订单 + * + * @param vo + * 取消订单传参 + * @return com.starry.common.result.R + * @author admin + * @since 2024/5/8 15:57 + **/ + @ClerkUserLogin + @PostMapping("/order/cancellation") + public R endOrder(@Validated @RequestBody PlayOrderStateEditVo vo) { + playOrderInfoService.updateStateTo4("1", ThreadLocalRequestDetail.getClerkUserInfo().getId(), vo.getOrderId(), + vo.getRefundReason(), vo.getImages()); + return R.ok("成功"); + } + + /** + * 分页获取店员评价(订单评价) + * + * @param vo + * 店员评价查询对象 + * @return 店员评价 + */ + @PostMapping("/user/queryEvaluateByPage") + public R queryEvaluateById(@Validated @RequestBody PlayOrderEvaluateQueryVo vo) { + clerkUserInfoService.selectById(vo.getClerkId()); + return R.ok(playOrderEvaluateInfoService.selectByPage(vo)); + } + + @GetMapping("/level/queryAll") + public R userAdd() { + return R.ok(playClerkLevelInfoService.selectAll()); + } + + @GetMapping("/class/queryAll") + public R queryClassAll() { + return R.ok(playClerkClassificationInfoService.selectAll()); + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/controller/WxClerkLeveController.java --- +package com.starry.admin.modules.weichat.controller; + +import com.starry.admin.modules.clerk.module.entity.PlayClerkLevelInfoEntity; +import com.starry.admin.modules.clerk.service.IPlayClerkLevelInfoService; +import com.starry.admin.modules.weichat.entity.level.PlayClerkLevelReturnVo; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.util.ArrayList; +import java.util.List; +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 店员等级 + * + * @author admin + * @since 2024/5/29 上午6:24 + **/ +@Api(tags = "微信店员等级接口", description = "微信端店员等级相关接口") +@Slf4j +@RestController +@RequestMapping("/wx/level/") +public class WxClerkLeveController { + + @Resource + private IPlayClerkLevelInfoService playClerkLevelInfoService; + + /** + * 顾客查询所有店员所有等级列表 + * + * @return 店员所有等级列表 + */ + @ApiOperation(value = "查询店员等级列表", notes = "顾客查询所有店员等级列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayClerkLevelReturnVo.class, responseContainer = "List")}) + @GetMapping("/custom/queryClerkAllLevel") + public R customQueryClerkAllLevel() { + List list = playClerkLevelInfoService.selectAll(); + List returnVoList = new ArrayList<>(list.size()); + for (PlayClerkLevelInfoEntity entity : list) { + PlayClerkLevelReturnVo vo = new PlayClerkLevelReturnVo(); + vo.setId(entity.getId()); + vo.setLevelName(entity.getName()); + returnVoList.add(vo); + } + return R.ok(returnVoList); + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/controller/WxClerkTypeController.java --- +package com.starry.admin.modules.weichat.controller; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.starry.admin.modules.clerk.module.entity.PlayClerkTypeInfoEntity; +import com.starry.admin.modules.clerk.service.IPlayClerkTypeInfoService; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.util.List; +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 店员等级 + * + * @author admin + * @since 2024/5/29 上午6:24 + **/ +@Api(tags = "微信店员类型接口", description = "微信端店员类型相关接口") +@Slf4j +@RestController +@RequestMapping("/wx/clerk/type") +public class WxClerkTypeController { + + @Resource + private IPlayClerkTypeInfoService clerkTypeInfoService; + + /** + * 顾客查询所有店员所有等级列表 + * + * @return 店员所有等级列表 + */ + @ApiOperation(value = "查询店员类型列表", notes = "查询所有店员类型列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayClerkTypeInfoEntity.class, responseContainer = "List")}) + @GetMapping("/list") + public R clerkTypeList() { + List list = clerkTypeInfoService.list( + Wrappers.lambdaQuery(PlayClerkTypeInfoEntity.class).eq(PlayClerkTypeInfoEntity::getHomeDisplayed, 1) + .orderByDesc(PlayClerkTypeInfoEntity::getSort)); + return R.ok(list); + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/controller/WxClerkWagesController.java --- +package com.starry.admin.modules.weichat.controller; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.starry.admin.common.aspect.ClerkUserLogin; +import com.starry.admin.common.conf.ThreadLocalRequestDetail; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.clerk.module.entity.PlayClerkWagesDetailsInfoEntity; +import com.starry.admin.modules.clerk.module.entity.PlayClerkWagesInfoEntity; +import com.starry.admin.modules.clerk.service.IPlayClerkWagesDetailsInfoService; +import com.starry.admin.modules.clerk.service.IPlayClerkWagesInfoService; +import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity; +import com.starry.admin.modules.order.service.IPlayOrderInfoService; +import com.starry.admin.modules.weichat.entity.wages.*; +import com.starry.common.result.R; +import com.starry.common.utils.ConvertUtil; +import com.starry.common.utils.IdUtils; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; + +/** + * 店员工资接口 + * + * @author admin + * @since 2024/5/31 16:18 + **/ +@Api(tags = "微信店员工资接口", description = "微信端店员工资相关接口") +@Slf4j +@RestController +@RequestMapping("/wx/wages") +public class WxClerkWagesController { + @Resource + private IPlayClerkWagesInfoService playClerkWagesInfoService; + + @Resource + private IPlayClerkWagesDetailsInfoService playClerkWagesDetailsInfoService; + + @Resource + private IPlayOrderInfoService playOrderInfoService; + + /** + * 店员查询本人未结算工资 订单完成之后,24小时之后进行订单结算,并且一旦订单结算了,就无法进行退款。想要退款,只能在24小时之内进行。 + * + * @author admin + * @since 2024/5/31 16:20 + **/ + @ApiOperation(value = "查询未结算工资", notes = "店员查询本人未结算工资") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = ClerkUnsettledWagesReturnVo.class)}) + @ClerkUserLogin + @GetMapping("clerk/queryUnsettledWages") + public R clerkQueryUnsettledWages() { + List list = playOrderInfoService + .queryBySettlementOrder(ThreadLocalRequestDetail.getClerkUserInfo().getId(), "0"); + BigDecimal orderMoney = BigDecimal.ZERO; + BigDecimal estimatedRevenue = BigDecimal.ZERO; + for (PlayOrderInfoEntity entity : list) { + orderMoney = orderMoney.add(entity.getFinalAmount()); + estimatedRevenue = estimatedRevenue.add(entity.getEstimatedRevenue()); + } + ClerkUnsettledWagesReturnVo vo = new ClerkUnsettledWagesReturnVo(orderMoney, list.size(), estimatedRevenue); + return R.ok(vo); + } + + /** + * 店员查询本人当期工资 + * + * @author admin + * @since 2024/5/31 16:20 + **/ + @ApiOperation(value = "查询当期工资", notes = "店员查询本人当期工资") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = ClerkCurrentPeriodWagesReturnVo.class)}) + @ClerkUserLogin + @GetMapping("clerk/queryCurrentPeriodWages") + public R clerkQueryCurrentPeriodWages() { + PlayClerkWagesInfoEntity entity = playClerkWagesInfoService + .selectCurrentPeriodWagesByClerkId(ThreadLocalRequestDetail.getClerkUserInfo().getId()); + if (entity == null) { + entity = new PlayClerkWagesInfoEntity(); + entity.setClerkId(ThreadLocalRequestDetail.getClerkUserInfo().getId()); + entity.setId(IdUtils.getUuid()); + entity.setStartCountDate(LocalDate.now()); + entity.setEndCountDate(LocalDate.now()); + entity.setFinalAmount(BigDecimal.ZERO); + entity.setOrderNumber(0); + entity.setOrdersExpiredNumber(0); + entity.setOrderContinueNumber(0); + entity.setOrderContinueProportion(0); + entity.setOrderContinueMoney(BigDecimal.ZERO); + } + ClerkCurrentPeriodWagesReturnVo returnVo = ConvertUtil.entityToVo(entity, + ClerkCurrentPeriodWagesReturnVo.class); + returnVo.setTotalMoney(entity.getFinalAmount()); + returnVo.setOrderWages(ConvertUtil.entityToVo(entity, OrderWagesReturnVo.class)); + return R.ok(returnVo); + } + + /** + * 店员查询本人历史工资 + * + * @author admin + * @since 2024/5/31 16:20 + **/ + @ApiOperation(value = "查询历史工资", notes = "店员查询本人历史工资") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = ClerkHistoricalWagesReturnVo.class, responseContainer = "Page")}) + @ClerkUserLogin + @PostMapping("clerk/queryHistoricalWages") + public R clerkQueryHistoricalWages() { + List list = playClerkWagesInfoService + .selectHistoricalWagesByClerkId(ThreadLocalRequestDetail.getClerkUserInfo().getId()); + List returnVoList = new ArrayList<>(list.size()); + for (PlayClerkWagesInfoEntity entity : list) { + returnVoList.add(ConvertUtil.entityToVo(entity, ClerkHistoricalWagesReturnVo.class)); + } + IPage page = new Page<>(); + page.setTotal(5); + page.setRecords(returnVoList); + page.setSize(10); + page.setPages(1); + return R.ok(page); + + } + + /** + * 店员查询本人工资详情 + * + * @author admin + * @since 2024/5/31 16:20 + **/ + @ApiOperation(value = "查询工资详情", notes = "店员查询本人工资详情") + @ApiImplicitParam(name = "id", value = "工资ID", required = true, dataType = "String", paramType = "query") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = ClerkWagesDetailsReturnVo.class, responseContainer = "List"), + @ApiResponse(code = 500, message = "ID不能为空")}) + @ClerkUserLogin + @GetMapping("clerk/queryWagesDetails") + public R clerkQueryWagesDetails(@RequestParam("id") String id) { + if (StrUtil.isBlankIfStr(id)) { + throw new CustomException("ID不能为空"); + } + List list = playClerkWagesDetailsInfoService.selectByWagesId(id); + List returnVos = new ArrayList<>(list.size()); + for (PlayClerkWagesDetailsInfoEntity entity : list) { + returnVos.add(ConvertUtil.entityToVo(entity, ClerkWagesDetailsReturnVo.class)); + } + return R.ok(returnVos); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/controller/WxCommodityController.java --- +package com.starry.admin.modules.weichat.controller; + +import com.starry.admin.modules.clerk.module.entity.PlayClerkCommodityEntity; +import com.starry.admin.modules.clerk.service.IPlayClerkCommodityService; +import com.starry.admin.modules.weichat.entity.PlayClerkCommodityTreeData; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author admin + */ +@Api(tags = "微信商品接口", description = "微信端商品相关接口") +@Slf4j +@RestController +@RequestMapping("/wx/commodity/") +public class WxCommodityController { + @Resource + private IPlayClerkCommodityService clerkCommodityService; + + @ApiOperation(value = "获取商品树", notes = "根据用户ID获取商品树形结构") + @ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "String", paramType = "query") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayClerkCommodityTreeData.class, responseContainer = "List")}) + @GetMapping("/getTree") + public R getTree(@RequestParam("userId") String userId) { + List commodityEntities = clerkCommodityService.selectByUser(userId); + Map> item = commodityEntities.stream() + .collect(Collectors.groupingBy(PlayClerkCommodityEntity::getCommodityName)); + List result = new ArrayList<>(); + for (Map.Entry> entry : item.entrySet()) { + + PlayClerkCommodityTreeData treeData = new PlayClerkCommodityTreeData(entry.getKey(), entry.getValue()); + result.add(treeData); + } + return R.ok(result); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/controller/WxCommonController.java --- +package com.starry.admin.modules.weichat.controller; + +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.util.StrUtil; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.common.oss.service.IOssFileService; +import com.starry.admin.modules.shop.service.IShopUiSettingService; +import com.starry.admin.modules.system.service.ISysAdministrativeAreaDictInfoService; +import com.starry.admin.modules.weichat.service.WxAccessTokenService; +import com.starry.admin.modules.weichat.utils.WxFileUtils; +import com.starry.admin.utils.SecurityUtils; +import com.starry.common.result.R; +import com.starry.common.utils.IdUtils; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.error.WxErrorException; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +/** + * @author admin + * @since 2024/4/10 16:18 + **/ +@Api(tags = "微信通用接口", description = "微信公共功能相关接口") +@Slf4j +@RestController +@RequestMapping("/wx/common/") +public class WxCommonController { + + @Resource + private IOssFileService ossFileService; + + @Resource + private ISysAdministrativeAreaDictInfoService areaDictInfoService; + @Resource + WxAccessTokenService wxAccessTokenService; + @Resource + private IShopUiSettingService shopUiSettingService; + + @ApiOperation(value = "获取行政区域树", notes = "获取省市区县的树形结构数据") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @GetMapping("area/tree") + public R areaTree() { + return R.ok(areaDictInfoService.selectTree("2")); + } + + @ApiOperation(value = "获取店铺UI设置", notes = "获取当前店铺的UI配置信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @GetMapping("setting/info") + public R selectShopUiSettingInfo() { + return R.ok(shopUiSettingService.selectShopUiSettingInfo()); + } + + @ApiOperation(value = "上传文件", notes = "上传文件到OSS存储") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功,返回文件访问地址")}) + @PostMapping("file/upload") + public R fileUpload(@ApiParam(value = "上传的文件", required = true) @RequestParam("file") MultipartFile file) + throws IOException { + String fileAddress = ossFileService.upload(file.getInputStream(), SecurityUtils.getTenantId(), + file.getOriginalFilename()); + return R.ok(fileAddress); + } + + @ApiOperation(value = "上传音频", notes = "通过微信媒体ID上传音频文件,自动转换为MP3格式") + @ApiImplicitParam(name = "mediaId", value = "微信媒体ID", required = true, dataType = "String", paramType = "query") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功,返回文件访问地址"), + @ApiResponse(code = 500, message = "上传失败,mediaId为空或文件不存在")}) + @GetMapping("audio/upload") + public R audioUpload(@RequestParam("mediaId") String mediaId) throws IOException, WxErrorException { + if (StrUtil.isBlankIfStr(mediaId)) { + throw new CustomException("mediaId不能为空"); + } + String accessToken = wxAccessTokenService.getAccessToken(); + // 下载录音文件,并转化为InputStream + InputStream inputStream = WxFileUtils.getTemporaryMaterial(accessToken, mediaId); + File tempFile = FileUtil.createTempFile("wx_" + SecurityUtils.getTenantId(), IdUtils.getUuid() + ".amr", null) + .toFile(); + // 可以在这里对临时文件进行操作 + log.error("tempFile = {}", tempFile.getPath()); + try (FileOutputStream fileOutputStream = new FileOutputStream(tempFile)) { + byte[] buffer = new byte[1024]; + int bytesRead; + // 读取InputStream并写入到FileOutputStream + while ((bytesRead = inputStream.read(buffer)) != -1) { + fileOutputStream.write(buffer, 0, bytesRead); + } + } + if (FileUtil.size(tempFile) <= 0) { + throw new CustomException("音频文件上传失败,文件不存在"); + } + // 将下载的微信素材文件,转化为MP3文件 + File targetFile = FileUtil.createTempFile("wx_" + SecurityUtils.getTenantId(), IdUtils.getUuid() + ".mp3", null) + .toFile(); + log.error("targetFile = {}", targetFile.getPath()); + WxFileUtils.audioConvert2Mp3(tempFile, targetFile); + // 将MP3文件上传到OSS + String fileAddress = ossFileService.upload(Files.newInputStream(targetFile.toPath()), + SecurityUtils.getTenantId(), IdUtils.getUuid() + ".mp3"); + // 删除临时文件 + FileUtil.del(tempFile); + FileUtil.del(targetFile); + return R.ok(fileAddress); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/controller/WxCouponController.java --- +package com.starry.admin.modules.weichat.controller; + +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson2.JSON; +import com.starry.admin.common.aspect.CustomUserLogin; +import com.starry.admin.common.conf.ThreadLocalRequestDetail; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity; +import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService; +import com.starry.admin.modules.custom.module.entity.PlayCustomUserInfoEntity; +import com.starry.admin.modules.shop.module.entity.PlayCouponInfoEntity; +import com.starry.admin.modules.shop.module.vo.PlayCommodityInfoVo; +import com.starry.admin.modules.shop.module.vo.PlayCouponDetailsReturnVo; +import com.starry.admin.modules.shop.service.IPlayCommodityInfoService; +import com.starry.admin.modules.shop.service.IPlayCouponDetailsService; +import com.starry.admin.modules.shop.service.IPlayCouponInfoService; +import com.starry.admin.modules.weichat.entity.WxCouponOrderQueryVo; +import com.starry.admin.modules.weichat.entity.WxCouponOrderReturnVo; +import com.starry.admin.modules.weichat.entity.WxCouponReceiveReturnVo; +import com.starry.common.result.R; +import com.starry.common.utils.ConvertUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * @author admin + * @since 2024/7/4 11:33 + **/ +@Api(tags = "微信优惠券接口", description = "微信端优惠券相关接口") +@Slf4j +@RestController +@RequestMapping("/wx/coupon/") +public class WxCouponController { + + @Resource + IPlayCouponDetailsService couponDetailsService; + + @Resource + IPlayClerkUserInfoService playClerkUserInfoService; + + @Resource + IPlayCouponInfoService couponInfoService; + + @Resource + private IPlayCommodityInfoService playCommodityInfoService; + + @ApiOperation(value = "领取优惠券", notes = "顾客领取指定ID的优惠券") + @ApiImplicitParam(name = "id", value = "优惠券ID", required = true, dataType = "String", paramType = "query") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = Map.class), + @ApiResponse(code = 500, message = "请求参数异常,优惠券ID不能为空")}) + @CustomUserLogin + @GetMapping("/custom/obtainCoupon") + public R queryAll(@RequestParam("id") String id) { + PlayCustomUserInfoEntity customUserInfo = ThreadLocalRequestDetail.getCustomUserInfo(); + if (StrUtil.isEmpty(id)) { + throw new CustomException("请求参数异常,优惠券ID不能为"); + } + PlayCouponInfoEntity entity = couponInfoService.selectPlayCouponInfoById(id); + String msg = couponInfoService.getReasonForNotObtainingCoupons(entity, customUserInfo); + boolean success = StrUtil.isBlank(msg); + // 优惠券领取验证通过,发放优惠券 + if (success) { + couponDetailsService.create(customUserInfo.getId(), customUserInfo.getNickname(), + customUserInfo.getLevelId(), entity.getId(), "1", "1"); + } + Map result = new HashMap<>(); + result.put("success", success); + result.put("msg", msg); + return R.ok(result); + } + + /** + * 查询所有优惠券,以及本人是否可领取 + * + * @return com.starry.common.result.R + * @author admin + * @since 2024/7/8 13:53 + **/ + @ApiOperation(value = "查询所有优惠券", notes = "查询所有优惠券并标记用户是否已领取") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = WxCouponReceiveReturnVo.class, responseContainer = "List")}) + @CustomUserLogin + @PostMapping("/custom/queryAll") + public R queryAll() { + List obtainedCoupons = couponDetailsService + .selectByCustomId(ThreadLocalRequestDetail.getCustomUserInfo().getId()); + List couponInfoEntities = couponInfoService.queryAll(); + List returnVos = new ArrayList<>(couponInfoEntities.size()); + for (PlayCouponInfoEntity couponInfoEntity : couponInfoEntities) { + if ("0".equals(couponInfoEntity.getCouponOnLineState())) { + continue; + } + WxCouponReceiveReturnVo vo = ConvertUtil.entityToVo(couponInfoEntity, WxCouponReceiveReturnVo.class); + for (PlayCouponDetailsReturnVo obtainedCoupon : obtainedCoupons) { + if (obtainedCoupon.getCouponId().equals(couponInfoEntity.getId())) { + vo.setObtained("1"); + } + } + returnVos.add(vo); + } + return R.ok(returnVos); + } + + /** + * 顾客查询订单可使用优惠券 + */ + @ApiOperation(value = "查询订单可用优惠券", notes = "查询当前订单可使用的优惠券列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = WxCouponOrderReturnVo.class, responseContainer = "List"), + @ApiResponse(code = 500, message = "请求参数异常,店员ID不能为空,等级ID不能为空")}) + @CustomUserLogin + @PostMapping("/custom/queryByOrder") + public R queryByOrder( + @ApiParam(value = "订单查询条件", required = true) @Validated @RequestBody WxCouponOrderQueryVo vo) { + if (vo.getLevelId().isEmpty() && vo.getClerkId().isEmpty()) { + throw new CustomException("请求参数异常,店员ID不能为空,等级ID不能为空"); + } + String levelId = vo.getLevelId(); + if (!vo.getClerkId().isEmpty()) { + PlayClerkUserInfoEntity clerkUserInfo = playClerkUserInfoService.selectById(vo.getClerkId()); + levelId = clerkUserInfo.getLevelId(); + } + log.info(JSON.toJSONString(vo)); + List list = couponDetailsService + .selectByCustomId(ThreadLocalRequestDetail.getCustomUserInfo().getId()); + PlayCommodityInfoVo commodityInfo = playCommodityInfoService.queryCommodityInfo(vo.getCommodityId(), levelId); + // 优惠券列表 + List couponReturnVos = new ArrayList<>(); + for (PlayCouponDetailsReturnVo couponDetails : list) { + PlayCouponInfoEntity couponInfo = couponInfoService.selectPlayCouponInfoById(couponDetails.getCouponId()); + WxCouponOrderReturnVo wxCouponReturnVo = ConvertUtil.entityToVo(couponDetails, WxCouponOrderReturnVo.class); + String couponReasonForUnavailableUse = couponInfoService.getCouponReasonForUnavailableUse(couponInfo, + vo.getPlaceType(), vo.getCommodityId(), vo.getCommodityQuantity(), + commodityInfo.getCommodityPrice()); + if (StrUtil.isEmpty(couponReasonForUnavailableUse)) { + wxCouponReturnVo.setAvailable("1"); + } else { + wxCouponReturnVo.setAvailable("0"); + wxCouponReturnVo.setReasonForUnavailableUse(couponReasonForUnavailableUse); + } + couponReturnVos.add(wxCouponReturnVo); + } + return R.ok(couponReturnVos); + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/controller/WxCustomController.java --- +package com.starry.admin.modules.weichat.controller; + +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson2.JSONObject; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.common.aspect.CustomUserLogin; +import com.starry.admin.common.conf.ThreadLocalRequestDetail; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.common.exception.ServiceException; +import com.starry.admin.common.task.OverdueOrderHandlerTask; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity; +import com.starry.admin.modules.clerk.service.IPlayClerkCommodityService; +import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService; +import com.starry.admin.modules.custom.module.entity.PlayCustomGiftInfoEntity; +import com.starry.admin.modules.custom.module.entity.PlayCustomLeaveMsgEntity; +import com.starry.admin.modules.custom.module.entity.PlayCustomUserInfoEntity; +import com.starry.admin.modules.custom.service.IPlayCustomFollowInfoService; +import com.starry.admin.modules.custom.service.IPlayCustomGiftInfoService; +import com.starry.admin.modules.custom.service.IPlayCustomLeaveMsgService; +import com.starry.admin.modules.custom.service.IPlayCustomUserInfoService; +import com.starry.admin.modules.order.module.entity.PlayOrderComplaintInfoEntity; +import com.starry.admin.modules.order.module.entity.PlayOrderEvaluateInfoEntity; +import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity; +import com.starry.admin.modules.order.service.IPlayOrderComplaintInfoService; +import com.starry.admin.modules.order.service.IPlayOrderEvaluateInfoService; +import com.starry.admin.modules.order.service.IPlayOrderInfoService; +import com.starry.admin.modules.shop.module.entity.PlayClerkGiftInfoEntity; +import com.starry.admin.modules.shop.module.entity.PlayCouponDetailsEntity; +import com.starry.admin.modules.shop.module.entity.PlayCouponInfoEntity; +import com.starry.admin.modules.shop.module.entity.PlayGiftInfoEntity; +import com.starry.admin.modules.shop.module.vo.PlayCommodityInfoVo; +import com.starry.admin.modules.shop.service.*; +import com.starry.admin.modules.weichat.entity.*; +import com.starry.admin.modules.weichat.entity.clerk.PlayClerkUserInfoResultVo; +import com.starry.admin.modules.weichat.entity.costom.PlayCustomHideLevelStateEditVo; +import com.starry.admin.modules.weichat.entity.costom.PlayCustomHideRankingStateEditVo; +import com.starry.admin.modules.weichat.entity.evaluate.PlayCustomOrderEvaluateReturnVo; +import com.starry.admin.modules.weichat.entity.order.PlayCustomOrderDetailsReturnVo; +import com.starry.admin.modules.weichat.entity.order.PlayCustomOrderInfoQueryVo; +import com.starry.admin.modules.weichat.entity.order.PlayCustomOrderListReturnVo; +import com.starry.admin.modules.weichat.entity.order.PlayOrderInfoCommodityAdd; +import com.starry.admin.modules.weichat.entity.user.PlayCustomUserReturnDetailVo; +import com.starry.admin.modules.weichat.service.WxCustomMpService; +import com.starry.admin.modules.weichat.service.WxCustomUserService; +import com.starry.admin.utils.MoneyUtils; +import com.starry.admin.utils.SecurityUtils; +import com.starry.common.result.R; +import com.starry.common.utils.ConvertUtil; +import com.starry.common.utils.IdUtils; +import com.starry.common.utils.StringUtils; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Date; +import java.util.Objects; +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * @author admin + */ +@Api(tags = "微信顾客接口", description = "微信端顾客相关接口") +@Slf4j +@RestController +@RequestMapping("/wx/custom/") +public class WxCustomController { + + @Resource + private IPlayCustomUserInfoService customUserInfoService; + + @Resource + private IPlayClerkUserInfoService clerkUserInfoService; + + @Resource + private IPlayGiftInfoService giftInfoService; + + @Resource + private IPlayCommodityInfoService playCommodityInfoService; + + @Resource + private IPlayCustomFollowInfoService playCustomFollowInfoService; + + @Resource + private IPlayClerkCommodityService playClerkCommodityService; + + @Resource + private WxCustomUserService customUserService; + + @Resource + private IPlayOrderInfoService playOrderInfoService; + + @Resource + private IPlayCustomLeaveMsgService playCustomLeaveMsgService; + + @Resource + private IPlayOrderComplaintInfoService playOrderComplaintInfoService; + + @Resource + private IPlayOrderEvaluateInfoService playOrderEvaluateInfoService; + + @Resource + private IPlayCustomGiftInfoService playCustomGiftInfoService; + + @Resource + private IPlayClerkGiftInfoService playClerkGiftInfoService; + + @Resource + private IPlayCouponInfoService playCouponInfoService; + @Resource + private IPlayCouponDetailsService couponDetailsService; + + @Resource + private WxCustomMpService wxCustomMpService; + + @Resource + OverdueOrderHandlerTask overdueOrderHandlerTask; + + /** + * 根据店员ID查询店员详细信息 + * + * @param id + * 店员ID + * @return 店员详细信息 + */ + @ApiOperation(value = "查询店员详细信息", notes = "根据店员ID查询店员的详细信息") + @ApiImplicitParam(name = "id", value = "店员ID", required = true, dataType = "String", paramType = "query") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = PlayClerkUserInfoResultVo.class)}) + @GetMapping("/queryClerkDetailedById") + public R queryClerkDetailedById(@RequestParam("id") String id) { + PlayClerkUserInfoEntity entity = clerkUserInfoService.selectById(id); + PlayClerkUserInfoResultVo vo = ConvertUtil.entityToVo(entity, PlayClerkUserInfoResultVo.class); + vo.setAddress(entity.getCity()); + // 查询是否关注,未登录情况下,默认为未关注 + String loginUserId = customUserService.getLoginUserId(); + if (StringUtils.isNotEmpty(loginUserId)) { + vo.setFollowState(playCustomFollowInfoService.queryFollowState(loginUserId, vo.getId())); + } + // 服务项目 + vo.setCommodity(playClerkCommodityService.getClerkCommodityList(vo.getId(), "1")); + return R.ok(vo); + } + + /** + * 顾客本人刷新头像 + */ + @ApiOperation(value = "刷新顾客头像", notes = "刷新当前登录顾客的头像信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @CustomUserLogin + @GetMapping("/refreshAvatar") + public R refreshAvatar() { + return R.ok(""); + } + + /** + * 根据顾客ID查询当前顾客详细信息 + */ + @ApiOperation(value = "查询顾客详细信息", notes = "查询当前登录顾客的详细信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = PlayCustomUserReturnDetailVo.class)}) + @CustomUserLogin + @GetMapping("/queryById") + public R queryById() { + String userId = ThreadLocalRequestDetail.getCustomUserInfo().getId(); + PlayCustomUserInfoEntity customUserInfo = customUserInfoService.selectById(userId); + PlayCustomUserReturnDetailVo vo = ConvertUtil.entityToVo(customUserInfo, PlayCustomUserReturnDetailVo.class); + PlayClerkUserInfoEntity clerkUserInfo = clerkUserInfoService.selectByOpenid(customUserInfo.getOpenid()); + if (clerkUserInfo != null) { + vo.setClerkState("1"); + } + return R.ok(vo); + } + + /** + * 顾客本人修改隐藏等级状态 + */ + @ApiOperation(value = "修改隐藏等级状态", notes = "顾客修改自己的隐藏等级状态") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @CustomUserLogin + @PostMapping("/updateHideLevelState") + public R updateHideLevelState( + @ApiParam(value = "隐藏等级状态信息", required = true) @Validated @RequestBody PlayCustomHideLevelStateEditVo vo) { + vo.setId(ThreadLocalRequestDetail.getCustomUserInfo().getId()); + PlayCustomUserInfoEntity entity = new PlayCustomUserInfoEntity(); + BeanUtils.copyProperties(vo, entity); + customUserInfoService.update(entity); + return R.ok("成功"); + } + + /** + * 顾客本人修改隐藏排名状态 + */ + @ApiOperation(value = "修改隐藏排名状态", notes = "顾客修改自己的隐藏排名状态") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @CustomUserLogin + @PostMapping("/updateHideRankingState") + public R updateHideRankingState( + @ApiParam(value = "隐藏排名状态信息", required = true) @Validated @RequestBody PlayCustomHideRankingStateEditVo vo) { + vo.setId(ThreadLocalRequestDetail.getCustomUserInfo().getId()); + PlayCustomUserInfoEntity entity = new PlayCustomUserInfoEntity(); + BeanUtils.copyProperties(vo, entity); + customUserInfoService.update(entity); + return R.ok("成功"); + } + + /** + * 打赏店员-打赏余额 + */ + @ApiOperation(value = "打赏店员", notes = "使用余额打赏店员") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 998, message = "余额不足")}) + @CustomUserLogin + @PostMapping("/order/reward") + public R rewardToOrder( + @ApiParam(value = "打赏信息", required = true) @Validated @RequestBody PlayOrderInfoRewardAdd vo) { + MoneyUtils.verificationTypeIsNormal(vo.getMoney()); + String userId = ThreadLocalRequestDetail.getCustomUserInfo().getId(); + PlayCustomUserInfoEntity customUserInfo = customUserInfoService.selectById(userId); + if (new BigDecimal(vo.getMoney()).compareTo(customUserInfo.getAccountBalance()) > 0) { + throw new ServiceException("余额不足", 998); + } + String orderId = IdUtils.getUuid(); + // 记录订单信息 + playOrderInfoService.createOrderInfo(orderId, playOrderInfoService.getOrderNo(), "3", "2", "2", "0", "1", "", + "0", BigDecimal.ZERO, "", "", "0", new BigDecimal(vo.getMoney()), new BigDecimal(vo.getMoney()), + BigDecimal.ZERO, userId, vo.getClerkId(), vo.getWeiChatCode(), new ArrayList<>(), vo.getRemark(), "", + "", ""); + // 顾客减少余额 + customUserInfoService.updateAccountBalanceById(customUserInfo.getId(), customUserInfo.getAccountBalance(), + customUserInfo.getAccountBalance().subtract(new BigDecimal(vo.getMoney())), "1", "打赏", + new BigDecimal(vo.getMoney()), BigDecimal.ZERO, orderId); + return R.ok("成功"); + } + + /** + * 顾客下单-赠送礼物 + **/ + @ApiOperation(value = "赠送礼物", notes = "顾客向店员赠送礼物") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 998, message = "余额不足")}) + @CustomUserLogin + @PostMapping("/order/gift") + public R giftToOdder(@ApiParam(value = "礼物信息", required = true) @Validated @RequestBody PlayOrderInfoGiftAdd vo) { + String userId = ThreadLocalRequestDetail.getCustomUserInfo().getId(); + PlayGiftInfoEntity giftInfo = giftInfoService.selectPlayGiftInfoById(vo.getGiftId()); + PlayCustomUserInfoEntity customUserInfo = customUserInfoService.selectById(userId); + BigDecimal money = giftInfo.getPrice().multiply(new BigDecimal(vo.getGiftQuantity())); + if (money.compareTo(customUserInfo.getAccountBalance()) > 0) { + throw new ServiceException("余额不足", 998); + } + String orderId = IdUtils.getUuid(); + // 记录订单信息 + playOrderInfoService.createOrderInfo(orderId, playOrderInfoService.getOrderNo(), "3", "2", "2", "1", "1", + giftInfo.getId(), "0", giftInfo.getPrice(), "", giftInfo.getName(), + String.valueOf(vo.getGiftQuantity()), money, money, BigDecimal.ZERO, userId, vo.getClerkId(), + vo.getWeiChatCode(), new ArrayList<>(), vo.getRemark(), "", "", ""); + // 顾客减少余额 + customUserInfoService.updateAccountBalanceById(customUserInfo.getId(), customUserInfo.getAccountBalance(), + customUserInfo.getAccountBalance().subtract(money), "1", "赠送礼物", money, BigDecimal.ZERO, orderId); + // 陪聊增加余额 + // 修改顾客和礼物消息 + PlayCustomGiftInfoEntity customGiftInfoEntity = playCustomGiftInfoService + .selectByGiftIdAndCustomId(vo.getGiftId(), userId); + if (customGiftInfoEntity == null) { + customGiftInfoEntity = new PlayCustomGiftInfoEntity(); + customGiftInfoEntity.setGiffId(vo.getGiftId()); + customGiftInfoEntity.setCustomId(userId); + customGiftInfoEntity.setGiffNumber(1L); + playCustomGiftInfoService.save(customGiftInfoEntity); + } else { + customGiftInfoEntity.setGiffNumber(customGiftInfoEntity.getGiffNumber() + vo.getGiftQuantity()); + playCustomGiftInfoService.update(customGiftInfoEntity); + } + + // 修改陪玩和礼物数据 + PlayClerkGiftInfoEntity clerkGiftInfoEntity = playClerkGiftInfoService.selectByGiftIdAndClerkId(vo.getGiftId(), + vo.getClerkId()); + if (clerkGiftInfoEntity == null) { + clerkGiftInfoEntity = new PlayClerkGiftInfoEntity(); + clerkGiftInfoEntity.setGiffId(vo.getGiftId()); + clerkGiftInfoEntity.setClerkId(vo.getClerkId()); + clerkGiftInfoEntity.setGiffNumber(0L); + playClerkGiftInfoService.create(clerkGiftInfoEntity); + } else { + customGiftInfoEntity.setGiffNumber(customGiftInfoEntity.getGiffNumber() + vo.getGiftQuantity()); + playClerkGiftInfoService.update(clerkGiftInfoEntity); + } + + return R.ok("成功"); + } + + /** + * 新增指定订单 + * + * @param vo + * 指定订单查询对象 + * @return com.starry.common.result.R + * @author admin + * @since 2024/5/8 16:31 + **/ + @ApiOperation(value = "商品下单", notes = "顾客购买店员服务商品") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 998, message = "余额不足"), + @ApiResponse(code = 500, message = "请求参数异常")}) + @CustomUserLogin + @PostMapping("/order/commodity") + public R commodityToOrdder( + @ApiParam(value = "商品订单信息", required = true) @Validated @RequestBody PlayOrderInfoCommodityAdd vo) { + String customId = ThreadLocalRequestDetail.getCustomUserInfo().getId(); + PlayClerkUserInfoEntity clerkUserInfo = clerkUserInfoService.selectById(vo.getClerkId()); + + PlayCommodityInfoVo commodityInfo = playCommodityInfoService.queryCommodityInfo(vo.getCommodityId(), + clerkUserInfo.getLevelId()); + + BigDecimal couponMoney = BigDecimal.ZERO; + for (String couponId : vo.getCouponIds()) { + PlayCouponDetailsEntity couponDetailsEntity = couponDetailsService.getById(couponId); + if (Objects.isNull(couponDetailsEntity)) { + throw new CustomException("优惠券不存在"); + } + PlayCouponInfoEntity couponInfo = playCouponInfoService + .selectPlayCouponInfoById(couponDetailsEntity.getCouponId()); + String couponReasonForUnavailableUse = playCouponInfoService.getCouponReasonForUnavailableUse(couponInfo, + "0", vo.getCommodityId(), vo.getCommodityQuantity(), commodityInfo.getCommodityPrice()); + if (StrUtil.isNotBlank(couponReasonForUnavailableUse)) { + throw new CustomException("优惠券不可用"); + } + if (couponInfo.getDiscountType().equals("0")) { + couponMoney = couponMoney.add(couponInfo.getDiscountAmount()); + } + } + + PlayCustomUserInfoEntity customUserInfo = customUserInfoService.selectById(customId); + + BigDecimal money = commodityInfo.getCommodityPrice().multiply(new BigDecimal(vo.getCommodityQuantity())); + + money = money.subtract(couponMoney); + if (money.compareTo(BigDecimal.ZERO) < 1) { + money = BigDecimal.ZERO; + } + + if (money.compareTo(customUserInfo.getAccountBalance()) > 0) { + throw new ServiceException("余额不足", 998); + } + String orderId = IdUtils.getUuid(); + String orderNo = playOrderInfoService.getOrderNo(); + // 记录订单信息 + playOrderInfoService.createOrderInfo(orderId, orderNo, "0", "2", "0", "", "1", commodityInfo.getCommodityId(), + "1", commodityInfo.getCommodityPrice(), commodityInfo.getServiceDuration(), + commodityInfo.getCommodityName(), String.valueOf(vo.getCommodityQuantity()), money, money, + BigDecimal.ZERO, customId, clerkUserInfo.getId(), vo.getWeiChatCode(), vo.getCouponIds(), + vo.getRemark(), "", "", ""); + // 顾客减少余额 + customUserInfoService.updateAccountBalanceById(customUserInfo.getId(), customUserInfo.getAccountBalance(), + customUserInfo.getAccountBalance().subtract(money), "1", "下单-指定单", money, BigDecimal.ZERO, orderId); + // 发送通知给店员 + wxCustomMpService.sendCreateOrderMessage(clerkUserInfo.getTenantId(), clerkUserInfo.getOpenid(), orderNo, + money.toString(), commodityInfo.getCommodityName()); + return R.ok("成功"); + } + + /** + * 新增随机订单 + * + * @param vo + * 随机单创建对象 + * @return R + */ + @CustomUserLogin + @PostMapping("/order/random") + public R randomToOrdder(@Validated @RequestBody PlayOrderInfoRandomAdd vo) { + // 验证当前顾客余额是否充足 + String customId = ThreadLocalRequestDetail.getCustomUserInfo().getId(); + PlayCustomUserInfoEntity customUserInfo = customUserInfoService.selectById(customId); + PlayCommodityInfoVo commodityInfo = playCommodityInfoService.queryCommodityInfo(vo.getCommodityId(), + vo.getLevelId()); + BigDecimal money = commodityInfo.getCommodityPrice().multiply(new BigDecimal(vo.getCommodityQuantity())); + if (money.compareTo(customUserInfo.getAccountBalance()) > 0) { + throw new ServiceException("余额不足", 998); + } + String orderId = IdUtils.getUuid(); + // 记录订单信息 + playOrderInfoService.createOrderInfo(orderId, playOrderInfoService.getOrderNo(), "0", "2", "1", "", "1", + commodityInfo.getCommodityId(), "1", commodityInfo.getCommodityPrice(), + commodityInfo.getServiceDuration(), commodityInfo.getCommodityName(), + String.valueOf(vo.getCommodityQuantity()), money, money, BigDecimal.ZERO, customId, "", + vo.getWeiChatCode(), vo.getCouponIds(), vo.getRemark(), vo.getSex(), vo.getLevelId(), + vo.getExcludeHistory()); + // 顾客减少余额 + customUserInfoService.updateAccountBalanceById(customUserInfo.getId(), customUserInfo.getAccountBalance(), + customUserInfo.getAccountBalance().subtract(money), "1", "下单-随机单", money, BigDecimal.ZERO, orderId); + // 记录订单,指定指定未接单后,进行退款处理 + overdueOrderHandlerTask.enqueue(orderId + "_" + SecurityUtils.getTenantId()); + // 下单成功后,先根据用户条件进行随机分配 + return R.ok("下单成功"); + } + + /** + * 顾客分页查询本人订单列表 + * + * @param vo + * 订单列表分页查询对象 + * @return com.starry.common.result.R + * @author admin + * @since 2024/5/8 15:57 + **/ + @CustomUserLogin + @PostMapping("/order/queryByPage") + public R queryOrderByPage(@Validated @RequestBody PlayCustomOrderInfoQueryVo vo) { + vo.setPurchaserBy(ThreadLocalRequestDetail.getCustomUserInfo().getId()); + IPage iPage = playOrderInfoService.customSelectOrderInfoByPage(vo); + return R.ok(iPage); + } + + /** + * 顾客分页查询本人订单详细信息 + * + * @param id + * 订单ID + * @return com.starry.common.result.R + * @author admin + * @since 2024/5/8 15:57 + **/ + @CustomUserLogin + @GetMapping("/order/queryById") + public R queryById(@RequestParam("id") String id) { + PlayCustomOrderDetailsReturnVo vo = playOrderInfoService + .customSelectOrderDetails(ThreadLocalRequestDetail.getCustomUserInfo().getId(), id); + return R.ok(vo); + } + + /** + * 顾客-完成订单 + * + * @param id + * 订单ID + * @return com.starry.common.result.R + * @author admin + * @since 2024/5/8 15:57 + **/ + @CustomUserLogin + @GetMapping("/order/end") + public R endOrder(@RequestParam("id") String id) { + playOrderInfoService.updateStateTo23("0", ThreadLocalRequestDetail.getCustomUserInfo().getId(), "3", id); + return R.ok("成功"); + } + + /** + * 顾客取消订单 + * + * @param vo + * 订单取消对象 + * @return com.starry.common.result.R + * @author admin + * @since 2024/5/8 15:57 + **/ + @CustomUserLogin + @PostMapping("/order/cancellation") + public R cancellationOrder(@Validated @RequestBody PlayOrderCancellationVo vo) { + playOrderInfoService.updateStateTo4("0", ThreadLocalRequestDetail.getCustomUserInfo().getId(), vo.getOrderId(), + vo.getRefundReason(), vo.getImages()); + return R.ok("取消成功"); + } + + /** + * 新增订单评价信息 + * + * @param vo + * 订单评价信息实体 + * @return com.starry.common.result.R + * @author admin + * @since 2024/5/8 15:57 + **/ + @CustomUserLogin + @PostMapping("/order/evaluate/add") + public R addOrderEvaluate(@Validated @RequestBody PlayOrderEvaluateAddVo vo) { + vo.setCustomId(ThreadLocalRequestDetail.getCustomUserInfo().getId()); + PlayOrderInfoEntity orderInfo = playOrderInfoService.selectOrderInfoById(vo.getOrderId()); + if (!orderInfo.getPurchaserBy().equals(vo.getCustomId())) { + throw new CustomException("只有下单人才能评价"); + } + PlayOrderEvaluateInfoEntity entity = ConvertUtil.entityToVo(vo, PlayOrderEvaluateInfoEntity.class); + playOrderEvaluateInfoService.create(entity); + return R.ok("评价成功"); + } + + /** + * 根据订单ID查询当前顾客对当前人的评价 + * + * @param orderId + * 订单ID + * @return com.starry.common.result.R + * @author admin + * @since 2024/5/8 15:57 + **/ + @CustomUserLogin + @GetMapping("/order/evaluate/queryByOrderId") + public R addOrderEvaluateByOrderId(@RequestParam("id") String orderId) { + PlayOrderEvaluateInfoEntity orderEvaluateInfo = playOrderEvaluateInfoService + .queryCustomToOrderEvaluateInfo(ThreadLocalRequestDetail.getCustomUserInfo().getId(), orderId); + if (orderEvaluateInfo == null) { + throw new CustomException("当前订单未评价"); + } + return R.ok(ConvertUtil.entityToVo(orderEvaluateInfo, PlayCustomOrderEvaluateReturnVo.class)); + } + + /** + * 新增订单投诉信息 + * + * @param vo + * 订单评价信息实体 + * @return com.starry.common.result.R + * @author admin + * @since 2024/5/8 15:57 + **/ + @CustomUserLogin + @PostMapping("/order/complaint/add") + public R addOrderComplaint(@Validated @RequestBody PlayOrderComplaintAddVo vo) { + vo.setCustomId(ThreadLocalRequestDetail.getCustomUserInfo().getId()); + PlayOrderInfoEntity orderInfo = playOrderInfoService.selectOrderInfoById(vo.getOrderId()); + if (!orderInfo.getPurchaserBy().equals(vo.getCustomId())) { + throw new CustomException("只有下单人才能投诉"); + } + PlayOrderComplaintInfoEntity entity = ConvertUtil.entityToVo(vo, PlayOrderComplaintInfoEntity.class); + playOrderComplaintInfoService.create(entity); + return R.ok("新增成功"); + } + + /** + * 顾客新增留言 + * + * @param vo + * 顾客新增留言对象 + * @return com.starry.common.result.R + * @author admin + * @since 2024/5/8 15:57 + **/ + @CustomUserLogin + @PostMapping("/leave/add") + public R cancellationOrder(@Validated @RequestBody PlayCustomLeaveAddVo vo) { + vo.setCustomId(ThreadLocalRequestDetail.getCustomUserInfo().getId()); + PlayCustomLeaveMsgEntity entity = ConvertUtil.entityToVo(vo, PlayCustomLeaveMsgEntity.class); + entity.setMsgTime(new Date()); + playCustomLeaveMsgService.create(entity); + return R.ok("取消成功"); + } + + /** + * 查询当前顾客是否允许留言 + * + * @return com.starry.common.result.R + * @author admin + * @since 2024/5/8 15:57 + **/ + @CustomUserLogin + @GetMapping("/leave/queryPermission") + public R queryLeavePermission() { + // 不允许留言的原因,如果原因为空,说明允许留言 + String noMessagesAllowedReason = playCustomLeaveMsgService + .queryNoMessagesAllowedReason(ThreadLocalRequestDetail.getCustomUserInfo().getId()); + if (StringUtils.isEmpty(noMessagesAllowedReason)) { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("permission", true); + jsonObject.put("msg", ""); + return R.ok(jsonObject); + } else { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("permission", false); + jsonObject.put("msg", noMessagesAllowedReason); + return R.ok(jsonObject); + } + } + + /** + * 顾客修改对陪玩的关注状态 + * + * @param vo + * 陪玩的关注状态对象 + * @return com.starry.common.result.R + * @author admin + * @since 2024/5/8 15:57 + **/ + @CustomUserLogin + @PostMapping("/followState/update") + public R followStateUpdate(@Validated @RequestBody PlayClerkFollowStateUpdate vo) { + PlayClerkUserInfoEntity clerkUserInfo = clerkUserInfoService.selectById(vo.getClerkId()); + playCustomFollowInfoService.updateFollowState(ThreadLocalRequestDetail.getCustomUserInfo().getId(), + clerkUserInfo.getId(), vo.getFollowState()); + return R.ok("修改成功"); + } + + /** + * 顾客查询已关注陪聊列表 + * + * @param vo + * 陪玩的关注状态对象 + * @return com.starry.common.result.R + * @author admin + * @since 2024/5/8 15:57 + **/ + @CustomUserLogin + @PostMapping("/follow/queryByPage") + public R followQueryByPage(@Validated @RequestBody PlayClerkFollowQueryVo vo) { + vo.setCustomId(ThreadLocalRequestDetail.getCustomUserInfo().getId()); + IPage iPage = playCustomFollowInfoService.selectByPage(vo); + return R.ok(iPage); + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/controller/WxGiftController.java --- +package com.starry.admin.modules.weichat.controller; + +import cn.hutool.core.util.StrUtil; +import com.starry.admin.common.aspect.ClerkUserLogin; +import com.starry.admin.common.aspect.CustomUserLogin; +import com.starry.admin.common.conf.ThreadLocalRequestDetail; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.shop.service.IPlayGiftInfoService; +import com.starry.admin.modules.weichat.entity.PlayGiftInfoDto; +import com.starry.admin.modules.weichat.entity.gift.PlayClerkGiftReturnVo; +import com.starry.common.result.R; +import com.starry.common.utils.ConvertUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.util.List; +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author admin + */ +@Api(tags = "微信礼物接口", description = "微信端礼物相关接口") +@Slf4j +@RestController +@RequestMapping("/wx/gift/") +public class WxGiftController { + @Resource + private IPlayGiftInfoService giftInfoService; + + /** + * 顾客查询礼物列表 + * + * @return 礼物列表 + */ + @ApiOperation(value = "查询所有礼物", notes = "查询系统中所有礼物列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayGiftInfoDto.class, responseContainer = "List")}) + @GetMapping("/listByAll") + public R customListByAll() { + return R.ok(ConvertUtil.entityToVoList(giftInfoService.listByAll(), PlayGiftInfoDto.class)); + } + + /** + * 顾客查询礼物列表 + * + * @param obtained + * 店员获得礼物状态,[0:未获得,1:已获得] + * @return 礼物列表 + */ + @ApiOperation(value = "店员查询礼物", notes = "根据获得状态查询店员礼物列表") + @ApiImplicitParam(name = "obtained", value = "获得状态[0:未获得,1:已获得]", required = true, dataType = "String", paramType = "query", allowableValues = "0,1") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayClerkGiftReturnVo.class, responseContainer = "List"), + @ApiResponse(code = 500, message = "obtained参数异常")}) + @ClerkUserLogin + @GetMapping("/clerk/listByAll") + public R clerkListByAll(@RequestParam("obtained") String obtained) { + if (StrUtil.isBlankIfStr(obtained)) { + throw new CustomException("obtained参数异常"); + } + if (!"0".equals(obtained) && !"1".equals(obtained)) { + throw new CustomException("obtained参数异常"); + } + List list = giftInfoService + .clerkListByAll(ThreadLocalRequestDetail.getClerkUserInfo().getId(), obtained); + return R.ok(list); + } + + /** + * 顾客获取礼物图鉴信息 + * + * @param vo + * 顾客获得礼物查询对象 + * @return 礼物列表 + */ + @ApiOperation(value = "顾客查询礼物", notes = "根据获得状态查询顾客礼物列表") + @ApiImplicitParam(name = "obtained", value = "获得状态[0:未获得,1:已获得]", required = true, dataType = "String", paramType = "query", allowableValues = "0,1") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayClerkGiftReturnVo.class, responseContainer = "List"), + @ApiResponse(code = 500, message = "obtained参数异常")}) + @CustomUserLogin + @GetMapping("/custom/listByAll") + public R customListByAll(@RequestParam("obtained") String obtained) { + if (StrUtil.isBlankIfStr(obtained)) { + throw new CustomException("obtained参数异常"); + } + if (!"0".equals(obtained) && !"1".equals(obtained)) { + throw new CustomException("obtained参数异常"); + } + List list = giftInfoService + .customListByAll(ThreadLocalRequestDetail.getCustomUserInfo().getId(), obtained); + return R.ok(list); + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/controller/WxLevelController.java --- +package com.starry.admin.modules.weichat.controller; + +import com.starry.admin.common.aspect.CustomUserLogin; +import com.starry.admin.modules.custom.module.entity.PlayCustomLevelInfoEntity; +import com.starry.admin.modules.custom.service.IPlayCustomLevelInfoService; +import com.starry.admin.modules.weichat.entity.vo.PlayCustomLevelInfoReturnVo; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.util.ArrayList; +import java.util.List; +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author admin + */ +@Api(tags = "微信等级接口", description = "微信端用户等级相关接口") +@Slf4j +@RestController +@RequestMapping("/wx/level/") +public class WxLevelController { + + @Resource + private IPlayCustomLevelInfoService levelInfoService; + + /** + * 顾客查询登记列表 + */ + @ApiOperation(value = "查询等级列表", notes = "查询所有顾客等级列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayCustomLevelInfoReturnVo.class, responseContainer = "List")}) + @CustomUserLogin + @GetMapping("/custom/queryAll") + public R queryById() { + List list = levelInfoService.selectAll(); + List result = new ArrayList<>(); + for (PlayCustomLevelInfoEntity entity : list) { + PlayCustomLevelInfoReturnVo vo = new PlayCustomLevelInfoReturnVo(); + BeanUtils.copyProperties(entity, vo); + result.add(vo); + } + return R.ok(result); + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/controller/WxOauthController.java --- +package com.starry.admin.modules.weichat.controller; + +import static com.starry.common.constant.Constants.*; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson2.JSONObject; +import com.starry.admin.common.aspect.ClerkUserLogin; +import com.starry.admin.common.aspect.CustomUserLogin; +import com.starry.admin.common.conf.ThreadLocalRequestDetail; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity; +import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService; +import com.starry.admin.modules.custom.module.entity.PlayCustomUserInfoEntity; +import com.starry.admin.modules.custom.service.IPlayCustomUserInfoService; +import com.starry.admin.modules.weichat.entity.WxUserLoginVo; +import com.starry.admin.modules.weichat.entity.WxUserQueryAddressVo; +import com.starry.admin.modules.weichat.service.WxCustomMpService; +import com.starry.admin.modules.weichat.service.WxOauthService; +import com.starry.admin.modules.weichat.service.WxTokenService; +import com.starry.common.redis.RedisCache; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.util.Date; +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.bean.WxJsapiSignature; +import me.chanjar.weixin.common.error.WxErrorException; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 微信用户 + * + * @author admin + * @since 2019-03-25 15:39:39 + */ +@Api(tags = "微信授权接口", description = "微信端用户授权相关接口") +@Slf4j +@RestController +@RequestMapping("/wx/oauth2") +public class WxOauthController { + + @Resource + private WxCustomMpService wxCustomMpService; + @Resource + private IPlayCustomUserInfoService customUserInfoService; + @Resource + private IPlayClerkUserInfoService clerkUserInfoService; + @Resource + private WxTokenService tokenService; + @Resource + private WxOauthService wxOauthService; + @Resource + private RedisCache redisCache; + + @ApiOperation(value = "获取配置地址", notes = "获取微信JSAPI配置签名") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = WxJsapiSignature.class)}) + @PostMapping("/getConfigAddress") + public R getConfigAddress(@ApiParam(value = "地址查询信息", required = true) @RequestBody WxUserQueryAddressVo vo) + throws WxErrorException { + // 默认回调地址 + String defaultAddress = "https://julyharbor.com/api/wx/oauth2/clerkLoginCallback"; + if (!StrUtil.isBlankIfStr(vo.getUrl())) { + defaultAddress = vo.getUrl(); + } + WxJsapiSignature wxJsapiSignature = wxCustomMpService.proxyWxMpService().createJsapiSignature(defaultAddress); + return R.ok(wxJsapiSignature); + } + + @ApiOperation(value = "获取店员登录地址", notes = "获取微信店员授权登录地址") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = String.class)}) + @PostMapping("/getClerkLoginAddress") + public R getClerkLoginAddress(@ApiParam(value = "地址查询信息", required = true) @RequestBody WxUserQueryAddressVo vo) { + // 默认回调地址 + String defaultAddress = "https://julyharbor.com/api/wx/oauth2/clerkLoginCallback"; + if (!StrUtil.isBlankIfStr(vo.getUrl())) { + defaultAddress = vo.getUrl(); + } + String url = wxCustomMpService.proxyWxMpService().getOAuth2Service().buildAuthorizationUrl(defaultAddress, + "snsapi_userinfo", "STATE"); + return R.ok(url); + } + + @ApiOperation(value = "店员登录回调", notes = "微信店员授权登录回调处理") + @ApiImplicitParam(name = "code", value = "授权码", required = true, dataType = "String", paramType = "query") + @GetMapping("/clerkLoginCallback") + public void clerkLoginCallback(@RequestParam("code") String code) { + } + + @ApiOperation(value = "店员登录", notes = "微信店员授权登录") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = JSONObject.class), + @ApiResponse(code = 401, message = "登录失败"), @ApiResponse(code = 500, message = "用户不存在")}) + @PostMapping("/clerk/login") + public R clerkLogin(@ApiParam(value = "登录信息", required = true) @Validated @RequestBody WxUserLoginVo vo) { + try { + String userId = wxOauthService.clerkUserLogin(vo.getCode()); + PlayClerkUserInfoEntity entity = clerkUserInfoService.selectById(userId); + if (entity == null) { + throw new CustomException("用户不存在"); + } + // 缓存租户信息 + String redisKey = "TENANT_INFO:" + entity.getId(); + redisCache.setCacheObject(redisKey, entity.getTenantId()); + String tokenValue = tokenService.createWxUserToken(entity.getId()); + JSONObject jsonObject = JSONObject.from(clerkUserInfoService.getVo(entity)); + jsonObject.put("tokenValue", TOKEN_PREFIX + tokenValue); + jsonObject.put("tokenName", CLERK_USER_LOGIN_TOKEN); + jsonObject.put("loginDate", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss")); + jsonObject.put("pcData", clerkUserInfoService.getPcData(entity)); + clerkUserInfoService.updateTokenById(entity.getId(), tokenValue); + return R.ok(jsonObject); + } catch (Exception e) { + log.error("顾客登录失败,", e); + return R.unauthorized(); + } + } + + @ApiOperation(value = "店员开发登录", notes = "微信店员开发环境登录(固定用户)") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = JSONObject.class), + @ApiResponse(code = 401, message = "登录失败"), @ApiResponse(code = 500, message = "用户不存在")}) + @PostMapping("/clerk/login/dev") + public R clerkLoginDev(@ApiParam(value = "登录信息", required = true) @Validated @RequestBody WxUserLoginVo vo) { + try { + String userId = "a4471ef596a1"; + PlayClerkUserInfoEntity entity = clerkUserInfoService.selectById(userId); + if (entity == null) { + throw new CustomException("用户不存在"); + } + // 缓存租户信息 + String redisKey = "TENANT_INFO:" + entity.getId(); + redisCache.setCacheObject(redisKey, entity.getTenantId()); + String tokenValue = tokenService.createWxUserToken(entity.getId()); + JSONObject jsonObject = JSONObject.from(clerkUserInfoService.getVo(entity)); + jsonObject.put("tokenValue", TOKEN_PREFIX + tokenValue); + jsonObject.put("tokenName", CLERK_USER_LOGIN_TOKEN); + jsonObject.put("loginDate", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss")); + jsonObject.put("pcData", clerkUserInfoService.getPcData(entity)); + clerkUserInfoService.updateTokenById(entity.getId(), tokenValue); + return R.ok(jsonObject); + } catch (Exception e) { + log.error("顾客登录失败,", e); + return R.unauthorized(); + } + } + + @ApiOperation(value = "店员ID登录", notes = "根据店员ID直接登录") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = JSONObject.class), + @ApiResponse(code = 500, message = "用户不存在")}) + @PostMapping("/clerk/loginById") + public R loginById(@ApiParam(value = "登录信息", required = true) @Validated @RequestBody WxUserLoginVo vo) { + PlayClerkUserInfoEntity entity = clerkUserInfoService.selectById(vo.getCode()); + if (entity == null) { + throw new CustomException("用户不存在"); + } + // 缓存租户信息 + String redisKey = "TENANT_INFO:" + entity.getId(); + redisCache.setCacheObject(redisKey, entity.getTenantId()); + JSONObject jsonObject = JSONObject.from(clerkUserInfoService.getVo(entity)); + String tokenValue = tokenService.createWxUserToken(entity.getId()); + jsonObject.put("tokenValue", TOKEN_PREFIX + tokenValue); + jsonObject.put("tokenName", CLERK_USER_LOGIN_TOKEN); + jsonObject.put("loginDate", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss")); + clerkUserInfoService.updateTokenById(entity.getId(), tokenValue); + return R.ok(jsonObject); + } + + @ApiOperation(value = "店员登出", notes = "店员退出登录") + @ApiResponses({@ApiResponse(code = 200, message = "登出成功")}) + @ClerkUserLogin + @GetMapping("/clerk/logout") + public R clerkLogout() { + wxOauthService.clerkUserLogout(ThreadLocalRequestDetail.getClerkUserInfo()); + return R.ok("登出成功"); + } + + @ApiOperation(value = "获取顾客登录地址", notes = "获取微信顾客授权登录地址") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = String.class)}) + @PostMapping("/getCustomLoginAddress") + public R getCustomLoginAddress(@ApiParam(value = "地址查询信息", required = true) @RequestBody WxUserQueryAddressVo vo) { + // 默认回调地址 + String defaultAddress = "https://julyharbor.com/api/wx/oauth2/customLoginCallback"; + if (!StrUtil.isBlankIfStr(vo.getUrl())) { + defaultAddress = vo.getUrl(); + } + String url = wxCustomMpService.proxyWxMpService().getOAuth2Service().buildAuthorizationUrl(defaultAddress, + "snsapi_userinfo", "STATE"); + return R.ok(url); + } + + @ApiOperation(value = "顾客登录回调", notes = "微信顾客授权登录回调处理") + @ApiImplicitParam(name = "code", value = "授权码", required = true, dataType = "String", paramType = "query") + @GetMapping("/customLoginCallback") + public void customLoginCallback(@RequestParam("code") String code) { + + } + + @ApiOperation(value = "顾客登录", notes = "微信顾客授权登录") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = JSONObject.class), + @ApiResponse(code = 401, message = "登录失败"), @ApiResponse(code = 500, message = "用户不存在")}) + @PostMapping("/custom/login") + public R customLogin(@ApiParam(value = "登录信息", required = true) @Validated @RequestBody WxUserLoginVo vo) { + log.info("顾客登录接口调用,code = {}", vo.getCode()); + try { + String userId = wxOauthService.customUserLogin(vo.getCode()); + PlayCustomUserInfoEntity entity = customUserInfoService.selectById(userId); + if (entity == null) { + throw new CustomException("用户不存在"); + } + // 缓存租户信息 + String redisKey = "TENANT_INFO:" + entity.getId(); + redisCache.setCacheObject(redisKey, entity.getTenantId()); + JSONObject jsonObject = JSONObject.from(entity); + String tokenValue = tokenService.createWxUserToken(entity.getId()); + jsonObject.put("tokenValue", TOKEN_PREFIX + tokenValue); + jsonObject.put("tokenName", CUSTOM_USER_LOGIN_TOKEN); + jsonObject.put("loginDate", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss")); + customUserInfoService.updateTokenById(entity.getId(), tokenValue); + return R.ok(jsonObject); + } catch (Exception e) { + log.error("登录失败", e); + return R.unauthorized(); + } + } + + @ApiOperation(value = "顾客ID登录", notes = "根据顾客ID直接登录") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = JSONObject.class), + @ApiResponse(code = 500, message = "用户不存在")}) + @PostMapping("/custom/loginById") + public R loginById1(@ApiParam(value = "登录信息", required = true) @Validated @RequestBody WxUserLoginVo vo) { + PlayCustomUserInfoEntity entity = customUserInfoService.selectById(vo.getCode()); + if (entity == null) { + throw new CustomException("用户不存在"); + } + // 缓存租户信息 + String redisKey = "TENANT_INFO:" + entity.getId(); + redisCache.setCacheObject(redisKey, entity.getTenantId()); + JSONObject jsonObject = JSONObject.from(entity); + String tokenValue = tokenService.createWxUserToken(entity.getId()); + jsonObject.put("tokenValue", TOKEN_PREFIX + tokenValue); + jsonObject.put("tokenName", CLERK_USER_LOGIN_TOKEN); + jsonObject.put("loginDate", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss")); + customUserInfoService.updateTokenById(entity.getId(), tokenValue); + return R.ok(jsonObject); + } + + @ApiOperation(value = "顾客登出", notes = "顾客退出登录") + @ApiResponses({@ApiResponse(code = 200, message = "登出成功")}) + @GetMapping("/custom/logout") + @CustomUserLogin + public R customLogout() { + wxOauthService.customUserLogout(ThreadLocalRequestDetail.getCustomUserInfo()); + return R.ok("登出成功"); + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/controller/WxOrderInfoController.java --- +package com.starry.admin.modules.weichat.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.admin.common.aspect.ClerkUserLogin; +import com.starry.admin.common.aspect.CustomUserLogin; +import com.starry.admin.common.conf.ThreadLocalRequestDetail; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.order.module.entity.PlayOrderContinueInfoEntity; +import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity; +import com.starry.admin.modules.order.module.vo.PlayOrderContinueQueryVo; +import com.starry.admin.modules.order.module.vo.PlayOrderContinueReturnVo; +import com.starry.admin.modules.order.module.vo.PlayOrderDetailsReturnVo; +import com.starry.admin.modules.order.module.vo.PlayOrderReviewStateEditVo; +import com.starry.admin.modules.order.service.IPlayOrderContinueInfoService; +import com.starry.admin.modules.order.service.IPlayOrderInfoService; +import com.starry.admin.modules.weichat.entity.order.PlayOrderInfoContinueAdd; +import com.starry.admin.modules.weichat.entity.order.PlayOrderInfoContinueQueryVo; +import com.starry.admin.modules.weichat.entity.order.PlayOrderInfoRandomQueryVo; +import com.starry.admin.modules.weichat.entity.order.PlayRewardOrderQueryVo; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.time.LocalDateTime; +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 订单处理 + * + * @author admin + * @since 2024/5/25 下午2:45 + **/ +@Api(tags = "微信订单接口", description = "微信端订单相关接口") +@Slf4j +@RestController +@RequestMapping("/wx/order") +public class WxOrderInfoController { + + @Resource + private IPlayOrderInfoService playOrderInfoService; + + @Resource + private IPlayOrderContinueInfoService playOrderContinueInfoService; + + /** + * 续单申请-店员发起 + * + * @param vo + * 续单申请提交对象 + */ + @ApiOperation(value = "店员申请续单", notes = "店员为当前订单发起续单申请") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "非本人订单;无法续单"), + @ApiResponse(code = 500, message = "同一场订单只能续单一次")}) + @ClerkUserLogin + @PostMapping("/clerk/continue") + public R continueToOrdder( + @ApiParam(value = "续单信息", required = true) @Validated @RequestBody PlayOrderInfoContinueAdd vo) { + PlayOrderInfoEntity entity = playOrderInfoService.selectOrderInfoById(vo.getOrderId()); + if (!entity.getAcceptBy().equals(ThreadLocalRequestDetail.getClerkUserInfo().getId())) { + throw new CustomException("非本人订单;无法续单"); + } + + PlayOrderContinueInfoEntity orderContinueInfo = playOrderContinueInfoService.selectPlayOrderId(vo.getOrderId()); + if (orderContinueInfo != null) { + throw new CustomException("同一场订单只能续单一次"); + } + PlayOrderContinueInfoEntity orderContinueInfoEntity = new PlayOrderContinueInfoEntity(); + orderContinueInfoEntity.setOrderId(entity.getId()); + orderContinueInfoEntity.setOrderNo(entity.getOrderNo()); + orderContinueInfoEntity.setCustomId(entity.getPurchaserBy()); + orderContinueInfoEntity.setClerkId(entity.getAcceptBy()); + orderContinueInfoEntity.setPlaceType(entity.getPlaceType()); + orderContinueInfoEntity.setOrderMoney(entity.getOrderMoney()); + orderContinueInfoEntity.setFinalAmount(entity.getFinalAmount()); + orderContinueInfoEntity.setContinueMsg(entity.getRemark()); + orderContinueInfoEntity.setReviewedRequired("1"); + orderContinueInfoEntity.setReviewedState("0"); + orderContinueInfoEntity.setImages(vo.getImages()); + orderContinueInfoEntity.setContinueTime(LocalDateTime.now()); + playOrderContinueInfoService.create(orderContinueInfoEntity); + return R.ok("下单成功"); + } + + /** + * 店员查询随机单列表 + * + * @param vo + * 随机单列表查询对象 + * @return 订单列表 + */ + @ApiOperation(value = "查询随机单列表", notes = "店员查询可接的随机订单列表") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @ClerkUserLogin + @PostMapping("/clerk/selectRandomOrderByPage") + public R selectUnacceptedOrderByPage( + @ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayOrderInfoRandomQueryVo vo) { + return R.ok( + playOrderInfoService.selectRandomOrderByPage(vo, ThreadLocalRequestDetail.getClerkUserInfo().getId())); + } + + /** + * 店员查询随机单详情 + * + * @param id + * 订单ID + * @return 订单列表 + */ + @ApiOperation(value = "查询随机单详情", notes = "店员查询随机订单的详细信息") + @ApiImplicitParam(name = "id", value = "订单ID", required = true, dataType = "String", paramType = "query") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = PlayOrderDetailsReturnVo.class), + @ApiResponse(code = 500, message = "订单不存在")}) + @ClerkUserLogin + @GetMapping("/clerk/selectRandomOrderById") + public R selectUnacceptedOrderByPage(@RequestParam("id") String id) { + PlayOrderDetailsReturnVo vo = playOrderInfoService.selectById(id); + if (vo == null) { + throw new CustomException("订单不存在"); + } + return R.ok(vo); + } + + /** + * 店员查询打赏动态 + * + * @param vo + * 打赏动态查询列表 + * @return 打赏动态列表 + */ + @ApiOperation(value = "店员查询打赏动态", notes = "店员查询打赏订单动态") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @PostMapping("/clerk/selectRewardByPage") + public R clerkSelectRewardByPage( + @ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayRewardOrderQueryVo vo) { + return R.ok(playOrderInfoService.selectRewardByPage(vo)); + } + + /** + * 顾客查询最新打赏动态 + * + * @return 打赏动态列表 + */ + @ApiOperation(value = "顾客查询打赏动态", notes = "顾客查询最新打赏订单动态") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @GetMapping("/custom/selectRewardByPage") + public R customSelectReward() { + PlayRewardOrderQueryVo vo = new PlayRewardOrderQueryVo(); + return R.ok(playOrderInfoService.selectRewardByPage(vo)); + } + + /** + * 顾客-分页查询续单列表 + * + * @param vo + * PlayOrderInfoContinueQueryVo + * @return 续单历史 + */ + @ApiOperation(value = "查询续单列表", notes = "顾客分页查询续单申请列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayOrderContinueReturnVo.class, responseContainer = "Page")}) + @CustomUserLogin + @PostMapping("/custom/continueListByPage") + public R continueListByPage( + @ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayOrderInfoContinueQueryVo vo) { + PlayOrderContinueQueryVo queryVo = new PlayOrderContinueQueryVo(); + BeanUtils.copyProperties(vo, queryVo); + queryVo.setCustomId(ThreadLocalRequestDetail.getCustomUserInfo().getId()); + IPage page = playOrderContinueInfoService.selectPlayByPage(queryVo); + return R.ok(page); + } + + /** + * 审批续单申申请 + */ + @ApiOperation(value = "审批续单申请", notes = "顾客审批店员发起的续单申请") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "续单已处理")}) + @CustomUserLogin + @PostMapping("/custom/updateReviewState") + public R updateReviewState( + @ApiParam(value = "审批信息", required = true) @Validated @RequestBody PlayOrderReviewStateEditVo vo) { + PlayOrderContinueInfoEntity entity = playOrderContinueInfoService.selectPlayOrderContinueInfoById(vo.getId()); + if (!"0".equals(entity.getReviewedState())) { + throw new CustomException("续单已处理"); + } + playOrderContinueInfoService.updateReviewState(vo); + return R.ok("成功"); + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/controller/WxPersonnelGroupInfoController.java --- +package com.starry.admin.modules.weichat.controller; + +import com.starry.admin.common.aspect.ClerkUserLogin; +import com.starry.admin.modules.personnel.module.entity.PlayPersonnelGroupInfoEntity; +import com.starry.admin.modules.personnel.service.IPlayPersonnelGroupInfoService; +import com.starry.admin.modules.weichat.entity.PlayGroupWagesQueryVo; +import com.starry.admin.modules.weichat.entity.PlayGroupWagesReturnVo; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.util.ArrayList; +import java.util.List; +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 微信查询组长工资 + * + * @author admin + * @since 2024/7/6 下午3:46 + **/ +@Api(tags = "微信分组管理", description = "微信端店员分组相关接口") +@Slf4j +@RestController +@RequestMapping("/wx/group") +public class WxPersonnelGroupInfoController { + + @Resource + private IPlayPersonnelGroupInfoService playClerkGroupInfoService; + + /** + * 查询组长公工资 + */ + @ApiOperation(value = "查询分组工资", notes = "获取所有店员分组的工资信息") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayGroupWagesReturnVo.class, responseContainer = "List")}) + @ClerkUserLogin + @PostMapping("/wages/listAll") + public R listGroupWagesAll( + @ApiParam(value = "查询条件", required = true) @Validated @RequestBody PlayGroupWagesQueryVo vo) { + List list = playClerkGroupInfoService.selectAll(); + List data = new ArrayList<>(); + for (PlayPersonnelGroupInfoEntity entity : list) { + PlayGroupWagesReturnVo bean = new PlayGroupWagesReturnVo(); + bean.setGroupName(entity.getGroupName()); + data.add(bean); + } + return R.ok(data); + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/controller/WxPlayController.java --- +package com.starry.admin.modules.weichat.controller; + +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson2.JSONArray; +import com.alibaba.fastjson2.JSONObject; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse; +import com.github.binarywang.wxpay.bean.profitsharing.ProfitSharingReceiverRequest; +import com.github.binarywang.wxpay.bean.profitsharing.ProfitSharingReceiverResult; +import com.github.binarywang.wxpay.bean.profitsharing.ProfitSharingRequest; +import com.github.binarywang.wxpay.bean.profitsharing.ProfitSharingResult; +import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest; +import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult; +import com.github.binarywang.wxpay.exception.WxPayException; +import com.github.binarywang.wxpay.service.WxPayService; +import com.github.binarywang.wxpay.util.SignUtils; +import com.starry.admin.common.aspect.CustomUserLogin; +import com.starry.admin.common.conf.ThreadLocalRequestDetail; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.custom.module.entity.PlayCustomUserInfoEntity; +import com.starry.admin.modules.custom.service.IPlayCustomUserInfoService; +import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity; +import com.starry.admin.modules.order.service.IPlayOrderInfoService; +import com.starry.admin.modules.order.service.impl.PlayOrderInfoServiceImpl; +import com.starry.admin.modules.system.module.entity.SysTenantEntity; +import com.starry.admin.modules.system.service.impl.SysTenantServiceImpl; +import com.starry.admin.modules.weichat.service.WxCustomMpService; +import com.starry.admin.utils.SecurityUtils; +import com.starry.common.result.R; +import com.starry.common.utils.StringUtils; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import org.dom4j.Document; +import org.dom4j.DocumentHelper; +import org.dom4j.Element; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author admin + */ +@Api(tags = "微信支付接口", description = "微信端支付相关接口") +@Slf4j +@RestController +@RequestMapping("/wx/pay/") +public class WxPlayController { + + @Resource + private SysTenantServiceImpl tenantService; + @Resource + private IPlayCustomUserInfoService customUserInfoService; + @Resource + private IPlayOrderInfoService orderInfoService; + + @Resource + PlayOrderInfoServiceImpl playOrderInfoService; + @Resource + private WxCustomMpService mpService; + + /** + * 微信支付-微信回调地址(https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_7&index=8) + * + * @author admin + * @since 2024/5/8 11:25 + **/ + @ApiOperation(value = "微信支付回调", notes = "微信支付后的回调接口") + @ApiResponses({@ApiResponse(code = 200, message = "成功")}) + @RequestMapping("/jsCallback") + public String wxPayNotify(HttpServletRequest request) { + try (InputStream inStream = request.getInputStream(); + ByteArrayOutputStream outSteam = new ByteArrayOutputStream()) { + byte[] buffer = new byte[1024]; + int len; + while ((len = inStream.read(buffer)) != -1) { + outSteam.write(buffer, 0, len); + } + log.info("微信支付回调开始-参数解析-开始"); + // 获取微信调用我们notify_url的返回信息 + String result = outSteam.toString("utf-8"); + log.info("微信支付回调开始-参数解析-结束,result={}", result); + this.dealNotify(result); + } catch (Exception e) { + log.error("微信支付回调业务处理异常", e); + } + return WxPayNotifyResponse.success("成功"); + } + + public void dealNotify(String xmlData) { + try { + Map orderMap = readStringXmlOut(xmlData); + String outTradeNo = orderMap.get("out_trade_no"); + String tenantId = orderMap.get("attach"); + if (StrUtil.isBlank(tenantId)) { + log.error("支付对应业务处理异常-未查询到租户信息,xmlData={}", xmlData); + } + SecurityUtils.setTenantId(tenantId); + PlayOrderInfoEntity orderInfoEntity = orderInfoService.queryByOrderNo(outTradeNo); + if (Objects.isNull(orderInfoEntity)) { + log.error("支付对应业务处理异常-未查询到对应的支付记录,xmlData={}", xmlData); + return; + } + // TODO如果订单不是支付订单,并且支付状态不为未支付 + if (!"0".equals(orderInfoEntity.getOrderType()) || !"0".equals(orderInfoEntity.getPayState())) { + log.error("支付对应业务处理异常-支付记录状态异常,支付记录:xmlData={}", xmlData); + return; + } + // 修养订单状态 + orderInfoEntity.setPayState("1"); + orderInfoService.updateById(orderInfoEntity); + // 修改账户余额 + customUserInfoService.customAccountBalanceRecharge(orderInfoEntity.getOrderMoney(), + orderInfoEntity.getPurchaserBy(), orderInfoEntity.getId()); + log.info("*********支付处理完成"); + // 推送通知 + mpService.sendBalanceMessage(orderInfoEntity); + // 请求分账 + WxPayService wxPayService = mpService.getWxPay(); + this.profitSharing(wxPayService, orderMap, orderInfoEntity, + tenantService.selectSysTenantByTenantId(orderInfoEntity.getTenantId())); + } catch (Exception e) { + log.error("订单回调业务处理异常,xmlData={}", xmlData); + } + } + + @ApiOperation(value = "测试消息推送", notes = "测试充值消息推送功能") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @GetMapping("/test") + public R test() { + PlayOrderInfoEntity orderInfo = playOrderInfoService.getById("0e3e7d7ec69a"); + mpService.sendBalanceMessage(orderInfo); + return R.ok(true); + } + + @ApiOperation(value = "获取支付金额", notes = "根据充值金额获取实际支付金额") + @ApiImplicitParam(name = "money", value = "充值金额", required = true, dataType = "String", paramType = "query") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "请求参数错误,money不能为空")}) + @CustomUserLogin + @GetMapping("/custom/getCustomPaymentAmount") + public R getCustomPaymentAmount(@RequestParam("money") String money) { + if (StringUtils.isEmpty(money)) { + throw new CustomException("请求参数错误,money不能为空"); + } + BigDecimal paymentAmount = customUserInfoService.getCustomPaymentAmount(new BigDecimal(money), + ThreadLocalRequestDetail.getCustomUserInfo().getId()); + return R.ok(paymentAmount); + } + + @ApiOperation(value = "创建充值订单", notes = "创建微信支付充值订单") + @ApiImplicitParam(name = "money", value = "充值金额", required = true, dataType = "String", paramType = "query") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "请求参数错误,money不能为空"), + @ApiResponse(code = 500, message = "充值金额不能小于10元"), @ApiResponse(code = 500, message = "系统错误,租户ID获取失败")}) + @CustomUserLogin + @GetMapping("/custom/createOrder") + public R createOrder(@RequestParam("money") String money) { + if (StringUtils.isEmpty(money)) { + throw new CustomException("请求参数错误,money不能为空"); + } + if (new BigDecimal(money).compareTo(new BigDecimal("10")) < 0) { + throw new CustomException("充值金额不能小于10元"); + } + String tenantId = SecurityUtils.getTenantId(); + if (StrUtil.isBlankIfStr(tenantId)) { + throw new CustomException("系统错误,租户ID获取失败"); + } + // 用户信息 + PlayCustomUserInfoEntity customUserInfo = customUserInfoService + .selectById(ThreadLocalRequestDetail.getCustomUserInfo().getId()); + // 租户信息 + SysTenantEntity tenant = tenantService.selectSysTenantByTenantId(tenantId); + Boolean profitSharing = tenant.getProfitsharingRate() > 0; + // 订单总金额,单位为分 + long totalFee = getTotalFee(money); + // 创建订单信息 + String orderNo = playOrderInfoService.getOrderNo(); + orderInfoService.createRechargeOrder(orderNo, new BigDecimal(totalFee * 1.0 / 100), + new BigDecimal(totalFee * 1.0 / 100), customUserInfo.getId()); + + WxPayService wxPayService = mpService.getWxPay(); + WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest(); + request.setOpenid(customUserInfo.getOpenid()); + // 订单总金额,单位为分(开发阶段固定设置为支付1分钱) + request.setAttach(tenantId); + request.setTotalFee((int) totalFee); + request.setOutTradeNo(orderNo); + request.setTradeType("JSAPI"); + request.setSpbillCreateIp("101.43.206.16"); + request.setNotifyUrl(wxPayService.getConfig().getNotifyUrl()); + request.setBody("船票充值"); + if (profitSharing) { + // 添加分账方 + this.profitSharingAddreceiver(wxPayService); + request.setProfitSharing("Y"); + } + + WxPayUnifiedOrderResult orderResult; + try { + // 统一下单,商户系统先调用该接口在微信支付服务后台生成预支付交易单,返回正确的预支付交易会话标识后再在APP里面调起支付 + orderResult = wxPayService.unifiedOrder(request); + } catch (WxPayException e) { + throw new RuntimeException(e); + } + // + String prepayId = orderResult.getPrepayId(); + // 组合参数构建支付 + Map paySignInfo = new HashMap<>(5); + String timeStamp = String.valueOf(System.currentTimeMillis()); + String nonceStr = "dalfhh241lnandnsklajax"; + paySignInfo.put("appId", wxPayService.getConfig().getAppId()); + paySignInfo.put("nonceStr", nonceStr); + paySignInfo.put("timeStamp", timeStamp); + paySignInfo.put("signType", "MD5"); + paySignInfo.put("package", "prepay_id=" + prepayId); + String[] signInfo = new String[0]; + String paySign = SignUtils.createSign(paySignInfo, "MD5", wxPayService.getConfig().getMchKey(), signInfo); + + // 组合支付参数 + JSONObject jsonObject = new JSONObject().fluentPut("appId", wxPayService.getConfig().getAppId()) + .fluentPut("timeStamp", timeStamp).fluentPut("nonceStr", nonceStr) + .fluentPut("package", "prepay_id=" + prepayId).fluentPut("signType", "MD5") + .fluentPut("paySign", paySign); + return R.ok(jsonObject); + } + + private void profitSharingAddreceiver(WxPayService wxPayService) { + ProfitSharingReceiverRequest request = new ProfitSharingReceiverRequest(); + request.setAppid(wxPayService.getConfig().getAppId()); + request.setMchId(wxPayService.getConfig().getMchId()); + String nonceStr = "dalfhh241lnandnsklajax"; + request.setNonceStr(nonceStr); + request.setSignType("HMAC-SHA256"); + request.setReceiver(new JSONObject().fluentPut("type", "MERCHANT_ID").fluentPut("account", "1681470208") + .fluentPut("name", "合肥经济技术开发区陪陪信息技术服务部(个体工商户)").fluentPut("relation_type", "SERVICE_PROVIDER") + .toString()); + try { + ProfitSharingReceiverResult result = wxPayService.getProfitSharingService().addReceiver(request); + log.info("请求添加分账结果:" + JSONObject.toJSONString(result)); + } catch (WxPayException e) { + throw new RuntimeException(e); + } + + } + + /** + * @param money + * 金额,单位-元 + * @return 金额, 单位-分 + */ + public long getTotalFee(String money) { + long totalFee; + try { + totalFee = (long) (Float.parseFloat(money) * 100); + } catch (Exception e) { + throw new CustomException("请求参数错误,money类型异常"); + } + if (totalFee <= 0 || totalFee > 1000000) { + throw new CustomException("请求参数错误,单笔支付金额必须大于0,且小于10000"); + } + return totalFee; + } + + public static Map readStringXmlOut(String xml) { + Map map = new HashMap(); + Document doc; + try { + doc = DocumentHelper.parseText(xml); // 将字符串转为XML + Element rootElt = doc.getRootElement(); // 获取根节点 + List list = rootElt.elements();// 获取根节点下所有节点 + for (Element element : list) { // 遍历节点 + map.put(element.getName(), element.getText()); // 节点的name为map的key,text为map的value + } + } catch (Exception e) { + throw new RuntimeException(e); + } + return map; + } + + private void profitSharing(WxPayService wxPayService, Map orderMap, + PlayOrderInfoEntity orderInfoEntity, SysTenantEntity tenant) throws WxPayException { + Boolean profitSharing = tenant.getProfitsharingRate() > 0; + if (!profitSharing) { + return; + } + log.info("开始进行分账。。。。。。。。。。。。。。。"); + long totalFee = getTotalFee(orderInfoEntity.getOrderMoney().toString()); + int amount = new BigDecimal(totalFee).multiply(BigDecimal.valueOf((double) tenant.getProfitsharingRate() / 100)) + .intValue(); + if (amount == 0) { + return; + } + ProfitSharingRequest request = new ProfitSharingRequest(); + request.setSignType("HMAC-SHA256"); + request.setTransactionId(orderMap.get("transaction_id")); + request.setOutOrderNo("ps" + orderMap.get("out_trade_no")); + + request.setReceivers(new JSONArray().fluentAdd( + new JSONObject().fluentPut("type", "MERCHANT_ID").fluentPut("name", "合肥经济技术开发区陪陪信息技术服务部(个体工商户)") + .fluentPut("account", "1681470208").fluentPut("amount", amount)) + .toString()); + ProfitSharingResult result = wxPayService.getProfitSharingService().profitSharing(request); + log.info("分账结果:" + JSONObject.toJSONString(result)); + // 保存分账金额 + BigDecimal profitSharingAmount = new BigDecimal(amount).divide(new BigDecimal(100)); + orderInfoService.update(null, + Wrappers.lambdaUpdate(PlayOrderInfoEntity.class).eq(PlayOrderInfoEntity::getId, orderInfoEntity.getId()) + .set(PlayOrderInfoEntity::getProfitSharingAmount, profitSharingAmount)); + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/controller/WxPlayOrderRankingController.java --- +package com.starry.admin.modules.weichat.controller; + +import com.starry.admin.common.aspect.ClerkUserLogin; +import com.starry.admin.common.conf.ThreadLocalRequestDetail; +import com.starry.admin.modules.clerk.service.IPlayClerkRankingInfoService; +import com.starry.admin.modules.weichat.entity.order.PlayOrderHistoryRankingReturnVo; +import com.starry.admin.modules.weichat.entity.order.PlayOrderRankingReturnVo; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.util.List; +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author admin + * @since 2024/5/25 下午10:25 + **/ +@Api(tags = "微信订单排行接口", description = "微信端订单排行相关接口") +@Slf4j +@RestController +@RequestMapping("/wx/orderRanking") +public class WxPlayOrderRankingController { + + @Resource + private IPlayClerkRankingInfoService playClerkRankingInfoService; + + /** + * 查询当前排行 + */ + @ApiOperation(value = "查询当前排行", notes = "查询店员当前排行榜信息") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = PlayOrderRankingReturnVo.class)}) + @ClerkUserLogin + @GetMapping("/clerk/selectCurrentRanking") + public R selectCurrentRanking() { + PlayOrderRankingReturnVo result = playClerkRankingInfoService + .selectCurrentRanking(ThreadLocalRequestDetail.getClerkUserInfo().getId()); + return R.ok(result); + + } + + /** + * 查询历史排行 + */ + @ApiOperation(value = "查询历史排行", notes = "查询店员历史排行榜信息") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayOrderHistoryRankingReturnVo.class, responseContainer = "List")}) + @ClerkUserLogin + @GetMapping("/clerk/selectHistoryRanking") + public R selectHistoryRanking() { + List result = playClerkRankingInfoService + .selectHistoryRanking(ThreadLocalRequestDetail.getClerkUserInfo().getId()); + return R.ok(result); + + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/controller/WxShopController.java --- +package com.starry.admin.modules.weichat.controller; + +import com.starry.admin.common.aspect.ClerkUserLogin; +import com.starry.admin.modules.shop.module.entity.PlayShopArticleInfoEntity; +import com.starry.admin.modules.shop.module.entity.PlayShopCarouselInfoEntity; +import com.starry.admin.modules.shop.service.IPlayShopArticleInfoService; +import com.starry.admin.modules.shop.service.IPlayShopCarouselInfoService; +import com.starry.admin.modules.weichat.entity.PlayShopReadArticleVo; +import com.starry.admin.modules.weichat.entity.shop.ShopHomeCarouseInfoReturnVo; +import com.starry.common.result.R; +import com.starry.common.utils.ConvertUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.util.List; +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 店铺接口 + * + * @author admin + * @since 2024/5/20 下午11:19 + **/ +@Api(tags = "微信店铺接口", description = "微信端店铺相关接口") +@Slf4j +@RestController +@RequestMapping("/wx/shop") +public class WxShopController { + + @Resource + private IPlayShopCarouselInfoService playShopCarouselInfoService; + + @Resource + IPlayShopArticleInfoService playShopArticleInfoService; + + /** + * 获取首页轮播图 + */ + @ApiOperation(value = "获取首页轮播图", notes = "获取店铺首页轮播图信息") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = ShopHomeCarouseInfoReturnVo.class, responseContainer = "List")}) + @GetMapping(value = "custom/getShopHomeCarouseInfo") + public R getShopHomeCarouseInfo() { + List entities = playShopCarouselInfoService.selectHomeCarouselInfo(); + return R.ok(ConvertUtil.entityToVoList(entities, ShopHomeCarouseInfoReturnVo.class)); + } + + /** + * 获取店铺文章列表 + */ + @ApiOperation(value = "获取文章列表", notes = "获取店铺所有文章列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = PlayShopArticleInfoEntity.class, responseContainer = "List")}) + @ClerkUserLogin + @GetMapping(value = "clerk/getArticleList") + public R getArticleList() { + return R.ok(playShopArticleInfoService.selectByList()); + } + + /** + * 阅读店铺文章 + */ + @ApiOperation(value = "阅读文章", notes = "阅读店铺文章并增加访问次数") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @ClerkUserLogin + @GetMapping(value = "clerk/readShopArticleInfo") + public R readShopArticleInfo(@ApiParam(value = "文章参数", required = true) @RequestBody PlayShopReadArticleVo vo) { + PlayShopArticleInfoEntity entity = playShopArticleInfoService.selectById(vo.getId()); + entity.setVisitsNumber(entity.getVisitsNumber() + 1); + playShopArticleInfoService.update(entity); + return R.ok("成功"); + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/controller/WxSmsController.java --- +package com.starry.admin.modules.weichat.controller; + +import com.starry.admin.utils.SmsUtils; +import com.starry.common.result.R; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +/** + * 动态接口 + * + * @author admin + * @since 2024/5/20 下午11:19 + **/ +@Api(tags = "微信短信接口", description = "微信端短信发送相关接口") +@Slf4j +@RestController +@RequestMapping("/wx/sms") +public class WxSmsController { + @Resource + private SmsUtils smsUtils; + + @ApiOperation(value = "发送短信", notes = "向指定手机号发送短信验证码") + @ApiImplicitParam(name = "phone", value = "手机号码", required = true, dataType = "String", paramType = "query") + @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @GetMapping("/send") + public R sendSms(@RequestParam("phone") String phone) { + smsUtils.sendSmsApi(phone); + return R.ok(); + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/PlayClerkCommodityTreeData.java --- +package com.starry.admin.modules.weichat.entity; + +import com.starry.admin.modules.clerk.module.entity.PlayClerkCommodityEntity; +import com.starry.common.utils.ConvertUtil; +import java.math.BigDecimal; +import java.util.List; +import lombok.Data; + +/** + * 店员商品树状数据 + * + * @author admin + */ +@Data +public class PlayClerkCommodityTreeData { + + private String commodityType; + + private List value; + + public PlayClerkCommodityTreeData(String commodityType, List value) { + this.commodityType = commodityType; + this.value = ConvertUtil.entityToVoList(value, ClerkCommodityInfo.class); + } + + @Data + public static class ClerkCommodityInfo { + + private String id; + + private String commodityName; + + private BigDecimal commodityPrice; + + private String serviceDuration; + + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/PlayClerkFollowQueryVo.java --- +package com.starry.admin.modules.weichat.entity; + +import com.starry.common.domain.BasePageEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 顾客查询已关注陪聊接口 + * + * @author admin + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class PlayClerkFollowQueryVo extends BasePageEntity { + + private String customId; + + /** + * 关注状态[0:未关注,1:已关注] + */ + private String followState = "1"; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/PlayClerkFollowReturnVo.java --- +package com.starry.admin.modules.weichat.entity; + +import lombok.Data; + +/** + * 顾客查询已关注陪聊接口 + * + * @author admin + */ +@Data +public class PlayClerkFollowReturnVo { + + private String id; + /** + * 顾客ID + * + * @since 2024/5/10 10:39 + **/ + private String customId; + /** + * 店员ID + */ + private String clerkId; + + /** + * 店员昵称 + */ + private String nickname; + + /** + * 店员头像 + */ + private String avatar; + + /** + * 关注状态[0:未关注,1:已关注] + */ + private String followState; + + /** + * 在线状态【1:在线,0:离线】 + */ + private String onlineState; + + /** + * 最低消费 + */ + private String latestConsumption = "最低1船票"; + + /** + * 个性签名 + */ + private String signature; + + /** + * 性别[0:未知;1:男;2:女] + */ + private String sex; + + /** + * 年龄 + */ + private Integer age; + + /** + * 关注人数 + * + * @since 2024/5/10 10:42 + **/ + private Integer followNumber; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/PlayClerkFollowStateUpdate.java --- +package com.starry.admin.modules.weichat.entity; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Pattern; +import lombok.Data; + +/** + * 店员和陪聊关注状态 + * + * @author admin + */ +@Data +public class PlayClerkFollowStateUpdate { + + /** + * 店员用户ID + */ + @NotBlank(message = "打赏对象不能为空") + private String clerkId; + + @NotBlank(message = "关注状态不能为空") + @Pattern(regexp = "[01]", message = "关注状态必须为0或者1") + private String followState; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/PlayClerkUserAlbumVo.java --- +package com.starry.admin.modules.weichat.entity; + +import java.util.List; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import lombok.Data; + +/** + * 店员相册实体 + * + * @author admin + * @since 2024/4/11 11:19 + **/ + +@Data +public class PlayClerkUserAlbumVo { + + @NotNull(message = "照片不能为空") + @Size(min = 1, max = 5, message = "照片必须为1-5张") + private List album; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/PlayClerkUserAudioVo.java --- +package com.starry.admin.modules.weichat.entity; + +import javax.validation.constraints.NotNull; +import lombok.Data; + +/** + * 店员录音文件 + * + * @author admin + * @since 2024/4/11 11:19 + **/ +@Data +public class PlayClerkUserAudioVo { + + /** + * 录音 + */ + @NotNull(message = "录音文件不能为空") + private String audio; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/PlayClerkUserAvatarVo.java --- +package com.starry.admin.modules.weichat.entity; + +import javax.validation.constraints.NotNull; +import lombok.Data; + +/** + * 店员头像信息 + * + * @author admin + * @since 2024/4/11 11:19 + **/ +@Data +public class PlayClerkUserAvatarVo { + + /** + * 头像 + */ + @NotNull(message = "头像不能为空") + private String avatar; + + /** + * 头像框 + */ + private String avatarFrameId; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/PlayClerkUserBindCodeVo.java --- +package com.starry.admin.modules.weichat.entity; + +import javax.validation.constraints.NotBlank; +import lombok.Data; + +/** + * @author admin + */ +@Data +public class PlayClerkUserBindCodeVo { + + /** + * 手机号码区号 + */ + @NotBlank(message = "手机号码区号不能为空") + private String areaCode; + + /** + * 手机号码 + */ + @NotBlank(message = "手机号码不能为空") + private String phone; + + /** + * 手机号码 + */ + @NotBlank(message = "验证码不能为空") + private String code; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/PlayClerkUserByWxAddVo.java --- +package com.starry.admin.modules.weichat.entity; + +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import lombok.Data; + +/** + * 微信端申请成为店员 + * + * @author admin + */ +@Data +public class PlayClerkUserByWxAddVo { + + /** + * 店员昵称 + */ + @NotBlank(message = "昵称不能为空") + private String nickname; + + /** + * 店员性别(0:未知;1:男;2:女) + */ + @NotNull(message = "性别不能为空") + private String sex; + + /** + * 年龄 + */ + @NotNull(message = "性别不能为空") + private Integer age; + + /** + * 微信号码 + */ + @NotNull(message = "微信号码不能为空") + private String weiChatCode; + + /** + * 手机号码区号 + */ + @NotBlank(message = "手机号码区号不能为空") + private String areaCode; + + /** + * 手机号码 + */ + @NotBlank(message = "手机号码不能为空") + private String phone; + + /** + * 所在国家 + */ + private String country = "中国"; + + /** + * 所在省份 + */ + @NotBlank(message = "省份不能为空") + private String province; + + /** + * 所在城市 + */ + @NotBlank(message = "城市不能为空") + private String city; + + /** + * 音频 + */ + @NotBlank(message = "音频不能为空") + private String audio; + + @NotNull(message = "album不能为空") + @Size(min = 1, max = 5, message = "照片必须为1-5张") + private List album; + + /** + * 个性签名 + */ + private String signature; + + /** + * 备注 + */ + private String remark; + + private String smsCode; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/PlayClerkUserByWxEditVo.java --- +package com.starry.admin.modules.weichat.entity; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +/** + * 微信端申请成为店员 + * + * @author admin + */ +@Data +public class PlayClerkUserByWxEditVo { + + /** + * 店员昵称 + */ + @NotBlank(message = "昵称不能为空") + private String nickname; + + /** + * 店员性别(0:未知;1:男;2:女) + */ + @NotNull(message = "性别不能为空") + private Integer sex; + + /** + * 年龄 + */ + @NotNull(message = "性别不能为空") + private Integer age; + + /** + * 微信号码 + */ + @NotNull(message = "微信号码不能为空") + private Integer weiChatCode; + + /** + * 手机号码区号 + */ + @NotBlank(message = "手机号码区号不能为空") + private String areaCode; + + /** + * 手机号码 + */ + @NotBlank(message = "手机号码不能为空") + private String phone; + + /** + * 所在国家 + */ + private String country = "中国"; + + /** + * 所在省份 + */ + @NotBlank(message = "省份不能为空") + private String province; + + /** + * 所在城市 + */ + @NotBlank(message = "城市不能为空") + private String city; + + /** + * 音频 + */ + @NotBlank(message = "音频不能为空") + private String audioFrequency; + + /** + * 图片1 + **/ + private String image1; + + /** + * 图片2 + **/ + private String image2; + + /** + * 图片3 + **/ + private String image3; + + /** + * 图片4 + **/ + private String image4; + + /** + * 图片4 + **/ + private String image5; + + /** + * 微信二维码 + **/ + private String weChatCodeImage; + + /** + * 支付宝收款码图片 + **/ + private String weChatPayImage; + + /** + * 支付宝收款码图片 + **/ + private String alipayImage; + + /** + * 备注 + */ + private String remark; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/PlayClerkUserLoginResponseVo.java --- +package com.starry.admin.modules.weichat.entity; + +import com.alibaba.fastjson2.JSONObject; +import com.starry.admin.modules.clerk.module.entity.PlayClerkLevelInfoEntity; +import com.starry.admin.modules.clerk.module.vo.PlayClerkCommodityQueryVo; +import java.util.ArrayList; +import java.util.List; +import lombok.Data; + +/** + * 微信端店员登录返回值 + * + * @author admin + */ +@Data +public class PlayClerkUserLoginResponseVo { + + /** + * UUID + */ + private String id; + + /** + * 店员昵称 + */ + private String nickname; + + /** + * 头像 + */ + private String avatar; + + /** + * 头像是否可编辑 + */ + private boolean avatarAllowEdit = true; + + /** + * 相册 + */ + private List album = new ArrayList<>(); + + /** + * 相册是否运行编辑 + */ + private boolean albumAllowEdit = true; + + /** + * 音频 + */ + private String audio; + + /** + * 音频是否可修改 + */ + private boolean audioAllowEdit = true; + + /** + * 店员性别(0:未知;1:男;2:女) + */ + private String sex; + + /** + * 年龄 + */ + private Integer age; + + /** + * 个性签名 + */ + private String signature; + + /** + * 星座 + */ + private String constellation; + + /** + * 地区 + */ + private String area; + + /** + * 标签 + */ + private List label = new ArrayList<>(); + + /** + * 分类 + */ + private String typeId; + + /** + * 微信二维码 + **/ + private String weChatCodeImage; + + /** + * 微信收款码图片 + **/ + private String weChatPayImage; + + /** + * 支付宝收款码图片 + **/ + private String alipayImage; + + /** + * 是否必须实名【0:非必须实名;1:必须实名;2:跟随店铺设置】 + */ + private String mandatoryRealState; + + /** + * 在线状态【1:在线,0:离线】 + */ + private String onlineState; + + /** + * 员工状态【1:是陪聊,0:不是陪聊】 + */ + private String clerkState; + + /** + * 允许申请陪聊 + */ + private boolean clerkAllowEdit = true; + + /** + * 服务项目 + */ + private List commodity = new ArrayList<>(); + + /** + * 是否允许登录(0:允许,1:不允许) + */ + private String allowLogin = "0"; + + /** + * 禁止登录原因 + */ + private String disableLoginReason; + + private JSONObject pcData; + + private PlayClerkLevelInfoEntity levelInfo; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/PlayClerkUserOnlineStateVo.java --- +package com.starry.admin.modules.weichat.entity; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; +import lombok.Data; + +/** + * 店员在线状态【1:在线,0:离线】 + * + * @author admin + * @since 2024/4/11 11:19 + **/ +@Data +public class PlayClerkUserOnlineStateVo { + + /** + * 在线状态 + */ + @NotNull(message = "在线状态不能为空") + @Pattern(regexp = "[01]", message = "在线状态必须为0或1") + private String onlineState; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/PlayClerkUserOtherVo.java --- +package com.starry.admin.modules.weichat.entity; + +import java.util.ArrayList; +import java.util.List; +import lombok.Data; + +/** + * 店员录音文件 + * + * @author admin + * @since 2024/4/11 11:19 + **/ +@Data +public class PlayClerkUserOtherVo { + + /** + * 店员性别(0:未知;1:男;2:女) + */ + private Integer sex; + + /** + * 年龄 + */ + private Integer age; + + /** + * 个性签名 + */ + private String signature; + + /** + * 星座 + */ + private String constellation; + + /** + * 所在国家 + */ + private String country = "中国"; + + /** + * 所在省份 + */ + private String province; + + /** + * 所在城市 + */ + private String city; + + /** + * 标签 + */ + private List label = new ArrayList<>(); + + /** + * 分类 + */ + private String typeId; + + /** + * 微信二维码 + **/ + private String weChatCodeImage; + + /** + * 微信收款码图片 + **/ + private String weChatPayImage; + + /** + * 支付宝收款码图片 + **/ + private String alipayImage; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/PlayClerkUserSendCodeVo.java --- +package com.starry.admin.modules.weichat.entity; + +import javax.validation.constraints.NotBlank; +import lombok.Data; + +/** + * @author admin + */ +@Data +public class PlayClerkUserSendCodeVo { + + /** + * 手机号码区号 + */ + @NotBlank(message = "手机号码区号不能为空") + private String areaCode; + + /** + * 手机号码 + */ + @NotBlank(message = "手机号码不能为空") + private String phone; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/PlayClerkWxPerformanceInfoQueryVo.java --- +package com.starry.admin.modules.weichat.entity; + +import lombok.Data; + +/** + * @author admin + * @since 2024/6/10 下午8:58 + **/ +@Data +public class PlayClerkWxPerformanceInfoQueryVo { + + /** + * 店员ID + */ + private String clerkId; + + /** + * 订单开始时间 + */ + private String startTime; + + /** + * 订单结束时间 + */ + private String endTime; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/PlayCommodityReturnVo.java --- +package com.starry.admin.modules.weichat.entity; + +import java.math.BigDecimal; +import java.util.List; +import lombok.Data; + +/** + * 服务项目返回对象 + * + * @author admin + * @since 2024/5/29 16:41 + **/ +@Data +public class PlayCommodityReturnVo { + + private String id; + + private String pId; + /** + * 项目类型 + */ + private String itemType; + + /** + * 项目名称 + */ + private String itemName; + + /** + * 服务时长(文字描述信息,不参与订单计算) + */ + private String serviceDuration; + + /** + * 服务单价 + */ + private BigDecimal price; + + List child; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/PlayCustomLeaveAddVo.java --- +package com.starry.admin.modules.weichat.entity; + +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +/** + * 顾客新增留言对象 + * + * @author admin + * @since 2024/5/8 下午10:03 + **/ +@Data +public class PlayCustomLeaveAddVo { + + /** + * 顾客ID + */ + private String customId; + + /** + * 留言内容 + */ + @NotBlank(message = "留言内容不能为空") + @Length(max = 255, message = "留言内容不能超过255个字符") + private String content; + + /** + * 图片 + */ + + @NotNull(message = "images不能为空") + @Size(max = 3, message = "照片不能超过3张") + private List images; + + /** + * 备注 + */ + private String remark; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/PlayGiftInfoDto.java --- +package com.starry.admin.modules.weichat.entity; + +import java.math.BigDecimal; +import lombok.Data; + +@Data +public class PlayGiftInfoDto { + + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 礼物名称 + */ + private String name; + + /** + * 礼物类型(0:盲盒,1:普通礼物) + */ + private String type; + + /** + * 礼物图片地址 + */ + private String url; + + /** + * 单价 + */ + private BigDecimal price; + + /** + * 价格单位 + */ + private String unit; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/PlayGroupWagesQueryVo.java --- +package com.starry.admin.modules.weichat.entity; + +import java.util.List; +import lombok.Data; + +/** + * 组长工资查询对象 + * + * @author admin + * @since 2024/7/6 下午3:56 + **/ +@Data +public class PlayGroupWagesQueryVo { + + /** + * 统计时间 + */ + private List statisticalTime; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/PlayGroupWagesReturnVo.java --- +package com.starry.admin.modules.weichat.entity; + +import java.math.BigDecimal; +import lombok.Data; + +/** + * 组长工资查询对象 + * + * @author admin + * @since 2024/7/6 下午3:56 + **/ +@Data +public class PlayGroupWagesReturnVo { + + /** + * 组名称 + */ + private String groupName; + + /** + * 订单金额 + */ + private BigDecimal orderMoney = BigDecimal.ZERO; + + /** + * 订单最终金额(支付金额) + */ + private BigDecimal finalAmount = BigDecimal.ZERO; + + /** + * 续单比例 + */ + private final double orderContinueProportion = 0.0; + /** + * 续单金额 + */ + private final BigDecimal orderTotalAmount = BigDecimal.ZERO; + + /** + * 续费率 + */ + private final BigDecimal orderContinueRechargeProportion = BigDecimal.ZERO; + /** + * 退单率 + */ + private final BigDecimal orderChargebackProportion = BigDecimal.ZERO; + /** + * 续客率 + */ + private final BigDecimal continuousCustomProportion = BigDecimal.ZERO; + + /** + * 订单平均价格 + */ + private final BigDecimal averageUnitPrice = BigDecimal.ZERO; + + /** + * 组长工资 + */ + private final BigDecimal commission = BigDecimal.ZERO; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/PlayOrderCancellationVo.java --- +package com.starry.admin.modules.weichat.entity; + +import java.util.ArrayList; +import java.util.List; +import javax.validation.constraints.NotBlank; +import lombok.Data; + +/** + * @author admin + * @since 2024/5/10 下午5:15 + **/ +@Data +public class PlayOrderCancellationVo { + + /** + * 申请人ID + */ + private String customId; + /** + * 订单ID + */ + @NotBlank(message = "订单ID不能为空") + private String orderId; + + /** + * 取消原因 + */ + @NotBlank(message = "取消原因不能为空") + private String refundReason; + + private List images = new ArrayList<>(); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/PlayOrderComplaintAddVo.java --- +package com.starry.admin.modules.weichat.entity; + +import java.util.Date; +import java.util.List; +import javax.validation.constraints.NotBlank; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +/** + * 订单投诉新增VO + * + * @author admin + * @since 2024/5/8 下午10:49 + **/ +@Data +public class PlayOrderComplaintAddVo { + + /** + * 订单ID + */ + @NotBlank(message = "订单ID不能为空") + private String orderId; + + /** + * 顾客ID + */ + private String customId; + + /** + * 投诉人微信号码 + */ + @NotBlank(message = "微信号码不能为空") + private String wxChatCode; + + /** + * 投诉内容 + */ + @NotBlank(message = "投诉内容不能为空") + @Length(max = 255, message = "投诉内容最多255个字符") + private String complaintCon; + + /** + * 投诉时间 + */ + private Date complaintTime = new Date(); + + /** + * 图片列表 + */ + private List images; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/PlayOrderEvaluateAddVo.java --- +package com.starry.admin.modules.weichat.entity; + +import java.util.Date; +import javax.validation.constraints.*; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +/** + * 订单评价新增VO + * + * @author admin + * @since 2024/5/8 下午10:49 + **/ +@Data +public class PlayOrderEvaluateAddVo { + + /** + * 订单ID + */ + @NotBlank(message = "订单ID不能为空") + private String orderId; + + /** + * 顾客ID + */ + private String customId; + + /** + * 匿名评价(0:匿名,1:非匿名) + */ + @NotBlank(message = "是否匿名不能为空") + @Pattern(regexp = "[01]", message = "匿名评价只能为0或1") + private String anonymous; + + /** + * 评价类型(0:好评,1差评) + */ + private String evaluateType = "0"; + + /** + * 评价等级【1-5星,最低1星,最高5星】 + */ + @NotNull(message = "评价等级不能为空") + @Min(value = 1, message = "评价等级最低位1星") + @Max(value = 5, message = "评价等级最高5星") + private int evaluateLevel; + + /** + * 评价内容 + */ + @NotNull(message = "评价内容不能为空") + @Length(max = 255, message = "评价内容最多255个字符") + private String evaluateCon; + + /** + * 评价时间 + */ + private Date evaluateTime = new Date(); +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/PlayOrderInfoGiftAdd.java --- +package com.starry.admin.modules.weichat.entity; + +import com.starry.admin.modules.shop.module.constant.GiftConstant; +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +/** + * 新增赠礼订单实体 + * + * @author admin + */ +@Data +public class PlayOrderInfoGiftAdd { + + /** + * 店员用户ID + */ + @NotBlank(message = "打赏对象不能为空") + private String clerkId; + + @NotBlank(message = "礼物ID不能为空") + private String giftId; + + @NotNull(message = "礼物数量不能为空") + @Min(value = GiftConstant.MINIMUM_SINGLE_GIFT_QUANTITY, message = "礼物数量不能小于" + + GiftConstant.MINIMUM_SINGLE_GIFT_QUANTITY) + @Max(value = GiftConstant.MAXIMUM_SINGLE_GIFT_QUANTITY, message = "礼物数量不能大于" + + GiftConstant.MAXIMUM_SINGLE_GIFT_QUANTITY) + private int giftQuantity; + + private String weiChatCode; + + /** + * 备注 + */ + private String remark; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/PlayOrderInfoRandomAdd.java --- +package com.starry.admin.modules.weichat.entity; + +import com.starry.admin.modules.shop.module.constant.GiftConstant; +import java.util.List; +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; + +/** + * 新增随机订单实体 + * + * @author admin + */ +@Data +public class PlayOrderInfoRandomAdd { + + /** + * 陪聊性别(0:未知;1:男;2:女) + * + * @since 2024/5/8 15:31 + **/ + private String sex; + /** + * 陪聊等级 + **/ + @NotBlank(message = "商品ID不能为空") + private String levelId; + + /** + * 标签列表 + * + * @since 2024/5/8 15:26 + **/ + private List labels; + + @NotBlank(message = "商品ID不能为空") + private String commodityId; + + @NotNull(message = "数量不能为空") + @Min(value = GiftConstant.MINIMUM_SINGLE_GIFT_QUANTITY, message = "数量不能小于" + + GiftConstant.MINIMUM_SINGLE_GIFT_QUANTITY) + @Max(value = GiftConstant.MAXIMUM_SINGLE_GIFT_QUANTITY, message = "数量不能大于" + + GiftConstant.MAXIMUM_SINGLE_GIFT_QUANTITY) + private int commodityQuantity; + + @NotBlank(message = "微信号不能为空") + private String weiChatCode; + + /** + * 是否排除下单过的成员(0:不排除;1:排除) + * + * @since 2024/5/8 15:28 + **/ + private String excludeHistory; + + /** + * 优惠券ID列表 + */ + private List couponIds; + + /** + * 备注 + */ + private String remark; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/PlayOrderInfoRewardAdd.java --- +package com.starry.admin.modules.weichat.entity; + +import javax.validation.constraints.NotBlank; +import lombok.Data; + +/** + * 新增打赏订单实体 + * + * @author admin + */ +@Data +public class PlayOrderInfoRewardAdd { + + /** + * 店员用户ID + */ + @NotBlank(message = "打赏对象不能为空") + private String clerkId; + /** + * 打赏金额 + */ + @NotBlank(message = "打赏金额不能为空") + private String money; + + @NotBlank(message = "微信号不能为空") + private String weiChatCode; + + /** + * 备注 + */ + private String remark; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/PlayShopArticleInfoQueryVo.java --- +package com.starry.admin.modules.weichat.entity; + +import com.starry.common.domain.BasePageEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @author admin + * @since 2024/7/24 上午9:36 + **/ +@EqualsAndHashCode(callSuper = true) +@Data +public class PlayShopArticleInfoQueryVo extends BasePageEntity { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/PlayShopArticleInfoReturnVo.java --- +package com.starry.admin.modules.weichat.entity; + +import lombok.Data; + +/** + * @author admin + * @since 2024/7/24 上午9:36 + **/ +@Data +public class PlayShopArticleInfoReturnVo { + + private String id; + /** + * 文章标题 + **/ + private String articleTitle; + + /** + * 文章内容 + **/ + private String articleContent; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/PlayShopReadArticleVo.java --- +package com.starry.admin.modules.weichat.entity; + +import javax.validation.constraints.NotNull; +import lombok.Data; + +/** + * @author admin + * @since 2024/7/24 上午9:36 + **/ +@Data +public class PlayShopReadArticleVo { + + @NotNull(message = "id不能为空") + private String id; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/WxCouponOrderQueryVo.java --- +package com.starry.admin.modules.weichat.entity; + +import lombok.Data; + +/** + * 顾客优惠券下单查询对象 + * + * @author admin + * @since 2024/7/6 下午4:16 + **/ +@Data +public class WxCouponOrderQueryVo { + + private String commodityId; + + /*** + * 店员等级ID + */ + private String levelId; + + /*** + * 店员ID + */ + private String clerkId; + + /** + * 下单类型(-1:其他类型;0:指定单;1:随机单;2:打赏单) + */ + private String placeType; + + private int commodityQuantity; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/WxCouponOrderReturnVo.java --- +package com.starry.admin.modules.weichat.entity; + +import com.fasterxml.jackson.annotation.JsonFormat; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 顾客优惠券下单查询返回对象 + * + * @author admin + * @since 2024/7/6 下午4:16 + **/ +@Data +public class WxCouponOrderReturnVo { + + /** + * 优惠券ID + */ + private String id; + + /** + * 优惠券名称 + **/ + private String couponName = "测试券"; + + /** + * 有效期类型(0:永久有效;1:固定时间内有效;2:领取后几天内有效) + */ + private String validityPeriodType; + + /** + * 生效时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime productiveTime; + + /** + * 到期时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime expirationTime; + + /** + * 生效时长,validityPeriodType=2时有效 + **/ + private Integer effectiveDay; + + /** + * 使用优惠券最低消费金额 + **/ + private BigDecimal useMinAmount; + + /** + * 优惠类型(0:满减;1:折扣) + */ + private String discountType; + + /** + * 折扣值 + */ + private BigDecimal discountAmount; + + private String discountContent; + + /** + * 优惠是否可使用(0:不可使用,1:可使用) + */ + private String available; + + /** + * 优惠券不可用的原因 + */ + private String reasonForUnavailableUse; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/WxCouponQueryVo.java --- +package com.starry.admin.modules.weichat.entity; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; +import lombok.Data; + +/** + * 顾客优惠券查询对象 + * + * @author admin + * @since 2024/7/6 下午4:16 + **/ +@Data +public class WxCouponQueryVo { + + private String commodityId; + + /** + * 下单类型(-1:其他类型;0:指定单;1:随机单;2:打赏单) + */ + @NotNull(message = "下单类型不能为空") + @Pattern(regexp = "[0|1]", message = "订单类型必须为0或者1") + private String placeType; + + private int commodityQuantity; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/WxCouponReceiveReturnVo.java --- +package com.starry.admin.modules.weichat.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.starry.admin.common.conf.StringTypeHandler; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 顾客优惠券领取查询返回对象 + * + * @author admin + * @since 2024/7/6 下午4:16 + **/ +@Data +public class WxCouponReceiveReturnVo { + + /** + * 优惠券ID + */ + private String id; + + /** + * 优惠券名称 + **/ + private String couponName; + + /** + * 有效期类型(0:永久有效;1:固定时间内有效;2:领取后几天内有效) + */ + private String validityPeriodType; + + /** + * 生效时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime productiveTime; + + /** + * 到期时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime expirationTime; + + /** + * 生效时长,validityPeriodType=2时有效 + **/ + private Integer effectiveDay; + + /** + * 使用优惠券最低消费金额 + **/ + private BigDecimal useMinAmount; + + /** + * 优惠类型(0:满减;1:折扣) + */ + private String discountType; + + /** + * 折扣值 + */ + private BigDecimal discountAmount; + + /** + * 下单类型(0:指定单,1:随机单。2:打赏单) + */ + @TableField(typeHandler = StringTypeHandler.class) + private List placeType; + + /** + * 优惠内容(文字展示) + **/ + private String discountContent; + + /** + * 优惠是否已领取(0:未领取,1:已领取) + */ + private String obtained = "0"; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/WxCouponReturnVo.java --- +package com.starry.admin.modules.weichat.entity; + +import com.fasterxml.jackson.annotation.JsonFormat; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 顾客优惠券查询对象 + * + * @author admin + * @since 2024/7/6 下午4:16 + **/ +@Data +public class WxCouponReturnVo { + + /** + * 优惠券ID + */ + private String id; + + /** + * 优惠券名称 + **/ + private String couponName; + + /** + * 有效期类型(0:永久有效;1:固定时间内有效;2:领取后几天内有效) + */ + private String validityPeriodType; + + /** + * 生效时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime productiveTime; + + /** + * 到期时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime expirationTime; + + /** + * 生效时长,validityPeriodType=2时有效 + **/ + private Integer effectiveDay; + + /** + * 使用优惠券最低消费金额 + **/ + private BigDecimal useMinAmount; + + /** + * 优惠类型(0:满减;1:折扣) + */ + private String discountType; + + /** + * 折扣值 + */ + private BigDecimal discountAmount; + + /** + * 优惠是否可使用(0:不可使用,1:可使用) + */ + private String available; + + /** + * 优惠券不可用的原因 + */ + private String reasonForUnavailableUse; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/WxPayReturnVo.java --- +package com.starry.admin.modules.weichat.entity; + +import lombok.Data; + +/** + * 微信预支付接口返回信息 + * + * @author admin + * @since 2024/5/8 10:43 + **/ +@Data +public class WxPayReturnVo { + + private String orderId; + private String timeStamp; + private String nonceStr; + private String signType; + private String paySign; + private String prepayId; + private String callback; + + public WxPayReturnVo(String orderId, String timeStamp, String nonceStr, String signType, String paySign, + String prepayId, String callback) { + this.orderId = orderId; + this.timeStamp = timeStamp; + this.nonceStr = nonceStr; + this.signType = signType; + this.paySign = paySign; + this.prepayId = prepayId; + this.callback = callback; + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/WxPlayClerkUserQueryVo.java --- +package com.starry.admin.modules.weichat.entity; + +import com.starry.common.domain.BasePageEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 微信端分页查询店员文件 + * + * @author admin + * @since 2024/4/11 11:19 + **/ +@EqualsAndHashCode(callSuper = true) +@Data +public class WxPlayClerkUserQueryVo extends BasePageEntity { + + /** + * 分类 + */ + private String typeId; + /** + * 等级 + **/ + private String levelId; + + /** + * 性别[0:未知;1:男;2:女] + **/ + private Integer sex; + + /** + * 省 + **/ + private String province; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/WxUserLoginVo.java --- +package com.starry.admin.modules.weichat.entity; + +import javax.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class WxUserLoginVo { + + @NotBlank(message = "code不能为空") + private String code; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/WxUserQueryAddressVo.java --- +package com.starry.admin.modules.weichat.entity; + +import lombok.Data; + +/** + * @author admin + */ +@Data +public class WxUserQueryAddressVo { + + private String url; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/article/PlayClerkAddArticleVo.java --- +package com.starry.admin.modules.weichat.entity.article; + +import java.time.LocalDateTime; +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; +import lombok.Data; + +/** + * 店员新增动态 + * + * @author admin + * @since 2024/5/20 下午11:24 + **/ +@Data +public class PlayClerkAddArticleVo { + + /** + * 陪聊用户ID + */ + private String clerkId; + + /** + * 动态内容 + */ + @NotBlank(message = "动态内容不能为空") + private String articleCon; + + /** + * 动态附件类型(0:图片;1:视频;3:录音) + */ + @NotBlank(message = "动态附件类型不能为空") + @Pattern(regexp = "[012]", message = "动态附件类型只能为0或1") + private String annexType; + + /** + * 动态附件内容 + */ + @NotNull(message = "动态附件不能为空") + @Size(min = 1, message = "附件数量必须大于0") + @Size(max = 6, message = "附件数量必须小于6") + private List annexCon; + + /** + * 发布时间 + */ + private LocalDateTime releaseTime = LocalDateTime.now(); + + /** + * 审核状态(0:未审核:1:审核通过,2:审核不通过) + */ + private String reviewState = "0"; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/article/PlayClerkArticleCustomQueryVo.java --- +package com.starry.admin.modules.weichat.entity.article; + +import com.starry.common.domain.BasePageEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @author admin 顾客查询动态信息查询返回对象 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class PlayClerkArticleCustomQueryVo extends BasePageEntity { + + /** + * 收藏状态(0:未收藏,1:已收藏) + */ + private String followState; + + /** + * 店员ID + */ + private String clerkId; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/article/PlayClerkArticleCustomReturnVo.java --- +package com.starry.admin.modules.weichat.entity.article; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.starry.admin.modules.clerk.module.entity.PlayCustomArticleInfoEntity; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * @author admin 顾客查询动态信息查询返回对象 + */ +@Data +public class PlayClerkArticleCustomReturnVo { + + /** + * UUID + */ + private String id; + /** + * 陪聊用户ID + */ + private String clerkId; + + /** + * 陪聊用户昵称 + */ + private String clerkNickname; + + /** + * 陪聊用户头像 + */ + private String clerkAvatar; + + /** + * 陪聊用户性别 + */ + private String clerkSex; + + /** + * 动态内容 + */ + private String articleCon; + + /** + * 动态附件类型(0:图片;1:视频;2:音频) + */ + private String annexType; + + /** + * 动态附件内容 + */ + private List annexCon; + + /** + * 发布时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime releaseTime; + + /** + * 点赞总数 + */ + private Integer agreedQuantity = 0; + + /** + * 点赞状态(0:未关注,1:已关注) + */ + private String greedState = "0"; + + /** + * 收藏状态(0:未收藏,1:已收藏) + */ + private String followState = "0"; + + /** + * 陪聊点赞动态 + */ + @JsonIgnore + private List articleInfoEntities; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/article/PlayClerkArticleFollowCustomFollowStateEditStateVo.java --- +package com.starry.admin.modules.weichat.entity.article; + +import com.starry.common.domain.BasePageEntity; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Pattern; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @author admin 顾客收藏动态状态修改 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class PlayClerkArticleFollowCustomFollowStateEditStateVo extends BasePageEntity { + + @NotBlank(message = "id不能为空") + + private String id; + /** + * 收藏状态(0:未收藏,1:已收藏) + */ + @NotBlank(message = "followState不能为空") + @Pattern(regexp = "[01]", message = "followState值必须为0或者1") + private String followState; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/article/PlayClerkArticleFollowCustomGreedStateEditStateVo.java --- +package com.starry.admin.modules.weichat.entity.article; + +import com.starry.common.domain.BasePageEntity; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Pattern; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @author admin 顾客点赞动态查询状态修改 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class PlayClerkArticleFollowCustomGreedStateEditStateVo extends BasePageEntity { + + @NotBlank(message = "不能为空") + private String id; + + /** + * 点赞状态(0:未点赞,1:已关注) + */ + @NotBlank(message = "greedState不能为空") + @Pattern(regexp = "[01]", message = "greedState值必须为0或者1") + private String greedState; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/clerk/PlayClerkLevelAndRankingVo.java --- +package com.starry.admin.modules.weichat.entity.clerk; + +import lombok.Data; + +/** + * @author admin + * @since 2024/6/10 下午8:58 + **/ +@Data +public class PlayClerkLevelAndRankingVo { + + /** + * 等级ID + */ + private String levelName; + + /** + * 开始名次 + */ + private Integer startRanking; + + /** + * 开始名次 + */ + private Integer endRanking; + + private Integer sort; + + public PlayClerkLevelAndRankingVo(String levelName, Integer startRanking, Integer endRanking, Integer sort) { + this.levelName = levelName; + this.startRanking = startRanking; + this.endRanking = endRanking; + this.sort = sort; + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/clerk/PlayClerkLevelInfoReturnVo.java --- +package com.starry.admin.modules.weichat.entity.clerk; + +import java.util.List; +import lombok.Data; + +/** + * @author admin + * @since 2024/6/10 下午8:58 + **/ +@Data +public class PlayClerkLevelInfoReturnVo { + + /** + * 等级ID + */ + private String levelId; + + /** + * 等级名称 + */ + private String levelName; + + private List levelAndRanking; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/clerk/PlayClerkUserInfoQueryVo.java --- +package com.starry.admin.modules.weichat.entity.clerk; + +import com.starry.common.domain.BasePageEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 分页查询店员对象 + * + * @author admin + * @since 2024-03-30 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@ApiModel(value = "店员查询参数", description = "分页查询店员的条件参数对象") +public class PlayClerkUserInfoQueryVo extends BasePageEntity { + + /** + * 店员昵称 + **/ + @ApiModelProperty(value = "店员昵称", example = "张三", notes = "支持模糊查询") + private String nickname; + /** + * 店员等级 + */ + @ApiModelProperty(value = "店员等级ID") + private String levelId; + + /** + * 店员类型 + */ + @ApiModelProperty(value = "店员类型ID") + private String typeId; + + /** + * 性别[0:未知;1:男;2:女] + */ + @ApiModelProperty(value = "性别", example = "1", notes = "0:未知;1:男;2:女") + private String sex; + + /** + * 所在省份 + */ + @ApiModelProperty(value = "所在省份", example = "广东省") + private String province; + + /** + * 上架状态【1:上架,0:下架】 + */ + @ApiModelProperty(value = "上架状态", example = "1", notes = "1:上架,0:下架") + private String listingState; + + /** + * 是否推荐状态(1:已推荐,0:未推荐) + */ + @ApiModelProperty(value = "是否推荐", example = "1", notes = "1:已推荐,0:未推荐") + private String recommendationState; + + /** + * 员工状态【1:是陪聊,0:不是陪聊】 + */ + @ApiModelProperty(value = "员工状态", example = "1", notes = "1:是陪聊,0:不是陪聊", required = true) + private String clerkState = "1"; + + /** + * 在职状态(1:在职,0:离职) + */ + @ApiModelProperty(value = "在职状态", example = "1", notes = "1:在职,0:离职", required = true) + private String onboardingState = "1"; + + /** + * 手机号码 + */ + @ApiModelProperty(value = "手机号码", example = "13800138000") + private String phone; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/clerk/PlayClerkUserInfoResultVo.java --- +package com.starry.admin.modules.weichat.entity.clerk; + +import com.starry.admin.modules.clerk.module.entity.PlayClerkLevelInfoEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.ArrayList; +import java.util.List; +import lombok.Data; + +/** + * @author admin + */ +@Data +@ApiModel(value = "店员信息返回对象", description = "查询店员列表的返回结果对象") +public class PlayClerkUserInfoResultVo { + + /** + * UUID + */ + @ApiModelProperty(value = "店员ID", notes = "唯一标识") + private String id; + + /** + * 店员昵称 + */ + @ApiModelProperty(value = "店员昵称") + private String nickname; + + /** + * 店员等级 + */ + @ApiModelProperty(value = "店员等级ID") + private String levelId; + + private PlayClerkLevelInfoEntity levelInfo; + /** + * 店员等级 + */ + @ApiModelProperty(value = "店员等级名称") + private String levelName; + + /** + * 性别[0:未知;1:男;2:女] + */ + @ApiModelProperty(value = "性别", notes = "0:未知;1:男;2:女") + private String sex; + + /** + * 头像 + */ + @ApiModelProperty(value = "头像", notes = "头像图片URL") + private String avatar; + + /** + * 音频 + */ + @ApiModelProperty(value = "音频", notes = "音频文件URL") + private String audio; + + /** + * 星座 + */ + @ApiModelProperty(value = "星座", example = "天蝎座") + private String constellation; + + /** + * 标签 + */ + @ApiModelProperty(value = "标签列表", notes = "店员个人标签") + private List label = new ArrayList<>(); + + /** + * 相册 + */ + @ApiModelProperty(value = "相册列表", notes = "店员相册图片URL列表") + private List album = new ArrayList<>(); + + /** + * 个性签名 + */ + @ApiModelProperty(value = "个性签名") + private String signature; + + /** + * 年龄 + */ + @ApiModelProperty(value = "年龄", example = "25") + private Integer age; + + /** + * 所在省份 + */ + @ApiModelProperty(value = "所在省份", example = "广东省") + private String province; + + /** + * 所在城市 + */ + @ApiModelProperty(value = "所在城市", example = "深圳市") + private String city; + + /** + * 关注(0:未关注,1:已关注) + */ + @ApiModelProperty(value = "关注状态", notes = "0:未关注,1:已关注", example = "0") + private String followState = "0"; + + /** + * 在线状态【1:在线,0:离线】 + */ + @ApiModelProperty(value = "在线状态", notes = "1:在线,0:离线") + private String onlineState; + + /** + * 上架状态【1:上架,0:下架】 + */ + @ApiModelProperty(value = "上架状态", notes = "1:上架,0:下架") + private String listingState; + + /** + * 实名状态【1:已实名,0:未实名】 + */ + @ApiModelProperty(value = "实名状态", notes = "1:已实名,0:未实名") + private String realState; + + /** + * 是否必须实名【1:必须实名,0:非必须实名,2:跟随店铺设置】 + */ + @ApiModelProperty(value = "是否必须实名", notes = "1:必须实名,0:非必须实名,2:跟随店铺设置") + private String mandatoryRealState; + + /** + * 随机接单状态【1:允许,0:禁止】 + */ + @ApiModelProperty(value = "随机接单状态", notes = "1:允许,0:禁止") + private String randomOrderState; + + /** + * 服务项目 + */ + @ApiModelProperty(value = "服务项目列表", notes = "店员提供的服务项目") + private List commodity; + + /** + * 地址 + */ + @ApiModelProperty(value = "地址", notes = "店员所在详细地址") + private String address; + + /** + * 最低消费 + */ + @ApiModelProperty(value = "最低消费", notes = "店员服务的最低消费", example = "最低1船票") + private String latestConsumption = "最低1船票"; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/costom/PlayCustomHideLevelStateEditVo.java --- +package com.starry.admin.modules.weichat.entity.costom; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; +import lombok.Data; + +/** + * 顾客状态修改 + * + * @author admin + * @since 2024/5/21 下午10:38 + **/ +@Data +public class PlayCustomHideLevelStateEditVo { + + /** + * UUID + */ + private String id; + + /** + * 隐藏等级[0:不隐藏;1:隐藏] + */ + @NotNull(message = "hideLevelState不能为空") + @Pattern(regexp = "[01]", message = "hideLevelState状态异常") + private String hideLevelState; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/costom/PlayCustomHideRankingStateEditVo.java --- +package com.starry.admin.modules.weichat.entity.costom; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; +import lombok.Data; + +/** + * 顾客状态修改 + * + * @author admin + * @since 2024/5/21 下午10:38 + **/ +@Data +public class PlayCustomHideRankingStateEditVo { + + /** + * UUID + */ + private String id; + + /** + * 隐藏排名[0:不隐藏;1:隐藏] + */ + @NotNull(message = "hideRankingState不能为空") + @Pattern(regexp = "[01]", message = "hideRankingState状态异常") + private String hideRankingState; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/evaluate/PlayCustomOrderEvaluateReturnVo.java --- +package com.starry.admin.modules.weichat.entity.evaluate; + +import com.fasterxml.jackson.annotation.JsonFormat; +import java.util.Date; +import lombok.Data; + +/** + * 订单评价对象查询返回对象 + * + * @author admin + * @since 2024/5/13 16:15 + **/ +@Data +public class PlayCustomOrderEvaluateReturnVo { + + private String id; + + /** + * 匿名评价(0:匿名,1:非匿名) + */ + private String anonymous; + + /** + * 评价等级【1-5星,最低1星,最高5星】 + */ + private Integer evaluateLevel; + + /** + * 评价内容 + */ + private String evaluateCon; + + /** + * 评价时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date evaluateTime; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/gift/PlayClerkGiftReturnVo.java --- +package com.starry.admin.modules.weichat.entity.gift; + +import java.math.BigDecimal; +import lombok.Data; + +/** + * 店员礼物查询对象 + * + * @author admin + * @since 2024/5/26 上午12:20 + **/ +@Data +public class PlayClerkGiftReturnVo { + + /** + * UUID + */ + private String id; + + /** + * 礼物名称 + */ + private String name; + + /** + * 礼物类型(0:盲盒,1:普通礼物) + */ + private String type; + + /** + * 礼物图片地址 + */ + private String url; + + /** + * 单价 + */ + private BigDecimal price; + + /** + * 价格单位 + */ + private String unit; + + /** + * 礼物数量 + */ + private long giffNumber; + + /** + * 礼物状态(0:正常,1:已下架) + */ + private String state; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/gift/PlayCustomGiftQueryVo.java --- +package com.starry.admin.modules.weichat.entity.gift; + +import lombok.Data; + +/** + * 店员礼物查询对象 + * + * @author admin + * @since 2024/5/26 上午12:20 + **/ +@Data +public class PlayCustomGiftQueryVo { + + /** + * 是否已获得礼物(0:已获取,1:所有礼物) + */ + private String obtained; + + /** + * 是否是历史礼物(0:不是,1:是) + */ + private String history; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/level/PlayClerkLevelReturnVo.java --- +package com.starry.admin.modules.weichat.entity.level; + +import lombok.Data; + +/** + * @author admin + * @since 2024/5/29 上午6:29 + **/ +@Data +public class PlayClerkLevelReturnVo { + + private String id; + + private String levelName; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/order/PlayClearOrderInfoQueryVo.java --- +package com.starry.admin.modules.weichat.entity.order; + +import com.starry.common.domain.BasePageEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 店员分行查询订单-查询对象 + * + * @author admin + * @since 2024-03-20 + */ +@Data +@EqualsAndHashCode(callSuper = false) +public class PlayClearOrderInfoQueryVo extends BasePageEntity { + + private String id; + /** + * 订单状态【0:1:2:3:4】 0:已下单 1:已接单 2:已开始 3:已完成 4:已取消 + */ + private String orderStatus; + + /** + * 订单类型【0:充值订单;1:提现订单;2:普通订单】 + */ + private String orderType = "2"; + + /** + * 下单类型(0:指定单,1:随机单。2:打赏单) + */ + private String placeType; + + /** + * 下单人 + */ + private String purchaserBy; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/order/PlayClerkOrderDetailsReturnVo.java --- +package com.starry.admin.modules.weichat.entity.order; + +import com.fasterxml.jackson.annotation.JsonFormat; +import java.math.BigDecimal; +import java.util.Date; +import lombok.Data; + +/** + * 店员订单详情返回信息 + * + * @author admin + * @since 2024/5/12 下午9:16 + **/ +@Data +public class PlayClerkOrderDetailsReturnVo { + + /** + * 订单ID + */ + private String id; + + /** + * 订单编号 + */ + private String orderNo; + + /** + * 订单状态【0:1:2:3:4】 0:已下单(待接单) 1:已接单(待开始) 2:已开始(服务中) 3:已完成 4:已取消 + */ + private String orderStatus; + + /** + * 下单类型(0:指定单,1:随机单。2:打赏单) + */ + private String placeType; + + /** + * 商品数量 + */ + private int commodityNumber; + + /** + * 支付方式,0:余额支付,1:微信支付,2:支付宝支付 + */ + private String payMethod; + + /** + * 订单备注 + */ + private String remark; + + /** + * 买家微信号码 + */ + private String weiChatCode; + + /** + * 订单金额 + */ + private BigDecimal orderMoney; + + /** + * 下单时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date purchaserTime; + + /** + * 接单时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date acceptTime; + + /** + * 开始时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date startTime; + + /** + * 结束时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date endTime; + + /** + * 取消时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date cancelTime; + + /** + * 退款人类型[0:顾客;1:店员;2:管理员] + */ + private String refundByType; + + /** + * 退款人ID + */ + private String refundById; + + /** + * 退款原因 + **/ + private String refundReason; + + /** + * 订单最终金额(支付金额) + */ + private BigDecimal finalAmount; + + /** + * 预计收入 + */ + private BigDecimal estimatedRevenue; + + /** + * 优惠金额 + */ + private BigDecimal discountAmount; + + /** + * 用户ID + */ + private String customId; + + /** + * 用户昵称 + */ + private String customNickname; + + /** + * 用户头像 + */ + private String customAvatar; + + /** + * 用户等级ID + */ + private String customLevelId; + + /** + * 用户等级名称 + */ + private String customLevelName; + + /** + * 店员ID + */ + private String clerkId; + + /** + * 店员昵称 + */ + private String clerkNickname; + + /** + * 店员头像 + */ + private String clerkAvatar; + + /** + * 商品ID + */ + private String commodityId; + + /** + * 商品类型[0:礼物,1:服务] + */ + private String commodityType; + + /** + * 商品名称 + */ + private String commodityName; + /** + * 商品单价 + */ + private BigDecimal commodityPrice; + + /** + * 服务时长 + * + * @since 2024/5/8 16:44 + **/ + private String serviceDuration; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/order/PlayClerkOrderInfoQueryVo.java --- +package com.starry.admin.modules.weichat.entity.order; + +import com.starry.common.domain.BasePageEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 订单查询对象 + * + * @author admin + * @since 2024-03-20 + */ +@Data +@EqualsAndHashCode(callSuper = false) +public class PlayClerkOrderInfoQueryVo extends BasePageEntity { + + private String id; + /** + * 订单状态【0:1:2:3:4】 0:已下单 1:已接单 2:已开始 3:已完成 4:已取消 + */ + private String orderStatus; + + /** + * 订单类型【0:充值订单;1:提现订单;2:普通订单】 + */ + private String orderType = "2"; + + /** + * 下单类型(0:指定单,1:随机单。2:打赏单) + */ + private String placeType; + + /** + * 下单人 + */ + private String acceptBy; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/order/PlayClerkOrderListReturnVo.java --- +package com.starry.admin.modules.weichat.entity.order; + +import com.fasterxml.jackson.annotation.JsonFormat; +import java.math.BigDecimal; +import java.util.Date; +import lombok.Data; + +/** + * 店员查询订单列表返回对象 + * + * @author admin + * @since 2024-03-20 + */ +@Data +public class PlayClerkOrderListReturnVo { + + /** + * 订单ID + */ + private String id; + + /** + * 订单编号 + */ + private String orderNo; + + /** + * 订单状态【0:1:2:3:4】 0:已下单(待接单) 1:已接单(待开始) 2:已开始(服务中) 3:已完成 4:已取消 + */ + private String orderStatus; + + /** + * 下单类型(0:指定单,1:随机单。2:打赏单) + */ + private String placeType; + + /** + * 是否是首单【0:不是,1:是】 + */ + private String firstOrder; + + /** + * 商品数量 + */ + private int commodityNumber; + + /** + * 订单备注 + */ + private String remark; + + /** + * 下单时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date purchaserTime; + + /** + * 订单最终金额(支付金额) + */ + private BigDecimal finalAmount; + + /** + * 用户ID + */ + private String customId; + + /** + * 用户昵称 + */ + private String customNickname; + + /** + * 用户头像 + */ + private String customAvatar; + + /** + * 用户等级ID + */ + private String customLevelId; + + /** + * 用户等级名称 + */ + private String customLevelName; + + /** + * 店员ID + */ + private String clerkId; + + /** + * 店员昵称 + */ + private String clerkNickname; + + /** + * 店员头像 + */ + private String clerkAvatar; + + /** + * 商品ID + */ + private String commodityId; + + /** + * 商品类型[0:礼物,1:服务] + */ + private String commodityType; + + /** + * 商品类型[0:礼物,1:服务] + */ + private String commodityName; + /** + * 商品单价 + */ + private BigDecimal commodityPrice; + + /** + * 服务时长 + * + * @since 2024/5/8 16:44 + **/ + private String serviceDuration; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/order/PlayClerkRandomOrderDetailReturnVo.java --- +package com.starry.admin.modules.weichat.entity.order; + +import com.fasterxml.jackson.annotation.JsonFormat; +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; +import lombok.Data; + +/** + * 随机单详情返回接口 + * + * @author admin + * @since 2024/5/30 10:00 + **/ +@Data +public class PlayClerkRandomOrderDetailReturnVo { + + /** + * 订单ID + */ + private String id; + + /** + * 订单编号 + */ + private String orderNo; + + /** + * 订单状态【0:1:2:3:4】 0:已下单(待接单) 1:已接单(待开始) 2:已开始(服务中) 3:已完成 4:已取消 + */ + private final String orderStatus = "0"; + + /** + * 下单类型(0:指定单,1:随机单。2:打赏单) + */ + private final String placeType = "1"; + + /** + * 商品数量 + */ + private int commodityNumber; + + /** + * 支付方式,0:余额支付,1:微信支付,2:支付宝支付 + */ + private String payMethod; + + /** + * 订单备注 + */ + private String remark; + + /** + * 买家微信号码 + */ + private String weiChatCode; + + /** + * 卖家要求 + * + * @since 2024/5/30 10:02 + **/ + private List labels; + + /** + * 订单金额 + */ + private BigDecimal orderMoney; + + /** + * 下单时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date purchaserTime; + + /** + * 订单最终金额(支付金额) + */ + private BigDecimal finalAmount; + + /** + * 预计收入 + */ + private BigDecimal estimatedRevenue; + + /** + * 店员收入比例 + */ + private Integer estimatedRevenueRatio; + + /** + * 优惠金额 + */ + private BigDecimal discountAmount; + + /** + * 商品ID + */ + private String commodityId; + + /** + * 商品类型[0:礼物,1:服务] + */ + private String commodityType; + + /** + * 商品名称 + */ + private String commodityName; + /** + * 商品单价 + */ + private BigDecimal commodityPrice; + + /** + * 服务时长 + * + * @since 2024/5/8 16:44 + **/ + private String serviceDuration; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/order/PlayCustomOrderDetailsReturnVo.java --- +package com.starry.admin.modules.weichat.entity.order; + +import com.fasterxml.jackson.annotation.JsonFormat; +import java.math.BigDecimal; +import java.util.Date; +import lombok.Data; + +/** + * 顾客查询订单详情返回对象 + * + * @author admin + * @since 2024-03-20 + */ +@Data +public class PlayCustomOrderDetailsReturnVo { + + /** + * 订单ID + */ + private String id; + + /** + * 订单编号 + */ + private String orderNo; + + /** + * 订单状态【0:1:2:3:4】 0:已下单(待接单) 1:已接单(待开始) 2:已开始(服务中) 3:已完成 4:已取消 + */ + private String orderStatus; + + /** + * 下单类型(0:指定单,1:随机单。2:打赏单) + */ + private String placeType; + + /** + * 商品数量 + */ + private int commodityNumber; + + /** + * 支付方式,0:余额支付,1:微信支付,2:支付宝支付 + */ + private String payMethod; + + /** + * 订单备注 + */ + private String remark; + + /** + * 订单金额 + */ + private BigDecimal orderMoney; + + /** + * 下单时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date purchaserTime; + + /** + * 接单时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date acceptTime; + + /** + * 开始时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date startTime; + + /** + * 结束时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date endTime; + + /** + * 取消时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date cancelTime; + + /** + * 退款人类型[0:顾客;1:店员;2:管理员] + */ + private String refundByType; + + /** + * 退款人ID + */ + private String refundById; + + /** + * 退款原因 + **/ + private String refundReason; + + /** + * 是否评价(1:已评价;0:未评价) + */ + private String evaluate = "0"; + + /** + * 是否投诉(1:已投诉;0:未投诉) + */ + private String complaint = "0"; + + /** + * 订单最终金额(支付金额) + */ + private BigDecimal finalAmount; + + /** + * 优惠金额 + */ + private BigDecimal discountAmount; + + /** + * 用户ID + */ + private String customId; + + /** + * 用户昵称 + */ + private String customNickname; + + /** + * 用户头像 + */ + private String customAvatar; + + /** + * 店员ID + */ + private String clerkId; + + /** + * 店员昵称 + */ + private String clerkNickname; + + /** + * 店员头像 + */ + private String clerkAvatar; + + /** + * 商品ID + */ + private String commodityId; + + /** + * 商品类型[0:礼物,1:服务] + */ + private String commodityType; + + /** + * 商品名称 + */ + private String commodityName; + /** + * 商品单价 + */ + private BigDecimal commodityPrice; + + /** + * 服务时长 + * + * @since 2024/5/8 16:44 + **/ + private String serviceDuration; + + /** + * 微信号码 + * + * @since 2024/5/13 11:29 + **/ + private String weiChatCode; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/order/PlayCustomOrderInfoQueryVo.java --- +package com.starry.admin.modules.weichat.entity.order; + +import com.starry.common.domain.BasePageEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 订单查询对象 + * + * @author admin + * @since 2024-03-20 + */ +@Data +@EqualsAndHashCode(callSuper = false) +public class PlayCustomOrderInfoQueryVo extends BasePageEntity { + + private String id; + /** + * 订单状态【0:1:2:3:4】 0:已下单 1:已接单 2:已开始 3:已完成 4:已取消 + */ + private String orderStatus; + + /** + * 订单类型【0:充值订单;1:提现订单;2:普通订单】 + */ + private String orderType = "2"; + + /** + * 下单类型(0:指定单,1:随机单。2:打赏单) + */ + private String placeType; + + /** + * 下单人 + */ + private String purchaserBy; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/order/PlayCustomOrderListReturnVo.java --- +package com.starry.admin.modules.weichat.entity.order; + +import com.fasterxml.jackson.annotation.JsonFormat; +import java.math.BigDecimal; +import java.util.Date; +import lombok.Data; + +/** + * 顾客查询订单列表返回对象 + * + * @author admin + * @since 2024-03-20 + */ +@Data +public class PlayCustomOrderListReturnVo { + + /** + * 订单ID + */ + private String id; + + /** + * 订单编号 + */ + private String orderNo; + + /** + * 订单状态【0:1:2:3:4】 0:已下单(待接单) 1:已接单(待开始) 2:已开始(服务中) 3:已完成 4:已取消 + */ + private String orderStatus; + + /** + * 下单类型(0:指定单,1:随机单。2:打赏单) + */ + private String placeType; + + /** + * 商品数量 + */ + private int commodityNumber; + + /** + * 订单备注 + */ + private String remark; + + /** + * 下单时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date purchaserTime; + + /** + * 是否评价(1:已评价;0:未评价) + */ + private String evaluate = "0"; + + /** + * 是否投诉(1:已投诉;0:未投诉) + */ + private String complaint = "0"; + + /** + * 订单最终金额(支付金额) + */ + private BigDecimal finalAmount; + + /** + * 用户ID + */ + private String customId; + + /** + * 用户昵称 + */ + private String customNickname; + + /** + * 用户头像 + */ + private String customAvatar; + + /** + * 店员ID + */ + private String clerkId; + + /** + * 店员昵称 + */ + private String clerkNickname; + + /** + * 店员头像 + */ + private String clerkAvatar; + + /** + * 商品ID + */ + private String commodityId; + + /** + * 商品类型[0:礼物,1:服务] + */ + private String commodityType; + + /** + * 商品类型[0:礼物,1:服务] + */ + private String commodityName; + /** + * 商品单价 + */ + private BigDecimal commodityPrice; + + /** + * 服务时长 + * + * @since 2024/5/8 16:44 + **/ + private String serviceDuration; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/order/PlayOrderHistoryRankingReturnVo.java --- +package com.starry.admin.modules.weichat.entity.order; + +import java.time.LocalDate; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 订单排行分页查询对象 + * + * @author admin + * @since 2024/5/25 下午10:27 + **/ +@Data +public class PlayOrderHistoryRankingReturnVo { + + /** + * 开始统计时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd") + private LocalDate startCountDate; + + /** + * 结束统计时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd") + private LocalDate endCountDate; + + /** + * 排序名次 + */ + private Long rankingIndex; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/order/PlayOrderInfoCommodityAdd.java --- +package com.starry.admin.modules.weichat.entity.order; + +import com.starry.admin.modules.shop.module.constant.GiftConstant; +import java.util.List; +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +/** + * 新增赠礼订单实体 + * + * @author admin + */ +@Data +public class PlayOrderInfoCommodityAdd { + + /** + * 店员用户ID + */ + @NotBlank(message = "打赏对象不能为空") + private String clerkId; + + @NotBlank(message = "商品ID不能为空") + private String commodityId; + + @NotNull(message = "数量不能为空") + @Min(value = GiftConstant.MINIMUM_SINGLE_GIFT_QUANTITY, message = "数量不能小于" + + GiftConstant.MINIMUM_SINGLE_GIFT_QUANTITY) + @Max(value = GiftConstant.MAXIMUM_SINGLE_GIFT_QUANTITY, message = "数量不能大于" + + GiftConstant.MAXIMUM_SINGLE_GIFT_QUANTITY) + private int commodityQuantity; + + @NotBlank(message = "微信号不能为空") + @Length(max = 255, message = "微信号码长度不超过255个字符") + private String weiChatCode; + + /** + * 优惠券ID列表 + */ + private List couponIds; + + /** + * 备注 + */ + private String remark; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/order/PlayOrderInfoContinueAdd.java --- +package com.starry.admin.modules.weichat.entity.order; + +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import lombok.Data; + +/** + * 续单申请 + * + * @author admin + */ +@Data +public class PlayOrderInfoContinueAdd { + + /** + * orderId + */ + @NotBlank(message = "orderId不能为空") + private String orderId; + + /** + * 订单备注 + */ + private String remark; + + /** + * 图片列表 + */ + @NotNull(message = "images不能为空") + @Size(min = 1, max = 6, message = "图片张数必须大于1张且小于6张") + private List images; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/order/PlayOrderInfoContinueQueryVo.java --- +package com.starry.admin.modules.weichat.entity.order; + +import com.starry.common.domain.BasePageEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 续单申请列表查询 + * + * @author admin + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class PlayOrderInfoContinueQueryVo extends BasePageEntity { + + /** + * 顾客ID + */ + private String customId; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/order/PlayOrderInfoRandomQueryVo.java --- +package com.starry.admin.modules.weichat.entity.order; + +import com.starry.common.domain.BasePageEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 待接单大厅 + * + * @author admin + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class PlayOrderInfoRandomQueryVo extends BasePageEntity { + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/order/PlayOrderInfoRandomReturnVo.java --- +package com.starry.admin.modules.weichat.entity.order; + +import com.fasterxml.jackson.annotation.JsonFormat; +import java.math.BigDecimal; +import java.util.Date; + +/** + * @author admin + * @since 2024/5/30 9:22 + **/ +public class PlayOrderInfoRandomReturnVo { + + /** + * 订单ID + */ + private String id; + + /** + * 订单编号 + */ + private String orderNo; + + /** + * 订单状态【0:1:2:3:4】 0:已下单(待接单) 1:已接单(待开始) 2:已开始(服务中) 3:已完成 4:已取消 + */ + private final String orderStatus = "0"; + + /** + * 下单类型(0:指定单,1:随机单。2:打赏单) + */ + private final String placeType = "1"; + + /** + * 商品数量 + */ + private int commodityNumber; + + /** + * 订单备注 + */ + private String remark; + + /** + * 下单时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date purchaserTime; + + /** + * 订单最终金额(支付金额) + */ + private BigDecimal finalAmount; + + /** + * 用户ID + */ + private String customId; + + /** + * 用户昵称 + */ + private String customNickname; + + /** + * 用户头像 + */ + private String customAvatar; + + /** + * 用户等级ID + */ + private String customLevelId; + + /** + * 用户等级名称 + */ + private String customLevelName; + + /** + * 店员ID + */ + private String clerkId; + + /** + * 店员昵称 + */ + private String clerkNickname; + + /** + * 店员头像 + */ + private String clerkAvatar; + + /** + * 商品ID + */ + private String commodityId; + + /** + * 商品类型[0:礼物,1:服务] + */ + private String commodityType; + + /** + * 商品类型[0:礼物,1:服务] + */ + private String commodityName; + /** + * 商品单价 + */ + private BigDecimal commodityPrice; + + /** + * 服务时长 + * + * @since 2024/5/8 16:44 + **/ + private String serviceDuration; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/order/PlayOrderRankingListVo.java --- +package com.starry.admin.modules.weichat.entity.order; + +import lombok.Data; + +/** + * 订单排行分页查询对象 + * + * @author admin + * @since 2024/5/25 下午10:27 + **/ +@Data +public class PlayOrderRankingListVo { + + /** + * 店员ID + */ + private String clerkId; + + /** + * 店员昵称 + */ + private String clerkNickname; + + /** + * 店员头像 + */ + private String clerkAvatar; + + /** + * 店员等级ID + */ + private String levelId; + + /** + * 店员等级名称 + */ + private String levelName; + + /** + * 店员性别 + */ + private String clerkSex; + + /** + * 排序名次 + */ + private Long rankingIndex; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/order/PlayOrderRankingQueryVo.java --- +package com.starry.admin.modules.weichat.entity.order; + +import com.starry.common.domain.BasePageEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 订单排行分页查询对象 + * + * @author admin + * @since 2024/5/25 下午10:27 + **/ +@EqualsAndHashCode(callSuper = true) +@Data +public class PlayOrderRankingQueryVo extends BasePageEntity { + + private String clerkId; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/order/PlayOrderRankingReturnVo.java --- +package com.starry.admin.modules.weichat.entity.order; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.List; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 订单排行分页查询对象 + * + * @author admin + * @since 2024/5/25 下午10:27 + **/ +@Data +public class PlayOrderRankingReturnVo { + + /** + * UUID + */ + private String id; + + /** + * 店员ID + */ + private String clerkId; + + /** + * 店员昵称 + */ + private String clerkNickname; + + /** + * 店员头像 + */ + private String clerkAvatar; + + /** + * 店员等级ID + */ + private String levelId; + + /** + * 店员等级名称 + */ + private String levelName; + + /** + * 店员性别 + */ + private String clerkSex; + + /** + * 开始统计时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd") + private LocalDate startCountDate; + + /** + * 结束统计时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd") + private LocalDate endCountDate; + + /** + * 是否是当前排名 + */ + private String currentRanking; + + /** + * 订单总数 + */ + private String orderNumber; + + /** + * 订单金额 + */ + private BigDecimal orderMoney; + + /** + * 续单数 + */ + private Long orderContinueNumber; + + /** + * 续单金额 + */ + private BigDecimal orderContinueMoney; + + /** + * 超时未接单数量 + */ + private Long ordersExpiredNumber; + + /** + * 距离前一名相差金额 + */ + private BigDecimal previousMoney; + + /** + * 排序列表 + */ + private List rankings; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/order/PlayRandomOrderInfoReturnVo.java --- +package com.starry.admin.modules.weichat.entity.order; + +import com.fasterxml.jackson.annotation.JsonFormat; +import java.math.BigDecimal; +import java.util.Date; +import lombok.Data; + +/** + * @author admin + * @since 2024/6/1 下午11:20 + **/ +@Data +public class PlayRandomOrderInfoReturnVo { + + /** + * 订单ID + */ + private String id; + + /** + * 订单编号 + */ + private String orderNo; + + /** + * 订单状态【0:1:2:3:4】 0:已下单(待接单) 1:已接单(待开始) 2:已开始(服务中) 3:已完成 4:已取消 + */ + private String orderStatus; + + /** + * 下单类型(0:指定单,1:随机单。2:打赏单) + */ + private String placeType; + + /** + * 是否是首单【0:不是,1:是】 + */ + private String firstOrder; + + /** + * 商品数量 + */ + private int commodityNumber; + + /** + * 订单备注 + */ + private String remark; + + /** + * 下单时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date purchaserTime; + + /** + * 订单最终金额(支付金额) + */ + private BigDecimal finalAmount; + + /** + * 用户ID + */ + private String customId; + + /** + * 用户昵称 + */ + private String customNickname; + + /** + * 用户头像 + */ + private String customAvatar; + + /** + * 用户等级ID + */ + private String customLevelId; + + /** + * 用户等级名称 + */ + private String customLevelName; + + /** + * 商品ID + */ + private String commodityId; + + /** + * 商品类型[0:礼物,1:服务] + */ + private String commodityType; + + /** + * 商品名称 + */ + private String commodityName; + /** + * 商品单价 + */ + private BigDecimal commodityPrice; + + /** + * 服务时长 + * + * @since 2024/5/8 16:44 + **/ + private String serviceDuration; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/order/PlayRewardInfoReturnVo.java --- +package com.starry.admin.modules.weichat.entity.order; + +import com.fasterxml.jackson.annotation.JsonFormat; +import java.math.BigDecimal; +import java.util.Date; +import lombok.Data; + +/** + * 打赏动态查询返回信息 + * + * @author admin + * @since 2024/5/25 下午7:49 + **/ +@Data +public class PlayRewardInfoReturnVo { + + /** + * UUID + */ + private String id; + + /** + * 店员ID + */ + private String clerkId; + + /** + * 店员昵称 + */ + private String clerkNickname; + + /** + * 店员头像 + */ + private String clerkAvatar; + + /** + * 打赏类型(0:余额;1:礼物) + */ + private String rewardType; + + /** + * 商品数量 + */ + private String commodityNumber; + + /** + * 商品名称 + */ + private String commodityName; + + /** + * 订单金额 + */ + private BigDecimal orderMoney; + + /** + * 下单时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date purchaserTime; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/order/PlayRewardOrderQueryVo.java --- +package com.starry.admin.modules.weichat.entity.order; + +import com.starry.common.domain.BasePageEntity; + +/** + * 打赏动态分页查询对象 + * + * @author admin + * @since 2024/5/25 下午7:36 + **/ +public class PlayRewardOrderQueryVo extends BasePageEntity { +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/shop/ShopHomeCarouseInfoReturnVo.java --- +package com.starry.admin.modules.weichat.entity.shop; + +import lombok.Data; + +/** + * @author admin + * @since 2024/6/5 下午4:40 + **/ +@Data +public class ShopHomeCarouseInfoReturnVo { + + /** + * 图片URL + */ + private String carouselUrl; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/user/PlayCustomUserReturnDetailVo.java --- +package com.starry.admin.modules.weichat.entity.user; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import java.math.BigDecimal; +import java.util.Date; +import lombok.Data; + +/** + * @author admin + * @since 2024/5/28 下午5:07 + **/ +@Data +public class PlayCustomUserReturnDetailVo { + /** + * UUID + */ + private String id; + /** + * 租户ID + */ + private String tenantId; + /** + * 用户的标识,对当前公众号唯一 + */ + private String openid; + /** + * 用户的标识,对当前公众号唯一 + */ + private String unionid; + /** + * 顾客昵称 + */ + private String nickname; + /** + * 顾客性别(0:未知;1:男,2:女) + */ + private Integer sex; + /** + * 头像 + */ + private String avatar; + /** + * 手机号码 + */ + private String phone; + /** + * 微信号码 + */ + private String weiChatCode; + /** + * 等级ID + */ + private String levelId; + /** + * 所在国家 + */ + private String country; + /** + * 所在省份 + */ + private String province; + /** + * 所在城市 + */ + private String city; + /** + * 账户余额 + */ + private BigDecimal accountBalance; + /** + * 余额状态[0:不存在余额,1:存在余额] + */ + private String accountState; + /** + * 关注状态[0:未关注,1:已关注] + */ + private String subscribeState; + /** + * 黑名单状态[0:非黑名单,1:黑名单] + */ + private String blacklistState; + /** + * 违规状态[0:未违规,1:违规] + */ + private String violationState; + /** + * 是否下单状态[0:未下单过,1:下单过] + */ + private String purchaseState; + /** + * 绑定手机状态[0:未绑定,1:绑定] + */ + private String mobilePhoneState; + /** + * 实名状态【1:已实名,0:未实名】 + */ + private String realState; + /** + * 是否必须实名【2:跟随店铺设置,1:必须实名,0:非必须实名】 + */ + private String mandatoryRealState; + /** + * 注册时间 + */ + private Date registrationTime; + /** + * 上次登录时间 + */ + private Date lastLoginTime; + /** + * 首次下单时间 + */ + private Date firstPurchaseTime; + /** + * 最后一次下单时间 + */ + private Date lastPurchaseTime; + /** + * 隐藏等级[0:不隐藏;1:隐藏] + */ + private String hideLevelState; + /** + * 隐藏排名[0:不隐藏;1:隐藏] + */ + private String hideRankingState; + /** + * 备注 + */ + private String remark; + /** + * 最近一次登录token + */ + @JsonIgnore + private String token; + + /** + * 员工状态【1:是陪聊,0:不是陪聊】 + */ + public String clerkState = "0"; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/vo/PlayCustomLevelInfoReturnVo.java --- +package com.starry.admin.modules.weichat.entity.vo; + +import lombok.Data; + +/** + * @author admin + * @since 2024/5/21 下午10:18 + **/ +@Data +public class PlayCustomLevelInfoReturnVo { + + /** + * 等级名称 + */ + private String name; + + /** + * 等级数字(排序字段) + */ + private Integer level; + + /** + * 上一级消费金额 + */ + private String consumptionAmount; + + /** + * 满减比例 + */ + private Integer discount; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/wages/ClerkCurrentPeriodWagesReturnVo.java --- +package com.starry.admin.modules.weichat.entity.wages; + +import com.fasterxml.jackson.annotation.JsonFormat; +import java.math.BigDecimal; +import java.time.LocalDate; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * @author admin + * @since 2024/6/1 上午11:44 + **/ +@Data +public class ClerkCurrentPeriodWagesReturnVo { + + /** + * UUID + */ + private String id; + + /** + * 总金额 + */ + private BigDecimal totalMoney; + + /** + * 开始统计时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private LocalDate startCountDate; + + /** + * 结束统计时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private LocalDate endCountDate; + + /** + * 平台工资(订单) + */ + private OrderWagesReturnVo orderWages; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/wages/ClerkHistoricalWagesReturnVo.java --- +package com.starry.admin.modules.weichat.entity.wages; + +import com.fasterxml.jackson.annotation.JsonFormat; +import java.math.BigDecimal; +import java.time.LocalDate; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * @author admin + * @since 2024/6/1 上午11:44 + **/ +@Data +public class ClerkHistoricalWagesReturnVo { + + /** + * UUID + */ + private String id; + + /** + * 订单金额 + */ + private BigDecimal orderMoney; + + /** + * 开始统计时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private LocalDate startCountDate; + + /** + * 结束统计时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private LocalDate endCountDate; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/wages/ClerkUnsettledWagesReturnVo.java --- +package com.starry.admin.modules.weichat.entity.wages; + +import java.math.BigDecimal; +import lombok.Data; + +/** + * @author admin + * @since 2024/6/1 下午1:52 + **/ +@Data +public class ClerkUnsettledWagesReturnVo { + + /** + * 订单金额 + */ + private BigDecimal orderMoney; + + /** + * 订单总数 + */ + private Integer orderNumber; + + /** + * 预计收入 + */ + private BigDecimal estimatedRevenue; + + public ClerkUnsettledWagesReturnVo(BigDecimal orderMoney, Integer orderNumber, BigDecimal estimatedRevenue) { + this.orderMoney = orderMoney; + this.orderNumber = orderNumber; + this.estimatedRevenue = estimatedRevenue; + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/wages/ClerkWagesDetailsReturnVo.java --- +package com.starry.admin.modules.weichat.entity.wages; + +import com.fasterxml.jackson.annotation.JsonFormat; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * @author admin + * @since 2024/6/1 下午1:22 + **/ +@Data +public class ClerkWagesDetailsReturnVo { + /** + * UUID + */ + private String id; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 工资统计ID + */ + private Long wagesId; + + /** + * 店员ID + */ + private String clerkId; + + /** + * 订单ID + */ + private String orderId; + + /** + * 订单编号 + */ + private String orderNo; + + /** + * 订单最终金额(支付金额) + */ + private BigDecimal finalAmount; + + /** + * 订单工资 + */ + private BigDecimal estimatedRevenue; + + /** + * 订单完成时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime endOrderTime; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/entity/wages/OrderWagesReturnVo.java --- +package com.starry.admin.modules.weichat.entity.wages; + +import java.math.BigDecimal; +import lombok.Data; + +/** + * @author admin + * @since 2024/6/1 上午11:44 + **/ +@Data +public class OrderWagesReturnVo { + + /** + * 订单总数 + */ + private Integer orderNumber = 0; + + /** + * 订单金额 + */ + private BigDecimal orderMoney = BigDecimal.ZERO; + + /** + * 续单数 + */ + private Integer orderContinueNumber = 0; + + /** + * 续单比例 + */ + private double orderContinueProportion = 0.0; + + /** + * 续单金额 + */ + private BigDecimal orderContinueMoney = BigDecimal.ZERO; + + /** + * 超时未接单数 + */ + private Integer ordersExpiredNumber = 0; + + /** + * 店员收入 + */ + private BigDecimal estimatedRevenue = BigDecimal.ZERO; + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/service/Constants.java --- +package com.starry.admin.modules.weichat.service; + +import io.jsonwebtoken.Claims; + +/** + * 通用常量信息 + * + * @author ruoyi + */ +public class Constants { + /** + * UTF-8 字符集 + */ + public static final String UTF8 = "UTF-8"; + + /** + * GBK 字符集 + */ + public static final String GBK = "GBK"; + + /** + * www主域 + */ + public static final String WWW = "www."; + + /** + * http请求 + */ + public static final String HTTP = "http://"; + + /** + * https请求 + */ + public static final String HTTPS = "https://"; + + /** + * 通用成功标识 + */ + public static final String SUCCESS = "0"; + + /** + * 通用失败标识 + */ + public static final String FAIL = "1"; + + /** + * 登录成功 + */ + public static final String LOGIN_SUCCESS = "Success"; + + /** + * 注销 + */ + public static final String LOGOUT = "Logout"; + + public static final String CHANGE_PHONE = "CHANGE_PHONE"; + + /** + * 注册 + */ + public static final String REGISTER = "Register"; + + /** + * 登录失败 + */ + public static final String LOGIN_FAIL = "Error"; + + /** + * 验证码有效期(分钟) + */ + public static final Integer CAPTCHA_EXPIRATION = 2; + + /** + * 令牌 + */ + public static final String TOKEN = "token"; + + /** + * 令牌前缀 + */ + public static final String TOKEN_PREFIX = "Bearer "; + + public static final String MINI_USER_LOGIN_TOKEN = "usertoken"; + public static final String MINI_COSER_LOGIN_TOKEN = "cosertoken"; + + /** + * 令牌前缀 + */ + public static final String LOGIN_USER_KEY = "login_user_key"; + public static final String LOGIN_USER_KEY_WX = "login_user_key_wx"; + public static final String LOGIN_USER_KEY_COSER = "login_user_key_coser"; + + /** + * 用户ID + */ + public static final String JWT_USERID = "userid"; + + /** + * 用户名称 + */ + public static final String JWT_USERNAME = Claims.SUBJECT; + + /** + * 用户头像 + */ + public static final String JWT_AVATAR = "avatar"; + + /** + * 创建时间 + */ + public static final String JWT_CREATED = "created"; + + /** + * 用户权限 + */ + public static final String JWT_AUTHORITIES = "authorities"; + + /** + * 资源映射路径 前缀 + */ + public static final String RESOURCE_PREFIX = "/profile"; + + public static final String MINI_USER_DE_AVATAR = "https://live-cloud-cvoon.oss-cn-hangzhou.aliyuncs.com/cdn/img/1881712023451_.pic.jpg"; + public static final String MINI_COSER_DE_AVATAR = "https://live-cloud-cvoon.oss-cn-hangzhou.aliyuncs.com/cdn/img/1891712023452_.pic.jpg"; + + /** + * RMI 远程方法调用 + */ + public static final String LOOKUP_RMI = "rmi:"; + + /** + * LDAP 远程方法调用 + */ + public static final String LOOKUP_LDAP = "ldap:"; + + /** + * LDAPS 远程方法调用 + */ + public static final String LOOKUP_LDAPS = "ldaps:"; + + /** + * 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加) + */ + public static final String[] JOB_WHITELIST_STR = {"com.ruoyi"}; + + /** + * 定时任务违规的字符 + */ + public static final String[] JOB_ERROR_STR = {"java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml", + "org.springframework", "org.apache", "com.ruoyi.common.utils.file", "com.ruoyi.common.config"}; +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/service/WxAccessTokenService.java --- +package com.starry.admin.modules.weichat.service; + +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.error.WxErrorException; +import org.springframework.stereotype.Service; + +/** + * 微信公众号开发 + * + * @author admin + */ +@Slf4j +@Service +public class WxAccessTokenService { + + @Resource + private WxCustomMpService wxCustomMpService; + + /** + * 获取微信AccessToken + * + * @return access_token + */ + public String getAccessToken() throws WxErrorException { + String token = wxCustomMpService.proxyWxMpService().getAccessToken(); + log.error("token = " + token); + // 缓存业务处理 + return token; + + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/service/WxCustomMpService.java --- +package com.starry.admin.modules.weichat.service; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.github.binarywang.wxpay.config.WxPayConfig; +import com.github.binarywang.wxpay.service.WxPayService; +import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl; +import com.starry.admin.common.exception.CustomException; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserReviewInfoEntity; +import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService; +import com.starry.admin.modules.custom.module.entity.PlayCustomUserInfoEntity; +import com.starry.admin.modules.custom.service.IPlayCustomUserInfoService; +import com.starry.admin.modules.order.module.entity.PlayOrderComplaintInfoEntity; +import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity; +import com.starry.admin.modules.personnel.module.entity.PlayPersonnelAdminInfoEntity; +import com.starry.admin.modules.personnel.service.IPlayPersonnelAdminInfoService; +import com.starry.admin.modules.system.module.entity.SysTenantEntity; +import com.starry.admin.modules.system.service.impl.SysTenantServiceImpl; +import com.starry.admin.utils.SecurityUtils; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Objects; +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.template.WxMpTemplateData; +import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage; +import me.chanjar.weixin.mp.config.impl.WxMpMapConfigImpl; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +/** + * @author admin + */ +@Slf4j +@Service +public class WxCustomMpService { + + @Resource + private WxMpService wxMpService; + + @Resource + private SysTenantServiceImpl tenantService; + @Resource + private IPlayCustomUserInfoService customUserInfoService; + @Resource + private IPlayPersonnelAdminInfoService playPersonnelAdminInfoService; + @Resource + private IPlayClerkUserInfoService clerkUserInfoService; + + /** + * 支付成功回调地址 + */ + public static String NOTIFY_URL = "https://julyharbor.com/api/wx/pay/jsCallback"; + + public WxMpService proxyWxMpService() { + String tenantId = SecurityUtils.getTenantId(); + if (StrUtil.isBlankIfStr(tenantId)) { + throw new CustomException("系统错误,租户ID不能为空"); + } + SysTenantEntity entity = tenantService.selectSysTenantByTenantId(tenantId); + if (entity == null) { + throw new CustomException("系统错误,租户ID不能为空"); + } + WxMpMapConfigImpl config = new WxMpMapConfigImpl(); + config.setAppId(entity.getAppId()); + config.setSecret(entity.getSecret()); + wxMpService.addConfigStorage(entity.getAppId(), config); + return wxMpService.switchoverTo(entity.getAppId()); + } + + public WxPayService getWxPay() { + String tenantId = SecurityUtils.getTenantId(); + if (StrUtil.isBlankIfStr(tenantId)) { + throw new CustomException("系统错误,租户ID不能为空"); + } + SysTenantEntity entity = tenantService.selectSysTenantByTenantId(tenantId); + if (entity == null) { + throw new CustomException("系统错误,租户ID不能为空"); + } + if (StringUtils.isEmpty(entity.getMchId())) { + throw new CustomException("商户号不能为空,请联系平台方进行配置"); + } + WxPayConfig payConfig = new WxPayConfig(); + payConfig.setAppId(StringUtils.trimToNull(entity.getAppId())); + payConfig.setMchId(StringUtils.trimToNull(entity.getMchId())); + payConfig.setMchKey(StringUtils.trimToNull(entity.getMchKey())); + + payConfig.setNotifyUrl(StringUtils.trimToNull(NOTIFY_URL)); + payConfig.setTradeType("JSAPI"); + payConfig.setSignType("MD5"); + // 可以指定是否使用沙箱环境 + payConfig.setUseSandboxEnv(false); + WxPayService wxPayService = new WxPayServiceImpl(); + wxPayService.setConfig(payConfig); + return wxPayService; + } + + /** + * 充值成功-发送微信消息 + * + * @param order + * 订单信息 + */ + public void sendBalanceMessage(PlayOrderInfoEntity order) { + PlayCustomUserInfoEntity customUserInfo = customUserInfoService.selectById(order.getPurchaserBy()); + SysTenantEntity tenant = tenantService.selectSysTenantByTenantId(order.getTenantId()); + WxMpTemplateMessage templateMessage = getWxMpTemplateMessage(tenant.getChongzhichenggongTemplateId(), + customUserInfo.getOpenid(), "http://" + tenant.getTenantKey() + ".julyharbor.com/user/"); + List data = new ArrayList<>(); + data.add(new WxMpTemplateData("time4", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"))); + data.add(new WxMpTemplateData("amount2", order.getOrderMoney().toString())); + data.add(new WxMpTemplateData("amount17", "0")); + data.add(new WxMpTemplateData("thing10", tenant.getTenantName())); + templateMessage.setData(data); + try { + proxyWxMpService().getTemplateMsgService().sendTemplateMsg(templateMessage); + } catch (WxErrorException e) { + log.error("充值成功发送消息异常", e); + } + } + + /** + * 顾客下指定单后,给店员发新订单通知 通过微信公众号发送消息 + * + * @param tenantId + * 租户ID + * @param openId + * 消息接收人openID + * @param orderNo + * 消息内容-订单编号 + * @param money + * @param commodityName + */ + public void sendCreateOrderMessage(String tenantId, String openId, String orderNo, String money, + String commodityName) { + + SysTenantEntity tenant = tenantService.selectSysTenantByTenantId(tenantId); + WxMpTemplateMessage templateMessage = getWxMpTemplateMessage(tenant.getXindingdanshoulitongzhiTemplateId(), + openId, "http://" + tenant.getTenantKey() + ".julyharbor.com/clerk/#/orderDetail/"); + List data = new ArrayList<>(); + data.add(new WxMpTemplateData("time6", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"))); + data.add(new WxMpTemplateData("character_string9", orderNo)); + data.add(new WxMpTemplateData("short_thing5", "陪聊下单")); + data.add(new WxMpTemplateData("thing11", commodityName)); + data.add(new WxMpTemplateData("amount8", money)); + templateMessage.setData(data); + try { + proxyWxMpService().getTemplateMsgService().sendTemplateMsg(templateMessage); + } catch (WxErrorException e) { + log.error("接单成功发送消息异常", e); + } + + } + + /** + * 店员接单后,通过微信公众号发送消息 + * + * @param orderInfo + * @author admin + * @since 2024/7/31 10:51 + **/ + public void sendOrderMessage(PlayOrderInfoEntity orderInfo) { + SysTenantEntity tenant = tenantService.selectSysTenantByTenantId(orderInfo.getTenantId()); + PlayClerkUserInfoEntity clerkUserInfo = clerkUserInfoService.selectById(orderInfo.getAcceptBy()); + PlayCustomUserInfoEntity customUserInfo = customUserInfoService.selectById(orderInfo.getPurchaserBy()); + + WxMpTemplateMessage templateMessage = getWxMpTemplateMessage(tenant.getJiedanchenggongtongzhiTemplateId(), + clerkUserInfo.getOpenid(), + "http://" + tenant.getTenantKey() + ".julyharbor.com/clerk/#/orderDetail/" + orderInfo.getId()); + List data = new ArrayList<>(); + data.add(new WxMpTemplateData("character_string1", orderInfo.getOrderNo())); + data.add(new WxMpTemplateData("time2", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"))); + templateMessage.setData(data); + try { + proxyWxMpService().getTemplateMsgService().sendTemplateMsg(templateMessage); + } catch (WxErrorException e) { + log.error(e.getMessage(), e); + } + + templateMessage.setToUser(customUserInfo.getOpenid()); + templateMessage + .setUrl("http://" + tenant.getTenantKey() + ".julyharbor.com/user/#/orderDetail/" + orderInfo.getId()); + try { + proxyWxMpService().getTemplateMsgService().sendTemplateMsg(templateMessage); + } catch (WxErrorException e) { + log.error(e.getMessage(), e); + } + + } + + public void sendCheckMessage(PlayClerkUserReviewInfoEntity entity, PlayClerkUserInfoEntity userInfo, + String reviewState) { + String touser = userInfo.getOpenid(); + + SysTenantEntity tenant = tenantService.selectSysTenantByTenantId(userInfo.getTenantId()); + String template_id = tenant.getRzsqshtxTemplateId(); + String tenantKey = tenant.getTenantKey(); + String url = "http://" + tenantKey + ".julyharbor.com/clerk/"; + + WxMpTemplateMessage templateMessage = new WxMpTemplateMessage(); + templateMessage.setTemplateId(template_id); + templateMessage.setToUser(touser); + templateMessage.setUrl(url); + List data = new ArrayList<>(); + data.add(new WxMpTemplateData("short_thing7", reviewState.equals("1") ? "通过" : "拒绝")); + data.add(new WxMpTemplateData("thing2", entity.getNickname())); + data.add(new WxMpTemplateData("thing11", entity.getWeiChatCode())); + data.add(new WxMpTemplateData("time8", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"))); + templateMessage.setData(data); + try { + proxyWxMpService().getTemplateMsgService().sendTemplateMsg(templateMessage); + } catch (WxErrorException e) { + log.error(e.getMessage(), e); + + } + + } + + public void sendClerkApplyNoticeForAdmin(PlayClerkUserReviewInfoEntity entity, String tenantId) { + SysTenantEntity tenant = tenantService.selectSysTenantByTenantId(tenantId); + String template_id = tenant.getRzsqAdminTemplateId(); + String tenantKey = tenant.getTenantKey(); + String url = "http://" + tenantKey + ".julyharbor.com/clerk/#/admin/clerk-apply-list"; + List adminInfoEntityList = playPersonnelAdminInfoService.list(Wrappers + .lambdaQuery(PlayPersonnelAdminInfoEntity.class).select(PlayPersonnelAdminInfoEntity::getSysUserId)); + for (PlayPersonnelAdminInfoEntity adminInfoEntity : adminInfoEntityList) { + PlayClerkUserInfoEntity clerkUserInfo = clerkUserInfoService + .getOne(Wrappers.lambdaQuery(PlayClerkUserInfoEntity.class) + .eq(PlayClerkUserInfoEntity::getSysUserId, adminInfoEntity.getSysUserId()), false); + if (Objects.isNull(clerkUserInfo)) { + continue; + } + WxMpTemplateMessage templateMessage = new WxMpTemplateMessage(); + templateMessage.setTemplateId(template_id); + templateMessage.setToUser(clerkUserInfo.getOpenid()); + templateMessage.setUrl(url); + List data = new ArrayList<>(); + data.add(new WxMpTemplateData("phone_number15", entity.getPhone())); + data.add(new WxMpTemplateData("thing11", entity.getNickname())); + // data.add(new WxMpTemplateData("thing3", "有新的店员提交了审核,请前去查看")); + data.add(new WxMpTemplateData("thing2", "有新的店员提交了审核,请前去查看")); + templateMessage.setData(data); + try { + proxyWxMpService().getTemplateMsgService().sendTemplateMsg(templateMessage); + } catch (WxErrorException e) { + log.error(e.getMessage(), e); + + } + } + + } + + /** + * 获取微信发啥消息模板 + * + * @param templateId + * 消息模板ID + * @param toUser + * 发送目标用户ID + * @param url + * 消息回调地址 + * @return WxMpTemplateMessage + */ + public WxMpTemplateMessage getWxMpTemplateMessage(String templateId, String toUser, String url) { + WxMpTemplateMessage templateMessage = new WxMpTemplateMessage(); + templateMessage.setTemplateId(templateId); + templateMessage.setToUser(toUser); + templateMessage.setUrl(url); + return templateMessage; + } + + public void sendComplaintMessage(PlayOrderComplaintInfoEntity info, PlayOrderInfoEntity orderInfo) { + + SysTenantEntity tenant = tenantService.selectSysTenantByTenantId(info.getTenantId()); + List adminInfoEntityList = playPersonnelAdminInfoService.list(Wrappers + .lambdaQuery(PlayPersonnelAdminInfoEntity.class).select(PlayPersonnelAdminInfoEntity::getSysUserId)); + + for (PlayPersonnelAdminInfoEntity adminInfo : adminInfoEntityList) { + PlayClerkUserInfoEntity clerkUserInfo = clerkUserInfoService + .getOne(Wrappers.lambdaQuery(PlayClerkUserInfoEntity.class) + .eq(PlayClerkUserInfoEntity::getSysUserId, adminInfo.getSysUserId()), false); + if (Objects.isNull(clerkUserInfo)) { + continue; + } + WxMpTemplateMessage templateMessage = getWxMpTemplateMessage(tenant.getDingdantousuchuliTemplateId(), + clerkUserInfo.getOpenid(), + "http://" + tenant.getTenantKey() + ".julyharbor.com/clerk/#/admin/order/complain-list"); + List data = new ArrayList<>(); + data.add(new WxMpTemplateData("character_string", orderInfo.getOrderNo())); + data.add(new WxMpTemplateData("time2", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"))); + templateMessage.setData(data); + try { + proxyWxMpService().getTemplateMsgService().sendTemplateMsg(templateMessage); + } catch (WxErrorException e) { + log.error("发送投诉消息异常", e); + } + } + + } + + public void sendOrderFinishMessage(PlayOrderInfoEntity order) { + if (order.getPlaceType().equals("1") || order.getPlaceType().equals("2")) { + SysTenantEntity tenant = tenantService.selectSysTenantByTenantId(order.getTenantId()); + PlayCustomUserInfoEntity customUserInfo = customUserInfoService.selectById(order.getPurchaserBy()); + WxMpTemplateMessage templateMessage = getWxMpTemplateMessage(tenant.getDingdanwanchengtongzhiTemplateId(), + customUserInfo.getOpenid(), + "http://" + tenant.getTenantKey() + ".julyharbor.com/user/#/orderDetail/" + order.getId()); + List data = new ArrayList<>(); + data.add(new WxMpTemplateData("time18", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"))); + data.add(new WxMpTemplateData("character_string8", order.getOrderNo())); + data.add(new WxMpTemplateData("thing13", order.getCommodityName())); + templateMessage.setData(data); + try { + proxyWxMpService().getTemplateMsgService().sendTemplateMsg(templateMessage); + } catch (WxErrorException e) { + log.error("订单完成发送消息异常", e); + } + } + + } + + public void sendOrderCancelMessage(PlayOrderInfoEntity orderInfo, String refundReason) { + SysTenantEntity tenant = tenantService.selectSysTenantByTenantId(orderInfo.getTenantId()); + + PlayCustomUserInfoEntity customUserInfo = customUserInfoService.selectById(orderInfo.getPurchaserBy()); + + WxMpTemplateMessage templateMessage = getWxMpTemplateMessage(tenant.getQuxiaodingdantongzhiTemplateId(), + customUserInfo.getOpenid(), + "http://" + tenant.getTenantKey() + ".julyharbor.com/user/#/orderDetail/" + orderInfo.getId()); + List data = new ArrayList<>(); + data.add(new WxMpTemplateData("character_string2", orderInfo.getOrderNo())); + data.add(new WxMpTemplateData("thing5", StringUtils.isEmpty(refundReason) ? "已取消" : refundReason)); + data.add(new WxMpTemplateData("time18", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"))); + templateMessage.setData(data); + try { + proxyWxMpService().getTemplateMsgService().sendTemplateMsg(templateMessage); + } catch (WxErrorException e) { + log.error(e.getMessage(), e); + } + + if (StringUtils.isNotEmpty(orderInfo.getAcceptBy())) { + PlayClerkUserInfoEntity clerkUserInfo = clerkUserInfoService.selectById(orderInfo.getAcceptBy()); + + templateMessage.setToUser(clerkUserInfo.getOpenid()); + templateMessage.setUrl( + "http://" + tenant.getTenantKey() + ".julyharbor.com/clerk/#/orderDetail/" + orderInfo.getId()); + try { + proxyWxMpService().getTemplateMsgService().sendTemplateMsg(templateMessage); + } catch (WxErrorException e) { + log.error(e.getMessage(), e); + } + } + + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/service/WxCustomUserService.java --- +package com.starry.admin.modules.weichat.service; + +import com.starry.admin.modules.custom.module.entity.PlayCustomUserInfoEntity; +import com.starry.admin.modules.custom.service.IPlayCustomUserInfoService; +import com.starry.common.constant.Constants; +import com.starry.common.utils.StringUtils; +import java.util.Objects; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +public class WxCustomUserService { + + @Resource + private IPlayCustomUserInfoService customUserInfoService; + + @Resource + private HttpServletRequest request; + + @Resource + private WxTokenService tokenService; + + /** + * 获取当前登录顾客ID + * + * @return 当前登录顾客ID + */ + public String getLoginUserId() { + String userToken = request.getHeader(com.starry.common.constant.Constants.CUSTOM_USER_LOGIN_TOKEN); + if (StringUtils.isEmpty(userToken)) { + return ""; + } + if (userToken.startsWith(com.starry.common.constant.Constants.TOKEN_PREFIX)) { + userToken = userToken.replace(Constants.TOKEN_PREFIX, ""); + } + // 解析token + String userId; + try { + userId = tokenService.getWxUserIdByToken(userToken); + } catch (Exception e) { + return ""; + } + PlayCustomUserInfoEntity entity = customUserInfoService.selectById(userId); + if (Objects.isNull(entity)) { + return ""; + } + return userToken.equals(entity.getToken()) ? userId : ""; + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/service/WxOauthService.java --- +package com.starry.admin.modules.weichat.service; + +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson2.JSONObject; +import com.starry.admin.common.exception.ServiceException; +import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity; +import com.starry.admin.modules.clerk.service.IPlayClerkLevelInfoService; +import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService; +import com.starry.admin.modules.custom.module.entity.PlayCustomUserInfoEntity; +import com.starry.admin.modules.custom.service.IPlayCustomLevelInfoService; +import com.starry.admin.modules.custom.service.IPlayCustomUserInfoService; +import com.starry.common.utils.ConvertUtil; +import com.starry.common.utils.IdUtils; +import java.util.Date; +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.bean.WxOAuth2UserInfo; +import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken; +import me.chanjar.weixin.common.error.WxErrorException; +import org.springframework.stereotype.Service; + +/** + * 微信授权 + * + * @author admin + */ +@Slf4j +@Service +public class WxOauthService { + + @Resource + private WxCustomMpService wxCustomMpService; + + @Resource + private IPlayCustomUserInfoService customUserInfoService; + + @Resource + private IPlayClerkUserInfoService clerkUserInfoService; + + @Resource + private IPlayClerkLevelInfoService playClerkLevelInfoService; + + @Resource + private IPlayCustomLevelInfoService playCustomLevelInfoService; + + /** + * 微信用户登录 如果用户不存在,初始化用户并登录 + * + * @param code + * 微信授权code + * @return String 用户ID + * @author admin + * @since 2024/4/15 11:01 + **/ + public String clerkUserLogin(String code) { + WxOAuth2AccessToken token = getWxOAuth2AccessToken(code); + log.info("token = " + token); + String openId = getOpenId(token); + log.info("openId = " + openId); + WxOAuth2UserInfo userInfo = getWxOAuth2UserInfo(token); + PlayClerkUserInfoEntity item = clerkUserInfoService.selectByOpenid(openId); + if (item == null) { + PlayClerkUserInfoEntity entity = ConvertUtil.entityToVo(userInfo, PlayClerkUserInfoEntity.class); + entity.setAvatar(userInfo.getHeadImgUrl()); + entity.setWeiChatAvatar(userInfo.getHeadImgUrl()); + entity.setId(IdUtils.getUuid()); + entity.setLevelId(playClerkLevelInfoService.getDefaultLevel().getId()); + clerkUserInfoService.create(entity); + return entity.getId(); + } else { + PlayClerkUserInfoEntity entity = new PlayClerkUserInfoEntity(); + entity.setId(item.getId()); + entity.setAvatar(userInfo.getHeadImgUrl()); + entity.setWeiChatAvatar(userInfo.getHeadImgUrl()); + clerkUserInfoService.updateById(entity); + return item.getId(); + } + } + + public void clerkUserLogout(PlayClerkUserInfoEntity entity) { + entity.setToken("empty"); + clerkUserInfoService.update(entity); + } + + public void customUserLogout(PlayCustomUserInfoEntity entity) { + entity.setToken("empty"); + customUserInfoService.update(entity); + } + + public String customUserLogin(String code) { + WxOAuth2AccessToken token = getWxOAuth2AccessToken(code); + String openId = getOpenId(token); + WxOAuth2UserInfo userInfo = getWxOAuth2UserInfo(token); + log.info("微信登录返回用户信息:" + JSONObject.toJSONString(userInfo)); + PlayCustomUserInfoEntity entity = ConvertUtil.entityToVo(userInfo, PlayCustomUserInfoEntity.class); + entity.setAvatar(userInfo.getHeadImgUrl()); + PlayCustomUserInfoEntity item = customUserInfoService.selectByOpenid(openId); + if (item == null) { + entity.setId(IdUtils.getUuid()); + entity.setRegistrationTime(new Date()); + entity.setLevelId(playCustomLevelInfoService.getDefaultLevel().getId()); + } else { + entity.setId(item.getId()); + } + entity.setLastLoginTime(new Date()); + customUserInfoService.saveOrUpdate(entity); + return entity.getId(); + } + + /** + * 获取微信授权Token + * + * @param code + * code + * @return WxOAuth2AccessToken + * @author admin + * @since 2024/4/8 14:47 + **/ + public WxOAuth2AccessToken getWxOAuth2AccessToken(String code) { + if (StrUtil.isBlankIfStr(code)) { + throw new ServiceException("不能为空"); + } + synchronized (code.intern()) { + try { + return wxCustomMpService.proxyWxMpService().getOAuth2Service().getAccessToken(code); + } catch (WxErrorException e) { + throw new RuntimeException(e); + } + } + } + + /** + * 获取微信用户ID + * + * @param token + * code + * @return WxOAuth2AccessToken + * @author admin + * @since 2024/4/8 14:47 + **/ + public String getOpenId(WxOAuth2AccessToken token) { + if (token == null) { + throw new ServiceException("获取微信授权异常,WxOAuth2AccessToken不能为空"); + } + String openId = token.getOpenId(); + if (StrUtil.isBlankIfStr(openId)) { + throw new ServiceException("获取微信授权异常,openId不能为空"); + } + return openId; + } + + /** + * 获取微信用户ID + * + * @param token + * WxOAuth2AccessToken + * @return WxOAuth2UserInfo + * @author admin + * @since 2024/4/8 14:47 + **/ + public WxOAuth2UserInfo getWxOAuth2UserInfo(WxOAuth2AccessToken token) { + if (token == null) { + throw new ServiceException("获取微信授权异常,WxOAuth2AccessToken不能为空"); + } + try { + return wxCustomMpService.proxyWxMpService().getOAuth2Service().getUserInfo(token, null); + } catch (WxErrorException e) { + throw new RuntimeException(e); + } + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/service/WxTokenService.java --- +package com.starry.admin.modules.weichat.service; + +import cn.hutool.core.date.DateUtil; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +/** + * token验证处理 + * + * @author ruoyi + */ +@Slf4j +@Service +public class WxTokenService { + /** + * 令牌自定义标识 + * + * @since 2024/4/10 11:20 + **/ + @Value("${token.header}") + private String header; + + /** + * 令牌秘钥 + * + * @since 2024/4/10 11:20 + **/ + @Value("${token.secret}") + private String secret; + + /** + * 令牌有效期(默认30分钟) + * + * @since 2024/4/10 11:20 + **/ + @Value("${token.expireTime}") + private int expireTime; + + protected static final long MILLIS_SECOND = 1000; + + /** + * 根据微信用户id创建token + * + * @param userId + * 微信用户ID + * @return String token + * @author admin + * @since 2024/4/10 11:21 + **/ + public String createWxUserToken(String userId) { + if (Objects.isNull(userId)) { + throw new RuntimeException("用户id不能为空"); + } + Map claims = new HashMap<>(16); + claims.put(Constants.LOGIN_USER_KEY_WX, userId); + return Jwts.builder().setClaims(claims).setExpiration(DateUtil.offsetMinute(new Date(), expireTime)) + .signWith(SignatureAlgorithm.HS512, secret).compact(); + } + + /** + * 根据token获取微信用户ID + * + * @param token + * token + * @return String 微信用户ID + * @author admin + * @since 2024/4/10 11:24 + **/ + public String getWxUserIdByToken(String token) { + if (StringUtils.isEmpty(token)) { + throw new RuntimeException("token不能为空"); + } + if (token.startsWith(Constants.TOKEN_PREFIX)) { + token = token.replace(Constants.TOKEN_PREFIX, ""); + } + Claims claims = parseToken(token); + return claims.get(Constants.LOGIN_USER_KEY_WX).toString(); + } + + /** + * 根据token获取微信用户TenantId + * + * @param token + * token + * @param identity + * 用户身份(0:租户,1:顾客) + * @return String 微信用户租户ID + * @author admin + * @since 2024/4/10 11:24 + **/ + public String getWxUserTenantIdByToken(String token) { + if (StringUtils.isEmpty(token)) { + throw new RuntimeException("token不能为空"); + } + Claims claims = parseToken(token); + return claims.get(Constants.LOGIN_USER_KEY_WX).toString(); + } + + // public String getTenantId(String token) { + // if (StringUtils.isEmpty(token)) { + // throw new RuntimeException("token不能为空"); + // } + // Map claims = new HashMap<>(); + // claims.put(Constants.LOGIN_USER_KEY_MINI, miniUserId); + // return + // Jwts.builder().setClaims(claims).setExpiration(DateUtil.offsetMinute(new + // Date(), expireTime)).signWith(SignatureAlgorithm.HS512, secret).compact(); + // } + // + // // 小程序端-coser + // public String createMiniCoserToken(Long miniCoserId) { + // if (Objects.isNull(miniCoserId)) { + // throw new RuntimeException("用户id不能为空"); + // } + // Map claims = new HashMap<>(); + // claims.put(Constants.LOGIN_USER_KEY_COSER, miniCoserId); + // return + // Jwts.builder().setClaims(claims).setExpiration(DateUtil.offsetMinute(new + // Date(), expireTime)).signWith(SignatureAlgorithm.HS512, secret).compact(); + // } + // + // // 小程序端-coser + // public Long getMiniCoserIdByToken(String token) { + // if (StringUtils.isEmpty(token)) { + // throw new RuntimeException("token不能为空"); + // } + // Claims claims = parseToken(token); + // String userId = claims.get(Constants.LOGIN_USER_KEY_COSER).toString(); + // return Long.parseLong(userId); + // } + // + // + // /** + // * 验证令牌有效期,相差不足20分钟,自动刷新缓存 + // * + // * @param loginUser + // * @return 令牌 + // */ + // public void verifyToken(LoginUser loginUser) { + // long expireTime = loginUser.getExpireTime(); + // long currentTime = System.currentTimeMillis(); + // if (expireTime - currentTime <= MILLIS_MINUTE_TEN) { + // refreshToken(loginUser); + // } + // } + // + // /** + // * 刷新令牌有效期 + // * + // * @param loginUser 登录信息 + // */ + // public void refreshToken(LoginUser loginUser) { + // loginUser.setLoginTime(System.currentTimeMillis()); + // loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * + // MILLIS_MINUTE); + // // 根据uuid将loginUser缓存 + // String userKey = getTokenKey(loginUser.getToken()); + // redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES); + // } + // + // + // /** + // * 设置用户代理信息 + // * + // * @param loginUser 登录信息 + // */ + // public void setUserAgent(LoginUser loginUser) { + // UserAgent userAgent = + // UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent")); + // String ip = IpUtils.getIpAddr(); + // loginUser.setIpaddr(ip); + // loginUser.setLoginLocation(AddressUtils.getRealAddressByIP(ip)); + // loginUser.setBrowser(userAgent.getBrowser().getName()); + // loginUser.setOs(userAgent.getOperatingSystem().getName()); + // } + // + // /** + // * 从数据声明生成令牌 + // * + // * @param claims 数据声明 + // * @return 令牌 + // */ + // private String createToken(Map claims) { + // String token = + // Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS512, + // secret).compact(); + // return token; + // } + // + + /** + * 从令牌中获取数据声明 + * + * @param token + * 令牌 + * @return 数据声明 + */ + private Claims parseToken(String token) { + return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody(); + } + // + // /** + // * 获取请求token + // * + // * @param request + // * @return token + // */ + // private String getToken(HttpServletRequest request) { + // String token = request.getHeader(header); + // if (StrUtil.isNotBlank(token) && token.startsWith(Constants.TOKEN_PREFIX)) { + // token = token.replace(Constants.TOKEN_PREFIX, ""); + // } + // return token; + // } + // + // private String getTokenKey(String uuid) { + // return CacheConstants.LOGIN_TOKEN_KEY + uuid; + // } +} + + +--- File: play-admin/src/main/java/com/starry/admin/modules/weichat/utils/WxFileUtils.java --- +package com.starry.admin.modules.weichat.utils; + +import cn.hutool.core.io.FileUtil; +import com.alibaba.fastjson2.JSONObject; +import com.starry.admin.common.exception.CustomException; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import lombok.extern.slf4j.Slf4j; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import ws.schild.jave.Encoder; +import ws.schild.jave.MultimediaObject; +import ws.schild.jave.encode.AudioAttributes; +import ws.schild.jave.encode.EncodingAttributes; + +@Slf4j +public class WxFileUtils { + + /** + * 下载微信临时素材文件 + * + * @param access_token + * 微信token + * @param mediaId + * 素材ID + * @return InputStream + * @throws IOException + * IOException + */ + public static InputStream getTemporaryMaterial(String access_token, String mediaId) throws IOException { + String url = "https://api.weixin.qq.com/cgi-bin/media/get?access_token=" + access_token + "&media_id=" + + mediaId; + // 请求参数 + HashMap param = new HashMap<>(); + param.put("media_id", mediaId); + // 获取到http连接对象 + HttpPost httpPost = new HttpPost(url); + StringEntity stringEntity = new StringEntity(JSONObject.toJSONString(param)); + httpPost.setEntity(stringEntity); + // 打开链接发送请求 获取到返回的流 + CloseableHttpClient build = HttpClients.custom().build(); + CloseableHttpResponse execute = build.execute(httpPost); + return execute.getEntity().getContent(); + } + + public static void audioConvert2Mp3(File source, File target) { + if (FileUtil.isEmpty(source)) { + log.error("从微信下载的临时素材文件为空"); + throw new CustomException("音频文件上传失败"); + } + try { + AudioAttributes audio = new AudioAttributes(); + audio.setCodec("libmp3lame"); + audio.setBitRate(228000); + audio.setChannels(2); + audio.setSamplingRate(44100); + EncodingAttributes attrs = new EncodingAttributes(); + attrs.setOutputFormat("mp3"); + attrs.setAudioAttributes(audio); + Encoder encoder = new Encoder(); + encoder.encode(new MultimediaObject(source), target, attrs); + } catch (Exception ex) { + log.error("音频文件格式转化失败", ex); + throw new CustomException("音频文件上传失败"); + } + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/utils/DictUtils.java --- +package com.starry.admin.utils; + +import com.alibaba.fastjson2.JSONArray; +import com.starry.admin.modules.system.module.entity.SysDictDataEntity; +import com.starry.common.constant.CacheConstants; +import com.starry.common.redis.RedisCache; +import com.starry.common.utils.SpringUtils; +import com.starry.common.utils.StringUtils; +import java.util.Collection; +import java.util.List; + +/** + * @author admin + */ +public class DictUtils { + + /** + * 获取 cache key + * + * @param key + * 参数键 + * @return 缓存键key + */ + public static String getCacheKey(String key) { + return CacheConstants.SYS_DICT_KEY + key; + } + + /** + * 获取字典缓存 + * + * @param key + * 参数键 + * @return dictDatas 字典数据列表 + */ + public static List getDictCache(String key) { + JSONArray arrayCache = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key)); + if (StringUtils.isNotNull(arrayCache)) { + return arrayCache.toList(SysDictDataEntity.class); + } + return null; + } + + /** + * 设置字典缓存 + * + * @param key + * 参数键 + * @param dataList + * 字典数据列表 + */ + public static void setDictCache(String key, List dataList) { + SpringUtils.getBean(RedisCache.class).setCacheObject(getCacheKey(key), dataList); + } + + /** + * 清空字典缓存 + */ + public static void clearDictCache() { + Collection keys = SpringUtils.getBean(RedisCache.class).keys(CacheConstants.SYS_DICT_KEY + "*"); + SpringUtils.getBean(RedisCache.class).deleteObject(keys); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/utils/ExcelUtils.java --- +package com.starry.admin.utils; + +import com.alibaba.excel.EasyExcel; +import java.io.IOException; +import java.io.InputStream; +import java.util.List; +import javax.servlet.http.HttpServletResponse; + +/** + * @author admin + */ +public class ExcelUtils { + + public static List importEasyExcel(InputStream is, Class pojoClass) { + return EasyExcel.read(is).head(pojoClass).sheet().doReadSync(); + } + + public static void exportEasyExcel(HttpServletResponse response, Class pojoClass, List list, + String sheetName) { + try { + EasyExcel.write(response.getOutputStream(), pojoClass).sheet(sheetName).doWrite(list); + } catch (IOException e) { + throw new RuntimeException(e.getMessage()); + } + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/utils/HttpUtils.java --- +package com.starry.admin.utils; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import org.apache.commons.lang3.StringUtils; +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.client.HttpClient; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.conn.ClientConnectionManager; +import org.apache.http.conn.scheme.Scheme; +import org.apache.http.conn.scheme.SchemeRegistry; +import org.apache.http.conn.ssl.SSLSocketFactory; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.message.BasicNameValuePair; + +public class HttpUtils { + + /** + * get + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @return + * @throws Exception + */ + public static HttpResponse doGet(String host, String path, String method, Map headers, + Map querys) throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpGet request = new HttpGet(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + return httpClient.execute(request); + } + + /** + * post form + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param bodys + * @return + * @throws Exception + */ + public static HttpResponse doPost(String host, String path, String method, Map headers, + Map querys, Map bodys) throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPost request = new HttpPost(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (bodys != null) { + List nameValuePairList = new ArrayList(); + + for (String key : bodys.keySet()) { + nameValuePairList.add(new BasicNameValuePair(key, bodys.get(key))); + } + UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nameValuePairList, "utf-8"); + formEntity.setContentType("application/x-www-form-urlencoded; charset=UTF-8"); + request.setEntity(formEntity); + } + + return httpClient.execute(request); + } + + /** + * Post String + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param body + * @return + * @throws Exception + */ + public static HttpResponse doPost(String host, String path, String method, Map headers, + Map querys, String body) throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPost request = new HttpPost(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (StringUtils.isNotBlank(body)) { + request.setEntity(new StringEntity(body, "utf-8")); + } + + return httpClient.execute(request); + } + + /** + * Post stream + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param body + * @return + * @throws Exception + */ + public static HttpResponse doPost(String host, String path, String method, Map headers, + Map querys, byte[] body) throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPost request = new HttpPost(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (body != null) { + request.setEntity(new ByteArrayEntity(body)); + } + + return httpClient.execute(request); + } + + /** + * Put String + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param body + * @return + * @throws Exception + */ + public static HttpResponse doPut(String host, String path, String method, Map headers, + Map querys, String body) throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPut request = new HttpPut(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (StringUtils.isNotBlank(body)) { + request.setEntity(new StringEntity(body, "utf-8")); + } + + return httpClient.execute(request); + } + + /** + * Put stream + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param body + * @return + * @throws Exception + */ + public static HttpResponse doPut(String host, String path, String method, Map headers, + Map querys, byte[] body) throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPut request = new HttpPut(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (body != null) { + request.setEntity(new ByteArrayEntity(body)); + } + + return httpClient.execute(request); + } + + /** + * Delete + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @return + * @throws Exception + */ + public static HttpResponse doDelete(String host, String path, String method, Map headers, + Map querys) throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpDelete request = new HttpDelete(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + return httpClient.execute(request); + } + + private static String buildUrl(String host, String path, Map querys) + throws UnsupportedEncodingException { + StringBuilder sbUrl = new StringBuilder(); + sbUrl.append(host); + if (!StringUtils.isBlank(path)) { + sbUrl.append(path); + } + if (null != querys) { + StringBuilder sbQuery = new StringBuilder(); + for (Map.Entry query : querys.entrySet()) { + if (0 < sbQuery.length()) { + sbQuery.append("&"); + } + if (StringUtils.isBlank(query.getKey()) && !StringUtils.isBlank(query.getValue())) { + sbQuery.append(query.getValue()); + } + if (!StringUtils.isBlank(query.getKey())) { + sbQuery.append(query.getKey()); + if (!StringUtils.isBlank(query.getValue())) { + sbQuery.append("="); + sbQuery.append(URLEncoder.encode(query.getValue(), "utf-8")); + } + } + } + if (0 < sbQuery.length()) { + sbUrl.append("?").append(sbQuery); + } + } + + return sbUrl.toString(); + } + + private static HttpClient wrapClient(String host) { + HttpClient httpClient = new DefaultHttpClient(); + if (host.startsWith("https://")) { + sslClient(httpClient); + } + + return httpClient; + } + + private static void sslClient(HttpClient httpClient) { + try { + SSLContext ctx = SSLContext.getInstance("TLS"); + X509TrustManager tm = new X509TrustManager() { + public X509Certificate[] getAcceptedIssuers() { + return null; + } + + public void checkClientTrusted(X509Certificate[] xcs, String str) { + + } + + public void checkServerTrusted(X509Certificate[] xcs, String str) { + + } + }; + ctx.init(null, new TrustManager[]{tm}, null); + SSLSocketFactory ssf = new SSLSocketFactory(ctx); + ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + ClientConnectionManager ccm = httpClient.getConnectionManager(); + SchemeRegistry registry = ccm.getSchemeRegistry(); + registry.register(new Scheme("https", 443, ssf)); + } catch (KeyManagementException ex) { + throw new RuntimeException(ex); + } catch (NoSuchAlgorithmException ex) { + throw new RuntimeException(ex); + } + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/utils/ListToStringHandle.java --- +package com.starry.admin.utils; + +/** + * @Author: huchuansai + * @Date: 2024/3/5 11:52 AM + * @Description: + */ + +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONArray; +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.ibatis.type.BaseTypeHandler; +import org.apache.ibatis.type.JdbcType; + +/** + * List ==> string + * + * @Date 2022-10-08 + */ +public class ListToStringHandle extends BaseTypeHandler { + + @Override + public void setNonNullParameter(PreparedStatement preparedStatement, int i, List list, JdbcType jdbcType) + throws SQLException { + if (CollectionUtils.isNotEmpty(list)) { + preparedStatement.setString(i, JSON.toJSONString(list)); + } else { + preparedStatement.setString(i, null); + } + + } + + @Override + public List getNullableResult(ResultSet resultSet, String s) throws SQLException { + String result = resultSet.getString(s); + return result == null ? new ArrayList<>() : JSONArray.parseArray(result); + } + + @Override + public List getNullableResult(ResultSet resultSet, int i) throws SQLException { + String result = resultSet.getString(i); + return result == null ? new ArrayList<>() : JSONArray.parseArray(result); + } + + @Override + public List getNullableResult(CallableStatement callableStatement, int i) throws SQLException { + String result = callableStatement.getString(i); + return result == null ? new ArrayList<>() : JSONArray.parseArray(result); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/utils/MoneyUtils.java --- +package com.starry.admin.utils; + +import com.starry.admin.common.exception.CustomException; + +/** + * 金额辅助类 + * + * @author admin + */ +public class MoneyUtils { + + /** + * 校验金钱值是否正常 + * + * @param money + * 金钱值 + */ + public static void verificationTypeIsNormal(String money) { + if (money == null || money.isEmpty()) { + throw new CustomException("金额类型异常"); + } + float item; + try { + item = Float.parseFloat(money); + } catch (Exception e) { + throw new CustomException("金额类型异常"); + } + if (item < 0) { + throw new CustomException("金额不能小于0"); + } + if (item > Integer.MAX_VALUE) { + throw new CustomException("金额超出计算范围"); + } + } + +} + + +--- File: play-admin/src/main/java/com/starry/admin/utils/SecurityUtils.java --- +package com.starry.admin.utils; + +import com.starry.admin.common.domain.LoginUser; +import com.starry.admin.common.security.entity.JwtUser; +import com.starry.admin.modules.system.module.entity.SysUserEntity; +import com.starry.common.context.CustomSecurityContextHolder; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; + +/** + * 安全服务工具类 + * + * @author admin + */ +public class SecurityUtils { + /** + * 用户ID + **/ + public static String getUserId() { + try { + return getLoginUser().getUser().getUserId(); + } catch (Exception e) { + throw new RuntimeException("获取用户ID异常"); + } + } + + /** + * 获取用户账户 + **/ + public static String getUsername() { + try { + return getLoginUser().getUsername(); + } catch (Exception e) { + throw new RuntimeException("获取用户账户异常"); + } + } + + /** + * 获取用户 + **/ + public static JwtUser getOldLoginUser() { + try { + return (JwtUser) getAuthentication().getPrincipal(); + } catch (Exception e) { + throw new RuntimeException("获取用户信息异常"); + } + } + + /** + * 获取用户 + **/ + public static LoginUser getLoginUser() { + try { + return (LoginUser) getAuthentication().getPrincipal(); + } catch (Exception e) { + throw new RuntimeException("获取用户信息异常"); + } + } + + /** + * 获取Authentication + */ + public static Authentication getAuthentication() { + return SecurityContextHolder.getContext().getAuthentication(); + } + + /** + * 是否登录 + **/ + public static boolean isLogin() { + return getAuthentication() != null && getAuthentication().getPrincipal() != null; + } + + public static boolean isAdmin(SysUserEntity user) { + return user.getSuperAdmin(); + } + + /** + * 生成BCryptPasswordEncoder密码 + * + * @param password + * 密码 + * @return 加密字符串 + */ + public static String encryptPassword(String password) { + BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + return passwordEncoder.encode(password); + } + + /** + * 判断密码是否相同 + * + * @param rawPassword + * 真实密码 + * @param encodedPassword + * 加密后字符 + * @return 结果 + */ + public static boolean matchesPassword(String rawPassword, String encodedPassword) { + BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + return passwordEncoder.matches(rawPassword, encodedPassword); + } + + /** + * 获取租户ID + */ + public static String getTenantId() { + return CustomSecurityContextHolder.getTenantId(); + } + + /** + * 设置租户ID + */ + public static void setTenantId(String tenantId) { + CustomSecurityContextHolder.setTenantId(tenantId); + } +} + + +--- File: play-admin/src/main/java/com/starry/admin/utils/SmsUtils.java --- +package com.starry.admin.utils; + +import cn.hutool.core.util.RandomUtil; +import com.starry.common.redis.RedisCache; +import java.util.HashMap; +import java.util.Map; +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.apache.http.HttpResponse; +import org.apache.http.util.EntityUtils; +import org.springframework.stereotype.Service; + +/** + * @Author: huchuansai + * @Date: 2024/7/29 5:41 PM + * @Description: + */ +@Slf4j +@Service +public class SmsUtils { + @Resource + private RedisCache redisCache; + + // 发送短信验证码接口 + public void sendSmsApi(String phone) { + String code = RandomUtil.randomNumbers(4); + sendSms(phone, code, "CST_paqequfcmkuv11286"); + String key = "sms:phone:" + phone; + // 存放到redis里 + redisCache.setCacheObject(key, code, 10L, java.util.concurrent.TimeUnit.MINUTES); + } + + // 校验短信验证码是否正确 + public void checkSmsCode(String phone, String code) { + // if(StringUtils.isEmpty(code)){ + // throw new RuntimeException("短信验证码必填"); + // } + // String key = "sms:phone:" + phone; + // Object data = redisCache.getCacheObject(key); + // if (Objects.isNull(data)) { + // throw new RuntimeException("短信验证码无效或已过期"); + // } + // if (!code.equals(data.toString())) { + // throw new RuntimeException("短信验证码错误"); + // } + } + + private static void sendSms(String phone, String code, String templateId) { + String host = "https://wwsms.market.alicloudapi.com"; + String path = "/send_sms"; + String method = "POST"; + String appcode = "18639b38538849e1bc8a3413a8d0c0e5"; + Map headers = new HashMap<>(); + headers.put("Authorization", "APPCODE " + appcode); + headers.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); + Map querys = new HashMap<>(); + Map bodys = new HashMap<>(); + bodys.put("content", "code:" + code); + bodys.put("template_id", templateId); // 注意,模板CST_11253 仅作调试使用,下发短信不稳定,请联系客服报备自己的专属签名模板,以保障业务稳定使用 + bodys.put("phone_number", phone); + try { + HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys); + String resp = EntityUtils.toString(response.getEntity()); + log.info("send sms result:" + resp); + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new RuntimeException(e); + } + } + + public static void main(String[] args) { + sendSms("13210055630", "5566", "CST_paqequfcmkuv11286"); + } + +} + + +--- File: play-admin/src/main/resources/application-dev.yml --- +# 服务名 +spring: + application: + name: ${SPRING_APPLICATION_NAME:admin-tenant} + + flyway: + table: admin_flyway_schema_history + baseline-on-migrate: true + baseline-version: 1 + enabled: true + locations: classpath:db/migration + clean-disabled: true + validate-on-migrate: false + out-of-order: false + + # druid数据源配置 + datasource: + type: com.alibaba.druid.pool.DruidDataSource + # 配置MySQL的驱动程序类 + driver-class-name: com.p6spy.engine.spy.P6SpyDriver + # 数据库连接地址(以MySql为例) + url: ${SPRING_DATASOURCE_URL:jdbc:p6spy:mysql://primary:3306/play-with?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8} + # 数据库对应的用户名 + username: ${SPRING_DATASOURCE_USERNAME:root} + # 数据库对应的密码 + password: ${SPRING_DATASOURCE_PASSWORD:123456} + druid: + enable: true + db-type: mysql + # 配置监控统计拦截的filters,stat是sql监控,wall是防火墙(如果不添加则监控无效),添加log4j需要引入jar包 + filters: stat,wall,config + # 连接池最大活跃连接数 + max-active: ${SPRING_DATASOURCE_DRUID_MAX_ACTIVE:100} + # 连接池初始化连接数量 + initial-size: ${SPRING_DATASOURCE_DRUID_INITIAL_SIZE:1} + # 配置获取连接等待超时的时间 + max-wait: ${SPRING_DATASOURCE_DRUID_MAX_WAIT:60000} + # 连接池最小空闲数 + min-idle: ${SPRING_DATASOURCE_DRUID_MIN_IDLE:1} + # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 + timeBetweenEvictionRunsMillis: ${SPRING_DATASOURCE_DRUID_TIME_BETWEEN_EVICTION_RUNS_MILLIS:60000} + # 配置一个连接在池中最小生存的时间,单位是毫秒 + minEvictableIdleTimeMillis: ${SPRING_DATASOURCE_DRUID_MIN_EVICTABLE_IDLE_TIME_MILLIS:300000} + # 指定空闲连接检查、废弃连接清理、空闲连接池大小调整之间的操作时间间隔 + time-between-eviction-runs-millis: ${SPRING_DATASOURCE_DRUID_TIME_BETWEEN_EVICTION_RUNS_MILLIS:60000} + # 指定一个空闲连接最少空闲多久后可被清除 + min-evictable-idle-time-millis: ${SPRING_DATASOURCE_DRUID_MIN_EVICTABLE_IDLE_TIME_MILLIS:300000} + # 连接是否有效的查询语句 + validation-query: select 'x' + test-while-idle: true + test-on-borrow: false + test-on-return: false + # 打开 PSCache,并且指定每个连接上 PSCache 的大小 + pool-prepared-statements: true + max-open-prepared-statements: ${SPRING_DATASOURCE_DRUID_MAX_OPEN_PREPARED_STATEMENTS:50} + max-pool-prepared-statement-per-connection-size: ${SPRING_DATASOURCE_DRUID_MAX_POOL_PREPARED_STATEMENT_PER_CONNECTION_SIZE:20} + # 配置 DruidStatFilter + web-stat-filter: + enabled: true + # 排除一些不必要的url,比如.js,/jslib/等 + exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*" + # 过滤规则 + url-pattern: /* + # 配置 DruidStatViewServlet + stat-view-servlet: + # 手动重置监控数据 + enabled: true + # IP白名单,没有配置或者为空,则允许所有访问 + allow: ${SPRING_DATASOURCE_DRUID_STAT_VIEW_SERVLET_ALLOW:127.0.0.1} + # IP黑名单,若白名单也存在,则优先使用 + deny: + # 配置druid登录用户名、密码 + login-username: ${SPRING_DATASOURCE_DRUID_STAT_VIEW_SERVLET_LOGIN_USERNAME:admin} + login-password: ${SPRING_DATASOURCE_DRUID_STAT_VIEW_SERVLET_LOGIN_PASSWORD:admin} + # HTML 中 Reset All 按钮 + reset-enable: true + redis: + host: ${SPRING_REDIS_HOST:127.0.0.1} # Redis服务器地址 + database: ${SPRING_REDIS_DATABASE:10} # Redis数据库索引(默认为0) + port: ${SPRING_REDIS_PORT:6379} # Redis服务器连接端口 + password: ${SPRING_REDIS_PASSWORD:Spinfo@0123} + timeout: ${SPRING_REDIS_TIMEOUT:3000ms} # 连接超时时间(毫秒) + +# 全局日志级别 +logging: + level: + root: ${LOGGING_LEVEL_ROOT:info} + com.starry: debug + com.starry.admin.modules.weichat: debug + com.starry.admin.modules.order: debug + com.starry.admin.modules.clerk: debug + com.starry.admin.modules.custom: debug + com.starry.admin.modules.system: debug + org.springframework.web.servlet.DispatcherServlet: debug + org.springframework.security: debug + +jwt: + tokenHeader: X-Token #JWT存储的请求头 + tokenHead: Bearer #JWT负载中拿到开头 + secret: yz-admin-secret #JWT加解密使用的密钥 + expiration: 360000 #JWT的超期限时间秒(60*60*24) + +# token配置 +token: + # 令牌自定义标识 + header: Authorization + # 令牌密钥 + secret: abcdefghijklmnopqrstuvwxyz + # 令牌有效期,单位分钟(默认30分钟) + expireTime: 129600 + +# xl自定义配置 +xl: + login: + authCode: + # 登录验证码是否开启,开发环境配置false方便测试 + enable: ${XL_LOGIN_AUTHCODE_ENABLE:false} + + + + +--- File: play-admin/src/main/resources/application-prod.yml --- +# 服务名 +spring: + application: + name: admin-ucenter + + flyway: + table: admin_flyway_schema_history + baseline-on-migrate: true + baseline-version: 1 + enabled: true + locations: classpath:db/migration + clean-disabled: true + validate-on-migrate: false + out-of-order: false + # druid数据源配置 + datasource: + type: com.alibaba.druid.pool.DruidDataSource + # 配置MySQL的驱动程序类 + driver-class-name: com.mysql.cj.jdbc.Driver + # 数据库连接地址(以MySql为例) + url: jdbc:mysql://localhost:3306/admin?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8 + # 数据库对应的用户名 + username: root + # 数据库对应的密码 + password: root + druid: + # 配置监控统计拦截的filters,stat是sql监控,wall是防火墙(如果不添加则监控无效),添加log4j需要引入jar包 + filters: stat,wall,config + # 连接池最大活跃连接数 + max-active: 100 + # 连接池初始化连接数量 + initial-size: 1 + # 配置获取连接等待超时的时间 + max-wait: 60000 + # 连接池最小空闲数 + min-idle: 1 + # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 + timeBetweenEvictionRunsMillis: 60000 + # 配置一个连接在池中最小生存的时间,单位是毫秒 + minEvictableIdleTimeMillis: 300000 + # 指定空闲连接检查、废弃连接清理、空闲连接池大小调整之间的操作时间间隔 + time-between-eviction-runs-millis: 60000 + # 指定一个空闲连接最少空闲多久后可被清除 + min-evictable-idle-time-millis: 300000 + # 连接是否有效的查询语句 + validation-query: select 'x' + test-while-idle: true + test-on-borrow: false + test-on-return: false + # 打开 PSCache,并且指定每个连接上 PSCache 的大小 + pool-prepared-statements: true + max-open-prepared-statements: 50 + max-pool-prepared-statement-per-connection-size: 20 + # 配置 DruidStatFilter + web-stat-filter: + enabled: true #\u662F\u5426\u542F\u7528StatFilter\u9ED8\u8BA4\u503Ctrue + # 排除一些不必要的url,比如.js,/jslib/等 + exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*" + # 过滤规则 + url-pattern: /* + # 配置 DruidStatViewServlet + stat-view-servlet: + # 手动重置监控数据 + enabled: true + # IP白名单,没有配置或者为空,则允许所有访问 + allow: 127.0.0.1 + # IP黑名单,若白名单也存在,则优先使用 + deny: + # 配置druid登录用户名、密码 + login-username: admin + login-password: admin + # HTML 中 Reset All 按钮 + reset-enable: true + redis: + host: localhost # Redis服务器地址 + database: 0 # Redis数据库索引(默认为0) + port: 6379 # Redis服务器连接端口 + password: yz_admin # Redis服务器连接密码(默认为空) + timeout: 3000ms # 连接超时时间(毫秒) + +# 全局日志级别 +logging: + level: + root: info + +jwt: + tokenHeader: X-Token #JWT存储的请求头 + tokenHead: Bearer #JWT负载中拿到开头 + secret: yz-admin-secret #JWT加解密使用的密钥 + expiration: 360000 #JWT的超期限时间秒(60*60*24) + +# xl自定义配置 +xl: + login: + authCode: + # 登录验证码是否开启,开发环境配置false方便测试 + enable: false + +--- File: play-admin/src/main/resources/application-test.yml --- +# 服务名 +spring: + application: + name: admin-tenant + + flyway: + table: admin_flyway_schema_history + baseline-on-migrate: true + baseline-version: 1 + enabled: true + locations: classpath:db/migration + clean-disabled: true + validate-on-migrate: false + out-of-order: false + + # druid数据源配置 + datasource: + type: com.alibaba.druid.pool.DruidDataSource + # 配置MySQL的驱动程序类 + driver-class-name: com.p6spy.engine.spy.P6SpyDriver + # 数据库连接地址(以MySql为例) + url: jdbc:p6spy:mysql://122.51.20.105:3306/play-with?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true&rewriteBatchedStatements=true + # 数据库对应的用户名 + username: root + # 数据库对应的密码 + password: KdaKRZ2trpdhNePa + # 批量插入 + rewriteBatchedStatements: true + druid: + enable: true + db-type: mysql + # 配置监控统计拦截的filters,stat是sql监控,wall是防火墙(如果不添加则监控无效),添加log4j需要引入jar包 + filters: stat,wall,config + # 连接池最大活跃连接数 + max-active: 100 + # 连接池初始化连接数量 + initial-size: 1 + # 配置获取连接等待超时的时间 + max-wait: 60000 + # 连接池最小空闲数 + min-idle: 1 + # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 + timeBetweenEvictionRunsMillis: 60000 + # 配置一个连接在池中最小生存的时间,单位是毫秒 + minEvictableIdleTimeMillis: 300000 + # 指定空闲连接检查、废弃连接清理、空闲连接池大小调整之间的操作时间间隔 + time-between-eviction-runs-millis: 60000 + # 指定一个空闲连接最少空闲多久后可被清除 + min-evictable-idle-time-millis: 300000 + # 连接是否有效的查询语句 + validation-query: select 'x' + test-while-idle: true + test-on-borrow: false + test-on-return: false + # 打开 PSCache,并且指定每个连接上 PSCache 的大小 + pool-prepared-statements: true + max-open-prepared-statements: 50 + max-pool-prepared-statement-per-connection-size: 20 + # 配置 DruidStatFilter + web-stat-filter: + enabled: true #\u662F\u5426\u542F\u7528StatFilter\u9ED8\u8BA4\u503Ctrue + # 排除一些不必要的url,比如.js,/jslib/等 + exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*" + # 过滤规则 + url-pattern: /* + # 配置 DruidStatViewServlet + stat-view-servlet: + # 手动重置监控数据 + enabled: true + # IP白名单,没有配置或者为空,则允许所有访问 + allow: 127.0.0.1 + # IP黑名单,若白名单也存在,则优先使用 + deny: + # 配置druid登录用户名、密码 + login-username: admin + login-password: admin + # HTML 中 Reset All 按钮 + reset-enable: true + redis: + host: 122.51.20.105 # Redis服务器地址 + database: 10 # Redis数据库索引(默认为0) + port: 19087 # Redis服务器连接端口 + password: arcikXa7ZkEBGtLf + timeout: 3000ms # 连接超时时间(毫秒) + + + +# 全局日志级别 +logging: + level: + root: info + +jwt: + tokenHeader: X-Token #JWT存储的请求头 + tokenHead: Bearer #JWT负载中拿到开头 + secret: yz-admin-secret #JWT加解密使用的密钥 + expiration: 360000 #JWT的超期限时间秒(60*60*24) + +# token配置 +token: + # 令牌自定义标识 + header: Authorization + # 令牌密钥 + secret: abcdefghijklmnopqrstuvwxyz + # 令牌有效期,单位分钟(默认30分钟) + expireTime: 129600 + +# xl自定义配置 +xl: + login: + authCode: + # 登录验证码是否开启,开发环境配置false方便测试 + enable: false + + +--- File: play-admin/src/main/resources/application.yml --- +server: + port: 7002 + servlet: + context-path: /api +spring: + profiles: + active: test + servlet: + multipart: + max-file-size: 100MB + max-request-size: 1000MB +logging: + config: classpath:logback-spring.xml +# mybatis日志 +mybatis-plus: + global-config: + # 逻辑删除 + db-config: + logic-delete-field: deleted # 全局逻辑删除的实体字段名 + logic-delete-value: 1 + logic-not-delete-value: 0 + # xml文件路径,classpath* 代表所有模块的resources目录 classpath 不加星号代表当前模块下的resources目录 + mapper-locations: classpath*:mapper/**/*.xml + +wx: + mp: + app-id: xxx + secret: ddd + config-storage: + key-prefix: peipei + http-client-type: HttpClient + redis: + host: 12 + database: ${spring.redis.database} + port: ${spring.redis.port} + password: ${spring.redis.password} + type: RedisTemplate + +--- File: play-admin/src/main/resources/db/migration/V1.2025.0609.10.11__change_tables.sql --- +ALTER TABLE `play_clerk_level_info` + ADD COLUMN `style_type` int(10) NULL COMMENT '等级样式' AFTER `version`, +ADD COLUMN `style_image_url` varchar(255) NULL COMMENT '等级图片' AFTER `style_type`; + + +update `play_clerk_level_info` set `style_type` = `level`; +CREATE TABLE `shop_ui_setting` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int(11) NOT NULL DEFAULT '1' COMMENT '数据版本', + `setting_config` text COMMENT '配置内容', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='店员等级'; + +--- File: play-admin/src/main/resources/db/migration/V1__init_schema.sql --- +-- MySQL dump 10.13 Distrib 8.0.41, for Linux (x86_64) +-- +-- Host: primary Database: play-with +-- ------------------------------------------------------ +-- Server version 8.2.0 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!50503 SET NAMES utf8mb4 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `commodity_info` +-- + +DROP TABLE IF EXISTS `commodity_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `commodity_info` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `money` varchar(255) DEFAULT NULL COMMENT '价格', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `gen_table` +-- + +DROP TABLE IF EXISTS `gen_table`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `gen_table` ( + `table_id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `table_name` varchar(50) NOT NULL DEFAULT '0' COMMENT '表名称', + `table_comment` varchar(64) NOT NULL COMMENT '表描述', + `sub_table_name` varchar(64) DEFAULT NULL COMMENT '关联子表的表名', + `sub_table_fk_name` varchar(50) DEFAULT NULL COMMENT '子表关联的外键名', + `class_name` varchar(100) DEFAULT NULL COMMENT '实体类名称', + `tpl_category` varchar(30) DEFAULT 'crud' COMMENT '使用的模板(crud单表操作 tree树表操作)', + `package_name` varchar(100) DEFAULT '0' COMMENT '生成包路径', + `module_name` varchar(30) DEFAULT NULL COMMENT '生成模块名', + `business_name` varchar(30) DEFAULT NULL COMMENT '生成业务名', + `function_name` varchar(30) DEFAULT NULL COMMENT '生成功能名', + `function_author` varchar(30) DEFAULT NULL COMMENT '生成功能作者', + `gen_type` char(1) DEFAULT '0' COMMENT '生成代码方式(0zip压缩包 1自定义路径)', + `gen_path` varchar(100) DEFAULT '/' COMMENT '生成路径(不填默认项目路径)', + `options` varchar(1000) DEFAULT NULL COMMENT '其它生成选项', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`table_id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=73 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='代码生成业务表'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `gen_table_column` +-- + +DROP TABLE IF EXISTS `gen_table_column`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `gen_table_column` ( + `column_id` int NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `table_id` int DEFAULT NULL COMMENT '归属表id', + `column_name` varchar(50) NOT NULL DEFAULT '0' COMMENT '列名称', + `column_comment` varchar(1000) NOT NULL COMMENT '列描述', + `column_type` varchar(64) DEFAULT NULL COMMENT '列类型', + `java_type` varchar(50) DEFAULT NULL COMMENT 'JAVA类型', + `java_field` varchar(100) DEFAULT NULL COMMENT 'JAVA字段名', + `is_pk` char(1) DEFAULT NULL COMMENT '是否主键(1是)', + `is_increment` char(1) DEFAULT NULL COMMENT '是否自增(1是)', + `is_required` char(1) DEFAULT NULL COMMENT '是否必填(1是)', + `is_insert` char(1) DEFAULT NULL COMMENT '是否为插入字段(1是)', + `is_edit` char(1) DEFAULT NULL COMMENT '是否编辑字段(1是)', + `is_list` char(1) DEFAULT NULL COMMENT '是否列表字段(1是)', + `is_query` char(1) DEFAULT '0' COMMENT '是否查询字段(1是)', + `query_type` varchar(10) DEFAULT 'EQ' COMMENT '查询方式(等于、不等于、大于、小于、范围)', + `html_type` varchar(100) DEFAULT NULL COMMENT '显示类型(文本框、文本域、下拉框、复选框、单选框、日期控件)', + `dict_type` varchar(100) DEFAULT NULL COMMENT '字典类型', + `sort` int DEFAULT NULL COMMENT '排序', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`column_id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=976 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='代码生成业务表字段'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `order_details_info` +-- + +DROP TABLE IF EXISTS `order_details_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `order_details_info` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `order_id` varchar(32) DEFAULT NULL COMMENT '订单ID', + `commodity_id` varchar(32) DEFAULT NULL COMMENT '商品类型', + `commodity_type` varchar(1) DEFAULT NULL COMMENT '商品类型【0:1】\r\n0:服务\r\n1:优惠券', + `commodity_money` varchar(255) DEFAULT NULL COMMENT '商品金额', + `remake` varchar(1000) DEFAULT NULL COMMENT '备注', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='订单详情'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `order_log_info` +-- + +DROP TABLE IF EXISTS `order_log_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `order_log_info` ( + `id` varchar(255) NOT NULL COMMENT 'uuid', + `tenant_id` varchar(32) DEFAULT NULL COMMENT '租户ID', + `order_id` varchar(1) DEFAULT NULL COMMENT '订单ID', + `oper_type` varchar(1) DEFAULT NULL COMMENT '操作类型\r\n0:下单\r\n1:审核\r\n2:接单\r\n3:服务\r\n4:完成\r\n5:取消', + `oper_time` datetime(1) DEFAULT NULL COMMENT '操作时间', + `remark` varchar(255) DEFAULT NULL COMMENT '备注', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='订单日志'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_account info` +-- + +DROP TABLE IF EXISTS `play_account info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_account info` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `avatar_frame_type` bigint DEFAULT NULL COMMENT '头像框分类\r\n0:店员头像框\r\n1:客户头像框\r\n', + `avatar_frame_address` varchar(1000) DEFAULT NULL COMMENT '头像框地址', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='店员头像框'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_avatar_frame_info` +-- + +DROP TABLE IF EXISTS `play_avatar_frame_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_avatar_frame_info` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `avatar_frame_name` varchar(255) DEFAULT NULL COMMENT '头像框名称', + `avatar_frame_address` varchar(255) DEFAULT NULL COMMENT '头像框地址', + `access_type` varchar(1) DEFAULT '0' COMMENT '获取方式(0:手动赠送;1:自动赠送)', + `access_name` text COMMENT '获取条件名称', + `access_value` text COMMENT '获取条件', + `period_validity` varchar(10) DEFAULT NULL COMMENT '有效期(单位:天,-1标识永久有效)', + `add_time` datetime(1) DEFAULT NULL COMMENT '添加时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='店员头像框'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_balance_details_info` +-- + +DROP TABLE IF EXISTS `play_balance_details_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_balance_details_info` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `user_id` varchar(32) DEFAULT NULL COMMENT '用户ID', + `user_type` varchar(1) DEFAULT NULL COMMENT '用户类型[0:陪玩;1:顾客]', + `balance_before_operation` decimal(10,2) DEFAULT NULL COMMENT '操作前余额', + `balance_after_operation` decimal(10,2) DEFAULT NULL COMMENT '操作后余额', + `operation_type` varchar(1) DEFAULT NULL COMMENT '操作类型(0:充值;1:消费;2:服务)', + `operation_action` varchar(255) DEFAULT NULL COMMENT '操作动作', + `operation_time` datetime(1) DEFAULT NULL COMMENT '操作时间', + `balance_money` decimal(10,2) DEFAULT '0.00' COMMENT '操作金额', + `gift_amount` decimal(10,2) DEFAULT '0.00' COMMENT '赠送金额', + `payment_amount` decimal(10,2) DEFAULT '0.00' COMMENT '支付金额', + `order_id` varchar(32) DEFAULT NULL COMMENT '订单ID', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='余额明细'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_clerk_article_info` +-- + +DROP TABLE IF EXISTS `play_clerk_article_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_clerk_article_info` ( + `id` varchar(32) NOT NULL DEFAULT '0' COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `clerk_id` varchar(32) DEFAULT NULL COMMENT '陪玩用户ID', + `article_title` longtext COMMENT '动态标题', + `article_con` text COMMENT '动态内容', + `annex_type` varchar(1) NOT NULL COMMENT '动态附件类型(0:图片,1:视频)', + `annex_con` text COMMENT '附件内容', + `release_time` datetime DEFAULT NULL COMMENT '发布时间', + `review_state` varchar(1) DEFAULT NULL COMMENT '审核状态(0:未审核:1:审核通过,2:审核不通过)', + `review_by` varchar(32) DEFAULT NULL COMMENT '审核人', + `review_time` datetime DEFAULT NULL COMMENT '审核时间', + `review_con` text COMMENT '备注', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` varchar(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE, + KEY `key_openid` (`annex_type`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='店员动态信息'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_clerk_classification_info` +-- + +DROP TABLE IF EXISTS `play_clerk_classification_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_clerk_classification_info` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `name` varchar(255) DEFAULT NULL COMMENT '类型名称', + `sort` tinyint(1) DEFAULT NULL COMMENT '(排序字段)', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='店员分类'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_clerk_commodity_info` +-- + +DROP TABLE IF EXISTS `play_clerk_commodity_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_clerk_commodity_info` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `clerk_id` varchar(32) DEFAULT NULL COMMENT '店员用户ID', + `commodity_id` varchar(32) DEFAULT NULL COMMENT '服务项目ID', + `commodity_name` varchar(255) DEFAULT NULL COMMENT '服务项目名称', + `sort` varchar(255) DEFAULT NULL COMMENT '服务项目排序', + `enabling_state` tinyint(1) DEFAULT NULL COMMENT '服务启动状态\r\n0:停用\r\n1:启用', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE, + KEY `key_play_user_id` (`clerk_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='陪玩和项目关系'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_clerk_data_review_info` +-- + +DROP TABLE IF EXISTS `play_clerk_data_review_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_clerk_data_review_info` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `clerk_id` varchar(32) DEFAULT NULL COMMENT '店员ID', + `data_type` varchar(1) DEFAULT NULL COMMENT '资料类型[0:昵称;1:头像;2:相册;3:录音]', + `data_content` text COMMENT '资料内容', + `review_state` varchar(1) DEFAULT NULL COMMENT ' 审核状态(0:未审核:1:审核通过,2:审核不通过)', + `add_time` datetime(1) DEFAULT NULL COMMENT '资料添加时间', + `review_time` datetime(1) DEFAULT NULL COMMENT '审核时间', + `review_by` varchar(32) DEFAULT NULL COMMENT '审核人', + `review_con` text COMMENT '审核内容', + `remark` text COMMENT '备注', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='店员资料审核'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_clerk_gift_info` +-- + +DROP TABLE IF EXISTS `play_clerk_gift_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_clerk_gift_info` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `clerk_id` varchar(32) DEFAULT NULL COMMENT '店员ID', + `giff_id` varchar(32) DEFAULT NULL COMMENT '礼物ID', + `giff_number` int DEFAULT NULL COMMENT '礼物数量', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE, + KEY `key_openid` (`clerk_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='店员和礼物关系'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_clerk_level_info` +-- + +DROP TABLE IF EXISTS `play_clerk_level_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_clerk_level_info` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `name` varchar(255) DEFAULT NULL COMMENT '等级名称', + `level` tinyint(1) DEFAULT NULL COMMENT '等级数字(排序字段)', + `not_first_regular_ratio` tinyint(1) DEFAULT NULL COMMENT '非首次固定单比例[0 - 100%]', + `first_regular_ratio` tinyint(1) DEFAULT NULL COMMENT '首次固定单比例[0 - 100%]', + `first_reward_ratio` tinyint(1) DEFAULT NULL COMMENT '首次打赏比例[0 - 100%]', + `not_first_reward_ratio` tinyint(1) DEFAULT NULL COMMENT '非首次打赏比例[0 - 100%]', + `first_random_radio` tinyint(1) DEFAULT NULL COMMENT '首次随机单比例[0 - 100%]', + `not_first_random_radio` tinyint(1) DEFAULT NULL COMMENT '非首次随机单比例[0 - 100%]', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='店员等级'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_clerk_operation_log` +-- + +DROP TABLE IF EXISTS `play_clerk_operation_log`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_clerk_operation_log` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `play_user_id` varchar(32) DEFAULT NULL COMMENT '店员用户ID', + `play_user_name` tinyint DEFAULT NULL COMMENT '店员用户名称', + `operation_type` varchar(2) DEFAULT NULL COMMENT '操作类型\r\n0:上线\r\n1:离线\r\n2:上架\r\n3:下架\r\n4:显示\r\n5:影藏\r\n6:开启随机单\r\n7:关闭随机单\r\n8:开启影藏排名\r\n9:关闭影藏排名\r\n10:入职\r\n11:离职\r\n12:获得头像框\r\n13:分成变动\r\n14:等级变动\r\n14:\r\n15:\r\n16:', + `operation_by` varchar(32) DEFAULT NULL COMMENT '操作人ID', + `remark` varchar(1000) DEFAULT NULL COMMENT '备注', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='店员操作日志'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_clerk_pk` +-- + +DROP TABLE IF EXISTS `play_clerk_pk`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_clerk_pk` ( + `id` varchar(32) NOT NULL DEFAULT '0' COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` varchar(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + `clerk_a` varchar(255) DEFAULT NULL COMMENT '店员A', + `clerk_b` varchar(255) DEFAULT NULL COMMENT '店员B', + `radio` int DEFAULT NULL COMMENT '比例', + `pk_begin_time` datetime DEFAULT NULL COMMENT '开始时间', + `pk_end_time` datetime DEFAULT NULL COMMENT '结束时间', + `punishment_time` datetime DEFAULT NULL COMMENT '惩罚公示时间', + `status` varchar(255) DEFAULT NULL COMMENT '状态', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='店员pk'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_clerk_ranking_info` +-- + +DROP TABLE IF EXISTS `play_clerk_ranking_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_clerk_ranking_info` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `clerk_id` varchar(255) DEFAULT NULL COMMENT '店员ID', + `historical_statistics` varchar(1) DEFAULT '0' COMMENT '是否为历史统计(1:是;0:不是)', + `weekly_ranking` varchar(1) DEFAULT NULL COMMENT '日排名还是周排名(0:每日排名;1:每周排名)', + `serial_number` int DEFAULT '0' COMMENT '统计序号', + `ranking_index` int DEFAULT NULL COMMENT '排行序号', + `start_count_date` date DEFAULT NULL COMMENT '开始统计时间', + `end_count_date` date DEFAULT NULL COMMENT '结束统计时间', + `order_number` varchar(255) DEFAULT '0' COMMENT '订单总数', + `order_money` decimal(10,2) DEFAULT '0.00' COMMENT '订单金额', + `order_continue_number` int DEFAULT '0' COMMENT '续单数', + `order_continue_money` decimal(10,2) DEFAULT '0.00' COMMENT '续单金额', + `previous_money` decimal(10,2) DEFAULT '0.00' COMMENT '距离前一名成绩', + `orders_expired_number` int DEFAULT '0' COMMENT '超时未接单数', + `custom_number` int DEFAULT NULL COMMENT '客户数量', + `order_continue_proportion` decimal(10,2) DEFAULT NULL COMMENT '续单比例', + `average_unit_price` decimal(10,2) DEFAULT NULL COMMENT '平均每单价格', + `settlement_date` date DEFAULT NULL COMMENT '统计时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='店员排行'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_clerk_resource info` +-- + +DROP TABLE IF EXISTS `play_clerk_resource info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_clerk_resource info` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `play_user_id` varchar(32) DEFAULT NULL COMMENT '陪玩用户ID', + `resource_type` tinyint(1) DEFAULT NULL COMMENT '资源分类\r\n0:图片\r\n1:录音\r\n2:视频', + `resource_address` varchar(1000) DEFAULT NULL COMMENT '资源地址', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='店员资源'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_clerk_type_info` +-- + +DROP TABLE IF EXISTS `play_clerk_type_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_clerk_type_info` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `type_name` varchar(255) DEFAULT NULL COMMENT '分类名称', + `sort` int DEFAULT NULL COMMENT '排序', + `home_displayed` varchar(1) DEFAULT NULL COMMENT '是否在首页显示(0:不显示;1显示)', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='店员分类信息'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_clerk_type_user_info` +-- + +DROP TABLE IF EXISTS `play_clerk_type_user_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_clerk_type_user_info` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `type_id` varchar(32) DEFAULT NULL COMMENT '分组ID', + `clerk_id` varchar(32) DEFAULT NULL COMMENT '店员ID', + `sort` int DEFAULT NULL COMMENT '排序', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='店员和分类关系'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_clerk_user_info` +-- + +DROP TABLE IF EXISTS `play_clerk_user_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_clerk_user_info` ( + `id` varchar(32) NOT NULL DEFAULT '0' COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `sys_user_id` varchar(32) DEFAULT NULL COMMENT '陪玩用户ID', + `phone` varchar(255) DEFAULT NULL COMMENT '电话号码', + `wei_chat_code` varchar(255) DEFAULT NULL COMMENT '微信号码', + `wei_chat_avatar` varchar(255) DEFAULT NULL, + `openid` varchar(255) NOT NULL COMMENT '用户的标识,对当前公众号唯一', + `nickname` varchar(255) DEFAULT NULL COMMENT '店员昵称', + `type_id` varchar(32) DEFAULT NULL COMMENT '店员类别', + `fixing_level` varchar(1) DEFAULT NULL COMMENT '是否固定等级(0:固定等级,1:不固定)', + `group_id` varchar(32) DEFAULT NULL COMMENT '分组ID', + `level_id` varchar(32) DEFAULT NULL COMMENT '店员等级', + `sex` varchar(1) DEFAULT NULL COMMENT '店员性别(1:男:0:女)', + `code` varchar(32) DEFAULT NULL COMMENT '身份证号', + `album` text COMMENT '相册', + `avatar` varchar(1000) DEFAULT NULL COMMENT '头像', + `avatar_frame_id` varchar(32) DEFAULT NULL COMMENT '头像框', + `audio` varchar(1000) DEFAULT NULL COMMENT '音频', + `constellation` varchar(255) DEFAULT NULL COMMENT '星座', + `label` text COMMENT '标签', + `signature` text COMMENT '个性签名', + `age` int DEFAULT NULL COMMENT '年龄', + `country` varchar(64) DEFAULT NULL COMMENT '所在国家', + `province` varchar(64) DEFAULT NULL COMMENT '所在省份', + `city` varchar(64) DEFAULT NULL COMMENT '所在城市', + `account_balance` decimal(10,2) DEFAULT '0.00' COMMENT '账户余额(单位分)', + `remark` text COMMENT '备注', + `onboarding_state` varchar(1) DEFAULT '1' COMMENT '在职状态(1:在职,1:离职)', + `entry_time` datetime DEFAULT NULL COMMENT '入职时间', + `resignation_time` datetime DEFAULT NULL COMMENT '离职时间', + `working_hours` int DEFAULT NULL COMMENT '工作天数', + `recommendation_state` varchar(1) DEFAULT '0' COMMENT '是否推荐状态(1:已推荐,0:未推荐)', + `pin_to_top_state` varchar(1) DEFAULT '0' COMMENT '是否置顶状态(1:已置顶,0:未置顶)', + `online_state` varchar(1) DEFAULT '0' COMMENT '在线状态【1:在线,0:离线】', + `listing_state` varchar(1) DEFAULT '1' COMMENT '上架状态【1:上架,0:下架】', + `display_state` varchar(1) DEFAULT '1' COMMENT '显示状态【1:显示,0:隐藏】', + `real_state` varchar(1) DEFAULT '0' COMMENT '实名状态【1:已实名,0:未实名】', + `mandatory_real_state` varchar(1) DEFAULT '0' COMMENT '是否必须实名【1:必须实名,0:非必须实名】', + `random_order_state` varchar(1) DEFAULT '1' COMMENT '随机接单状态【1:允许,0:禁止】', + `registration_time` datetime DEFAULT NULL COMMENT '注册时间', + `last_login_time` datetime DEFAULT NULL COMMENT '上次登录时间', + `clerk_state` varchar(1) DEFAULT '0' COMMENT '店员状态(0:不是陪玩,1:陪玩)', + `token` text, + `we_chat_code_image` varchar(1000) DEFAULT NULL COMMENT '微信二维码', + `we_chat_pay_image` varchar(1000) DEFAULT NULL COMMENT '微信收款码图片', + `alipay_image` varchar(1000) DEFAULT NULL COMMENT '支付宝收款码图片', + `add_time` datetime DEFAULT NULL COMMENT '创建时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` varchar(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE, + KEY `key_openid` (`openid`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='店员用户'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_clerk_user_review_info` +-- + +DROP TABLE IF EXISTS `play_clerk_user_review_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_clerk_user_review_info` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `clerk_id` varchar(32) DEFAULT NULL COMMENT '店员ID', + `wei_chat_code` varchar(255) DEFAULT NULL COMMENT '微信号码', + `phone` varchar(255) DEFAULT NULL COMMENT '手机号码', + `nickname` varchar(255) DEFAULT NULL COMMENT '昵称', + `sex` varchar(1) DEFAULT NULL COMMENT '性别[0:未知;1:男;2:女]', + `age` int DEFAULT NULL COMMENT '年龄', + `province` varchar(255) DEFAULT NULL COMMENT '所在省份', + `city` varchar(255) DEFAULT NULL COMMENT '所在城市', + `remark` text COMMENT '备注(相关经验)', + `audio` varchar(255) DEFAULT NULL COMMENT '音频', + `album` text COMMENT '照片', + `add_time` datetime(1) DEFAULT NULL COMMENT '申请时间', + `review_state` varchar(1) DEFAULT NULL COMMENT ' 审核状态(0:未审核:1:审核通过,2:审核不通过)', + `review_time` datetime(1) DEFAULT NULL COMMENT '审核时间', + `review_by` varchar(32) DEFAULT NULL COMMENT '审核人', + `review_con` text COMMENT '审核内容', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='店员资料审核'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_clerk_wages_details_info` +-- + +DROP TABLE IF EXISTS `play_clerk_wages_details_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_clerk_wages_details_info` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `wages_id` varchar(32) DEFAULT '0' COMMENT '工资统计ID', + `clerk_id` varchar(255) DEFAULT NULL COMMENT '店员ID', + `order_id` varchar(32) DEFAULT NULL COMMENT '订单ID', + `order_no` varchar(32) DEFAULT NULL COMMENT '订单编号', + `final_amount` decimal(10,2) DEFAULT NULL COMMENT '订单最终金额(支付金额)', + `estimated_revenue` decimal(10,2) DEFAULT NULL COMMENT '工资金额', + `end_order_time` datetime DEFAULT NULL COMMENT '订单完成时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='店员工资明细信息'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_clerk_wages_info` +-- + +DROP TABLE IF EXISTS `play_clerk_wages_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_clerk_wages_info` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `clerk_id` varchar(255) DEFAULT NULL COMMENT '店员ID', + `historical_statistics` varchar(1) DEFAULT '0' COMMENT '是否为历史统计(1:是;0:不是)', + `serial_number` int DEFAULT '0' COMMENT '统计序号', + `ranking_index` int DEFAULT NULL COMMENT '排行序号', + `start_count_date` date DEFAULT NULL COMMENT '开始统计时间', + `end_count_date` date DEFAULT NULL COMMENT '结束统计时间', + `settlement_date` date DEFAULT NULL COMMENT '统计时间', + `order_number` int DEFAULT '0' COMMENT '订单总数', + `final_amount` decimal(10,2) DEFAULT '0.00' COMMENT '订单金额', + `order_continue_number` int DEFAULT '0' COMMENT '续单数', + `order_continue_proportion` float DEFAULT NULL COMMENT '续单比例', + `order_continue_money` decimal(10,2) DEFAULT '0.00' COMMENT '续单金额', + `orders_expired_number` int DEFAULT '0' COMMENT '超时未接单数', + `estimated_revenue` decimal(10,2) DEFAULT NULL COMMENT '店员收入', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='店员工资结算信息'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_clerk_waiter_info` +-- + +DROP TABLE IF EXISTS `play_clerk_waiter_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_clerk_waiter_info` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `sys_user_id` varchar(255) DEFAULT NULL COMMENT '账号ID', + `waiter_name` varchar(255) DEFAULT NULL COMMENT '客服名称', + `sort` int DEFAULT NULL COMMENT '排序', + `add_time` datetime DEFAULT NULL COMMENT '添加时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='客服信息'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_commodity_and_level_info` +-- + +DROP TABLE IF EXISTS `play_commodity_and_level_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_commodity_and_level_info` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `commodity_id` varchar(32) DEFAULT NULL COMMENT '商品ID', + `level_id` varchar(255) DEFAULT NULL COMMENT '店员等级ID', + `price` decimal(10,2) DEFAULT NULL COMMENT '服务单价', + `sort` int DEFAULT NULL COMMENT '排序', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='服务项目和店员等级数据'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_commodity_info` +-- + +DROP TABLE IF EXISTS `play_commodity_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_commodity_info` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `p_id` varchar(32) DEFAULT NULL COMMENT 'pid', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `item_type` varchar(255) DEFAULT NULL COMMENT '项目类型', + `item_name` varchar(255) DEFAULT NULL COMMENT '项目名称', + `service_duration` varchar(255) DEFAULT NULL COMMENT '服务时长(文字描述信息,不参与订单计算)', + `automatic_settlement_duration` int DEFAULT '-1' COMMENT '接单后自动结算等待时长(单位,秒,-1:不自动结算)', + `price` decimal(10,2) DEFAULT NULL COMMENT '服务单价', + `sort` int DEFAULT NULL COMMENT '排序', + `enable_stace` varchar(1) DEFAULT '1' COMMENT '启用状态(0:停用,1:启用)', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='服务项目和价格'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_coupon_details` +-- + +DROP TABLE IF EXISTS `play_coupon_details`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_coupon_details` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `custom_id` varchar(255) DEFAULT NULL COMMENT '顾客ID', + `custom_nickname` varchar(255) DEFAULT NULL COMMENT '顾客昵称', + `custom_level_id` varchar(255) DEFAULT NULL COMMENT '顾客等级ID', + `coupon_id` varchar(255) DEFAULT NULL COMMENT '优惠券名称', + `obtaining_channels` varchar(1) DEFAULT NULL COMMENT '获得渠道(1:自主领取;2:后台发放;3:退款返还;4:分享领取;5:抽奖获得)', + `use_state` varchar(1) DEFAULT NULL COMMENT '使用状态(1:未使用;2:已使用;3:已回收)', + `discount_type` varchar(1) DEFAULT NULL COMMENT '优惠类型(0:满减;1:折扣)', + `discount_content` varchar(255) DEFAULT NULL COMMENT '优惠内容,文字展示', + `discount_amount` decimal(10,2) DEFAULT NULL COMMENT '折扣值', + `validity_period_type` varchar(1) DEFAULT NULL COMMENT '有效期类型(0:永久有效;1:临时有效)', + `expiration_time` datetime DEFAULT NULL COMMENT '到期时间', + `obtaining_time` datetime DEFAULT NULL COMMENT '获得时间', + `use_time` datetime DEFAULT NULL COMMENT '使用时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='优惠券详情'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_coupon_info` +-- + +DROP TABLE IF EXISTS `play_coupon_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_coupon_info` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `coupon_name` varchar(255) DEFAULT NULL COMMENT '优惠券名称', + `validity_period_type` varchar(1) DEFAULT NULL COMMENT '有效期类型(0:永久有效;1:固定时间内有效;2:领取后几天内有效)', + `productive_time` datetime DEFAULT NULL COMMENT '生效时间', + `expiration_time` datetime DEFAULT NULL COMMENT '到期时间', + `effective_day` int DEFAULT NULL COMMENT '生效时长,validityPeriodType=2时有效', + `use_min_amount` decimal(10,2) DEFAULT NULL COMMENT '使用优惠券最近消费金额', + `discount_type` varchar(1) DEFAULT NULL COMMENT '优惠类型(0:满减;1:折扣)', + `discount_content` varchar(255) DEFAULT NULL COMMENT '优惠内容,文字展示', + `discount_amount` decimal(10,2) DEFAULT NULL COMMENT '折扣值', + `attribution_discounts` varchar(1) DEFAULT '1' COMMENT '优惠金额是否由店铺承担(0:不是;1:是)', + `place_type` varchar(255) DEFAULT NULL COMMENT '下单类型(0:指定单,1:随机单。2:打赏单)', + `clerk_type` varchar(1) DEFAULT '0' COMMENT '店员范围(0:所有店员)', + `coupon_quantity` int DEFAULT '0' COMMENT '优惠券总数(-1表示不限制数量)', + `issued_quantity` int DEFAULT '0' COMMENT '已发放数量', + `remaining_quantity` int DEFAULT '0' COMMENT '剩余数量', + `clerk_obtained_max_quantity` int DEFAULT '1' COMMENT '店员获得最大数量', + `claim_condition_type` varchar(1) DEFAULT NULL COMMENT '领取条件类型(0:所有人可领取,1:指定条件领取)', + `custom_level_check_type` varchar(1) DEFAULT NULL COMMENT '顾客等级选择状态(0:未选择,1:选择)', + `custom_level` varchar(255) DEFAULT NULL COMMENT '顾客等级', + `custom_follow_status_check_type` varchar(1) DEFAULT NULL COMMENT '用户关注公众号选择状态(0:未选择,1:选择)', + `custom_follow_status` varchar(2) DEFAULT '-1' COMMENT '顾客关注公众号状态(0:未关注;1:已关注)', + `custom_sex_check_type` varchar(1) DEFAULT NULL COMMENT ' 顾客性别选择状态(0:未选择,1:选择)', + `custom_sex` varchar(255) DEFAULT NULL COMMENT '顾客性别(0:未知;1:男,2:女)', + `new_user` varchar(1) DEFAULT NULL COMMENT '仅限新用户领取(0:不是;1:是)(没有下过单的用户,下单后再退单也不算)', + `coupon_on_line_state` varchar(1) DEFAULT NULL COMMENT '优惠券上架状态(0;下架;1:上架)', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='优惠券信息'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_custom_amount details` +-- + +DROP TABLE IF EXISTS `play_custom_amount details`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_custom_amount details` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `coston_id` varchar(32) DEFAULT NULL COMMENT '客户ID', + `operate` varchar(1) DEFAULT NULL COMMENT '操作【0;1:2】\r\n0:充值\r\n1:消费\r\n2;退款', + `trade_method` varchar(1) DEFAULT NULL COMMENT '交易方式\r\n0:微信支付\r\n1:其他支付', + ` +initial_amount` varchar(255) DEFAULT NULL COMMENT '交易前账户金额(单位分)', + `trade_amount` varchar(255) DEFAULT NULL COMMENT '交易金额(单位分)', + `account_balance` varchar(255) DEFAULT NULL COMMENT '交易后账户余额(单位分)', + `order_id` varchar(255) DEFAULT NULL COMMENT '订单ID', + `remark` varchar(1000) DEFAULT NULL COMMENT '备注', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='顾客金额详细'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_custom_article_info` +-- + +DROP TABLE IF EXISTS `play_custom_article_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_custom_article_info` ( + `id` varchar(32) NOT NULL DEFAULT '0' COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `article_id` varchar(32) DEFAULT NULL COMMENT '动态ID', + `clerk_id` varchar(32) DEFAULT NULL COMMENT '店员ID', + `custom_id` varchar(32) DEFAULT NULL COMMENT '顾客ID', + `endorse_state` varchar(1) DEFAULT NULL COMMENT '赞同状态(1:赞同,0:未赞同)', + `endorse_type` varchar(1) DEFAULT NULL COMMENT '赞同类型(1:点赞;0:收藏)', + `endorse_time` datetime NOT NULL COMMENT '赞同时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` varchar(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE, + KEY `key_openid` (`endorse_time`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='陪玩点赞动态信息'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_custom_follow_info` +-- + +DROP TABLE IF EXISTS `play_custom_follow_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_custom_follow_info` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `custom_id` varchar(32) DEFAULT NULL COMMENT '顾客ID', + `clerk_id` varchar(32) DEFAULT NULL COMMENT '陪玩ID', + `follow_time` datetime DEFAULT NULL COMMENT '关注时间', + `unfollow_time` datetime(1) DEFAULT NULL COMMENT '取消关注时间', + `follow_state` varchar(1) DEFAULT NULL COMMENT '关注状态[0:未关注,1:已关注]', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='顾客关注陪玩信息'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_custom_gift_info` +-- + +DROP TABLE IF EXISTS `play_custom_gift_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_custom_gift_info` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `custom_id` varchar(32) DEFAULT NULL COMMENT '顾客ID', + `giff_id` varchar(32) DEFAULT NULL COMMENT '礼物ID', + `giff_number` int DEFAULT NULL COMMENT '礼物数量', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE, + KEY `key_openid` (`custom_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='顾客和礼物关系'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_custom_leave_msg` +-- + +DROP TABLE IF EXISTS `play_custom_leave_msg`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_custom_leave_msg` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `custom_id` varchar(32) DEFAULT NULL COMMENT '顾客ID', + `content` longtext COMMENT '留言内容', + `images` text COMMENT '图片', + `msg_time` datetime DEFAULT NULL COMMENT '留言时间', + `remark` longtext COMMENT '备注', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE, + KEY `key_openid` (`custom_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='顾客留言'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_custom_level_info` +-- + +DROP TABLE IF EXISTS `play_custom_level_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_custom_level_info` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `name` varchar(255) DEFAULT NULL COMMENT '等级名称', + `level` tinyint(1) DEFAULT NULL COMMENT '等级数字(排序字段)', + `consumption_amount` varchar(255) DEFAULT NULL COMMENT '上一级消费金额', + `discount` tinyint(1) DEFAULT NULL COMMENT '满减比例', + `avatar_frame_address` varchar(1000) DEFAULT NULL COMMENT '头像框地址', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='顾客等级'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_custom_user_info` +-- + +DROP TABLE IF EXISTS `play_custom_user_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_custom_user_info` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `openid` varchar(255) DEFAULT NULL COMMENT '用户的标识,对当前公众号唯一', + `unionid` varchar(255) DEFAULT NULL COMMENT ' 用户的标识,对当前公众号唯一', + `nickname` varchar(255) DEFAULT NULL COMMENT '顾客昵称', + `sex` tinyint(1) DEFAULT NULL COMMENT '顾客性别(0:位置;1:男,2:女)', + `avatar` varchar(1000) DEFAULT NULL COMMENT '头像', + `phone` varchar(255) DEFAULT NULL COMMENT '电话号码', + `wei_chat_code` varchar(255) DEFAULT NULL COMMENT '微信号码', + `level_id` varchar(32) DEFAULT NULL COMMENT '等级', + `country` varchar(64) DEFAULT NULL COMMENT '所在国家', + `province` varchar(64) DEFAULT NULL COMMENT '所在省份', + `city` varchar(64) DEFAULT NULL COMMENT '所在城市', + `accumulated_recharge_amount` decimal(10,2) DEFAULT '0.00' COMMENT '累计充值金额', + `accumulated_consumption_amount` decimal(10,2) DEFAULT NULL COMMENT '累计消费金额', + `account_balance` decimal(10,2) DEFAULT '0.00' COMMENT '账户余额(单位分)', + `account_state` varchar(1) DEFAULT '0' COMMENT '余额状态[0:不存在余额,1:存在余额]', + `subscribe_state` varchar(1) DEFAULT '0' COMMENT '关注状态[0:未关注,1:已关注]', + `blacklist_state` varchar(1) DEFAULT '0' COMMENT '黑名单状态[0:非黑名单,1:黑名单]', + `violation_state` varchar(1) DEFAULT '0' COMMENT '违规状态[0:未违规,1:违规]', + `purchase_state` varchar(1) DEFAULT '0' COMMENT '是否下单状态[0:未未下单,1:下单过]', + `mobile_phone_state` varchar(1) DEFAULT '0' COMMENT '绑定手机状态[0:未绑定,1:绑定]', + `real_state` varchar(1) DEFAULT '0' COMMENT '实名状态【1:已实名,0:未实名】', + `mandatory_real_state` varchar(1) DEFAULT '0' COMMENT '是否必须实名【2:跟随店铺设置,1:必须实名,0:非必须实名】', + `registration_time` datetime DEFAULT NULL COMMENT '注册时间', + `last_login_time` datetime DEFAULT NULL COMMENT '上次登录时间', + `first_purchase_time` datetime DEFAULT NULL COMMENT '首次下单时间', + `last_purchase_time` datetime DEFAULT NULL COMMENT '最后一次下单时间', + `hide_level_state` varchar(1) DEFAULT '0' COMMENT '隐藏等级[0:不隐藏;1:隐藏]', + `hide_ranking_state` varchar(1) DEFAULT '0' COMMENT '隐藏排名[0:不隐藏;1:隐藏]', + `remark` text COMMENT '备注', + `token` text, + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE, + KEY `key_openid` (`openid`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='顾客'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_gift_info` +-- + +DROP TABLE IF EXISTS `play_gift_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_gift_info` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `history` varchar(1) DEFAULT '0' COMMENT '是否是历史礼物(0:不是,1:是)', + `name` varchar(255) DEFAULT NULL COMMENT '礼物名称', + `type` varchar(255) DEFAULT NULL COMMENT '礼物类型(0:盲盒,1:普通礼物)', + `url` varchar(1000) DEFAULT NULL COMMENT '礼物图片地址', + `price` decimal(10,2) DEFAULT '0.00' COMMENT '单价', + `unit` varchar(255) DEFAULT NULL COMMENT '价格单位', + `state` varchar(2) DEFAULT '0' COMMENT '状态(0:正常,1:下架)', + `listing_time` datetime DEFAULT NULL COMMENT '上架时间', + `delinting_time` datetime DEFAULT NULL COMMENT '下架时间', + `remark` text COMMENT '备注', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE, + KEY `key_openid` (`name`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='礼物'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_notice_info` +-- + +DROP TABLE IF EXISTS `play_notice_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_notice_info` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `notice_type` varchar(1) DEFAULT NULL COMMENT '公告类型【0:公告,1:消息】', + `title` text COMMENT '标题', + `content` text COMMENT '内容', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='公告'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_order_complaint_info` +-- + +DROP TABLE IF EXISTS `play_order_complaint_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_order_complaint_info` ( + `id` varchar(255) NOT NULL COMMENT 'uuid', + `tenant_id` varchar(32) DEFAULT NULL COMMENT '租户ID', + `order_id` varchar(32) DEFAULT NULL COMMENT '订单ID', + `custom_id` varchar(32) DEFAULT NULL COMMENT '顾客ID', + `clerk_id` varchar(32) DEFAULT NULL COMMENT '店员ID', + `commodity_id` varchar(32) DEFAULT NULL COMMENT '商品ID', + `wx_chat_code` varchar(255) DEFAULT NULL COMMENT '投诉人微信号码', + `complaint_con` text COMMENT '投诉内容', + `complaint_time` datetime DEFAULT NULL COMMENT '投诉时间', + `images` text COMMENT '图片列表', + `hidden` varchar(1) DEFAULT '0' COMMENT '数据是否隐藏(0:未隐藏,1:隐藏)', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='订单投诉信息'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_order_continue_info` +-- + +DROP TABLE IF EXISTS `play_order_continue_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_order_continue_info` ( + `id` varchar(255) NOT NULL COMMENT 'uuid', + `tenant_id` varchar(32) DEFAULT NULL COMMENT '租户ID', + `order_id` varchar(32) DEFAULT NULL COMMENT '订单ID', + `order_no` varchar(32) DEFAULT NULL COMMENT '订单号码', + `custom_id` varchar(32) DEFAULT NULL COMMENT '顾客ID', + `clerk_id` varchar(32) DEFAULT NULL COMMENT '店员ID', + `place_type` varchar(1) DEFAULT '0' COMMENT '下单类型(0:指定单,1:随机单。2:打赏单)', + `order_money` decimal(10,2) DEFAULT NULL COMMENT '下单金额', + `final_amount` decimal(10,2) DEFAULT NULL COMMENT '支付金额', + `continue_msg` text COMMENT '申请消息', + `images` text COMMENT '截图', + `reviewed_required` varchar(1) DEFAULT NULL COMMENT '是否需要审核,0:不需要,1:需要', + `reviewed_state` varchar(1) DEFAULT NULL COMMENT '审核状态(0:未审核,1:已通过,2:不通过)', + `reviewed_by` varchar(32) DEFAULT NULL COMMENT '审核人', + `reviewed_time` datetime DEFAULT NULL COMMENT '审核时间', + `reviewed_remark` varchar(255) DEFAULT NULL COMMENT '审核内容', + `continue_time` datetime DEFAULT NULL COMMENT '申请时间', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='订单续单信息'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_order_demand_info` +-- + +DROP TABLE IF EXISTS `play_order_demand_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_order_demand_info` ( + `id` varchar(255) NOT NULL COMMENT 'uuid', + `tenant_id` varchar(32) DEFAULT NULL COMMENT '租户ID', + `order_id` varchar(2) DEFAULT NULL COMMENT '订单ID', + `sex` varchar(1) DEFAULT NULL COMMENT '店员性别(0:位置;1:男,2:女)', + `level_id` varchar(32) DEFAULT NULL COMMENT '店员等级ID', + `commodity_id` varchar(32) DEFAULT NULL COMMENT '服务项目类型\r\n', + `commodity_number` int DEFAULT NULL COMMENT '商品数量', + `lables` text COMMENT '标签', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='订单需求(随机单使用)'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_order_evaluate_info` +-- + +DROP TABLE IF EXISTS `play_order_evaluate_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_order_evaluate_info` ( + `id` varchar(255) NOT NULL COMMENT 'uuid', + `tenant_id` varchar(32) DEFAULT NULL COMMENT '租户ID', + `order_id` varchar(32) DEFAULT NULL COMMENT '订单ID', + `custom_id` varchar(32) DEFAULT NULL COMMENT '顾客ID', + `clerk_id` varchar(32) DEFAULT NULL COMMENT '店员ID', + `commodity_id` varchar(32) DEFAULT NULL COMMENT '商品ID', + `anonymous` varchar(1) DEFAULT '1' COMMENT '匿名评价(0:匿名,1:非匿名)', + `evaluate_type` varchar(1) DEFAULT '0' COMMENT '评价类型(0:好评,1差评)', + `evaluate_level` bigint DEFAULT NULL COMMENT '评价等级【1-5星,最低1星,最高5星】', + `evaluate_con` text COMMENT '评价内容', + `evaluate_time` datetime DEFAULT NULL COMMENT '评价时间', + `hidden` varchar(1) DEFAULT '0' COMMENT '数据是否隐藏(0:未隐藏,1:隐藏)', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='订单评价信息'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_order_info` +-- + +DROP TABLE IF EXISTS `play_order_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_order_info` ( + `id` varchar(255) NOT NULL COMMENT 'uuid', + `tenant_id` varchar(32) DEFAULT NULL COMMENT '租户ID', + `order_no` varchar(20) DEFAULT NULL COMMENT '订单编号', + `backend_entry` varchar(1) DEFAULT '0' COMMENT '订单是否是客服录入订单[0:不是,1:是]', + `order_status` varchar(2) DEFAULT NULL COMMENT '订单状态【0:1:2:3:4】\r\n0:已下单(待接单)\r\n1:已接单(待开始)\r\n2:已开始(服务中)\r\n3:已完成\r\n4:已取消', + `order_type` varchar(2) DEFAULT NULL COMMENT '订单类型【-1:退款订单;0:充值订单;1:提现订单;2:普通订单】', + `place_type` varchar(2) DEFAULT NULL COMMENT '下单类型(0:指定单,1:随机单。2:打赏单)', + `reward_type` varchar(1) DEFAULT NULL COMMENT '打赏类型(0:余额;1:礼物)', + `first_order` varchar(2) DEFAULT '1' COMMENT '是否是首单【0:不是。1:是】', + `refund_type` varchar(2) DEFAULT '0' COMMENT '退款类型【0:未退款,1:已退款】', + `refund_amount` decimal(10,2) DEFAULT '0.00' COMMENT '退款金额', + `refund_reason` varchar(255) DEFAULT NULL COMMENT '退款原因', + `order_money` decimal(10,2) DEFAULT '0.00' COMMENT '下单金额', + `discount_amount` decimal(10,2) DEFAULT '0.00' COMMENT '优惠金额', + `final_amount` decimal(10,2) DEFAULT '0.00' COMMENT '最终金额(下单金额 - 退款金额)。单位分', + `estimated_revenue` decimal(10,2) DEFAULT '0.00' COMMENT '店员预计收入', + `estimated_revenue_ratio` int DEFAULT NULL COMMENT '店员提成比例', + `labels` text COMMENT '订单要求', + `sex` varchar(2) DEFAULT NULL COMMENT '随机单要求-店员性别(0:未知;1:男;2:女)', + `level_id` varchar(32) DEFAULT NULL COMMENT '随机单要求-店员等级ID', + `exclude_history` varchar(1) DEFAULT NULL COMMENT '随机单要求-是否排除下单过的成员(0:不排除;1:排除)', + `commodity_id` varchar(32) DEFAULT NULL COMMENT '商品ID', + `commodity_type` varchar(1) DEFAULT NULL COMMENT '商品类型[0:礼物,1:服务]', + `commodity_price` decimal(10,2) DEFAULT NULL COMMENT '商品单价', + `commodity_name` varchar(255) DEFAULT NULL COMMENT '商品名称', + `service_duration` varchar(255) DEFAULT NULL COMMENT '商品属性(服务时长)', + `commodity_number` int DEFAULT NULL COMMENT '商品数量', + `coupon_ids` text COMMENT '优惠券列表', + `use_coupon` varchar(1) DEFAULT '0' COMMENT '是否使用优惠券[0:未使用,1:已使用]', + `pay_method` varchar(2) DEFAULT '0' COMMENT '支付方式,0:余额支付,1:微信支付,2:支付宝支付', + `pay_state` varchar(2) DEFAULT NULL COMMENT '支付状态,[-1:支付失败;0:未支付;1:支付中,2:支付完成]', + `pay_msg` text COMMENT '支付备注', + `purchaser_by` varchar(32) DEFAULT '0' COMMENT '下单人', + `purchaser_time` datetime DEFAULT NULL COMMENT '下单时间', + `wei_chat_code` varchar(255) DEFAULT NULL COMMENT '微信号码', + `review_required` varchar(2) DEFAULT NULL COMMENT '是否需要审核,0:不需要,1:需要', + `review_state` varchar(2) DEFAULT NULL COMMENT '审核状态(0:未审核,1:已通过,2:不通过)', + `reviewed_by` varchar(32) DEFAULT NULL COMMENT '审核人', + `reviewed_time` datetime DEFAULT NULL COMMENT '审核时间', + `reviewed_remark` varchar(255) DEFAULT NULL COMMENT '审核内容', + `remark` longtext COMMENT '订单备注', + `backend_remark` text COMMENT '后台备注', + `accept_by` varchar(255) DEFAULT NULL COMMENT '接单人', + `accept_time` datetime DEFAULT NULL COMMENT '接单时间', + `group_id` varchar(32) DEFAULT NULL COMMENT '订单分组ID(和接单人同一个分组,接单时设置)', + `order_start_time` datetime DEFAULT NULL COMMENT '开始时间', + `order_end_time` datetime DEFAULT NULL COMMENT '完成时间', + `order_cancel_time` datetime DEFAULT NULL COMMENT '取消时间', + `order_settlement_state` varchar(1) DEFAULT '0' COMMENT '订单结算状态(0:未结算;1:已结算)', + `order_settlement_time` datetime DEFAULT NULL COMMENT '订单结算时间', + `orders_expired_state` varchar(1) DEFAULT '0' COMMENT '订单超时状态(0:未超时;1:已超时)', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + `profit_sharing_amount` decimal(20,2) DEFAULT NULL COMMENT '分账金额', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='订单信息'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_order_log_info` +-- + +DROP TABLE IF EXISTS `play_order_log_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_order_log_info` ( + `id` varchar(255) NOT NULL COMMENT 'uuid', + `tenant_id` varchar(32) DEFAULT NULL COMMENT '租户ID', + `order_id` varchar(1) DEFAULT NULL COMMENT '订单ID', + `oper_type` varchar(1) DEFAULT NULL COMMENT '操作类型\r\n0:下单\r\n1:审核\r\n2:接单\r\n3:服务\r\n4:完成\r\n5:取消', + `oper_time` datetime(1) DEFAULT NULL COMMENT '操作时间', + `remark` varchar(255) DEFAULT NULL COMMENT '备注', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='订单日志'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_order_random_info` +-- + +DROP TABLE IF EXISTS `play_order_random_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_order_random_info` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `sex` varchar(100) DEFAULT NULL COMMENT '店员性别(0:未知;1:男;2:女)', + `level_id` varchar(100) DEFAULT NULL COMMENT '店员等级ID', + `labels` text COMMENT '标签列表', + `commodity_id` varchar(32) DEFAULT NULL COMMENT '商品ID', + `commodity_price` decimal(10,2) DEFAULT NULL COMMENT '商品单价', + `commodity_name` varchar(255) DEFAULT NULL COMMENT '商品名称', + `commodity_number` int DEFAULT NULL COMMENT '商品数量', + `service_duration` varchar(255) DEFAULT NULL COMMENT '服务时长', + `wei_chat_code` varchar(100) DEFAULT NULL COMMENT '微信号', + `exclude_history` varchar(100) DEFAULT NULL COMMENT '是否排除下单过的成员(0:不排除;1:排除)', + `remark` text COMMENT '备注', + `purchaser_by` varchar(32) DEFAULT NULL COMMENT '下单人', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='随机单列表'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_order_refund_info` +-- + +DROP TABLE IF EXISTS `play_order_refund_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_order_refund_info` ( + `id` varchar(255) NOT NULL COMMENT 'uuid', + `tenant_id` varchar(32) DEFAULT NULL COMMENT '租户ID', + `order_id` varchar(32) DEFAULT NULL COMMENT '订单ID', + `custom_id` varchar(32) DEFAULT NULL COMMENT '顾客ID', + `clerk_id` varchar(32) DEFAULT NULL COMMENT '店员ID', + `pay_method` varchar(1) DEFAULT '0' COMMENT '支付方式,[0:余额支付;1:微信支付,2:支付宝支付]', + `use_coupon` varchar(1) DEFAULT NULL COMMENT '是否使用优惠券[0:未使用,1:已使用]', + `refund_type` varchar(1) DEFAULT '0' COMMENT '退款类型【0:部分退款;1:全部退款】', + `refund_amount` decimal(10,2) DEFAULT NULL COMMENT '退款金额', + `refund_reason` text COMMENT '退款原因', + `refund_by_type` varchar(1) DEFAULT NULL COMMENT '退款人类型[0:顾客;1:店员;2:组长]', + `refund_by_id` varchar(32) DEFAULT NULL COMMENT '退款人ID', + `images` text COMMENT '截图', + `refund_state` varchar(2) DEFAULT '0' COMMENT '退款状态[-1:异常;0:处理中;1:成功;2:关闭]', + `reviewed_required` varchar(1) DEFAULT NULL COMMENT '是否需要审核,0:不需要,1:需要', + `reviewed_state` varchar(1) DEFAULT NULL COMMENT '审核状态(0:未审核,1:已通过,2:不通过)', + `reviewed_by` varchar(32) DEFAULT NULL COMMENT '审核人', + `reviewed_time` datetime DEFAULT NULL COMMENT '审核时间', + `reviewed_remark` varchar(255) DEFAULT NULL COMMENT '审核内容', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='订单退款信息'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_personnel_admin_info` +-- + +DROP TABLE IF EXISTS `play_personnel_admin_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_personnel_admin_info` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `sys_user_id` varchar(255) DEFAULT NULL COMMENT '账号ID', + `sys_user_code` varchar(255) DEFAULT NULL COMMENT '用户账号', + `admin_name` varchar(255) DEFAULT NULL COMMENT '分组名称', + `leader_name` varchar(255) DEFAULT NULL COMMENT '组长名称', + `add_time` datetime DEFAULT NULL COMMENT '添加时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='管理员管理'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_personnel_group_info` +-- + +DROP TABLE IF EXISTS `play_personnel_group_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_personnel_group_info` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `sys_user_id` varchar(255) DEFAULT NULL COMMENT '账号ID', + `sys_user_code` varchar(255) DEFAULT NULL COMMENT '用户账号', + `group_name` varchar(255) DEFAULT NULL COMMENT '分组名称', + `leader_name` varchar(255) DEFAULT NULL COMMENT '组长名称', + `add_time` datetime DEFAULT NULL COMMENT '添加时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='分组管理'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_personnel_waiter_info` +-- + +DROP TABLE IF EXISTS `play_personnel_waiter_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_personnel_waiter_info` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `sys_user_id` varchar(255) DEFAULT NULL COMMENT '账号ID', + `sys_user_code` varchar(255) DEFAULT NULL COMMENT '用户账号', + `waiter_name` varchar(255) DEFAULT NULL COMMENT '客服名称', + `add_time` datetime DEFAULT NULL COMMENT '添加时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='客服管理'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_shop_article_info` +-- + +DROP TABLE IF EXISTS `play_shop_article_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_shop_article_info` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `article_type` varchar(255) DEFAULT NULL COMMENT '文章类型', + `article_title` varchar(255) DEFAULT '0' COMMENT '文章标标题', + `article_content` text COMMENT '文章内容', + `visits_number` int DEFAULT '0' COMMENT '浏览量', + `sort` int DEFAULT '0' COMMENT '排序', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE, + KEY `key_openid` (`article_type`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='店铺文章信息'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `play_shop_carousel_info` +-- + +DROP TABLE IF EXISTS `play_shop_carousel_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `play_shop_carousel_info` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `carousel_index` varchar(1) DEFAULT NULL COMMENT '轮播图位置(0:首页)', + `enable_state` varchar(1) DEFAULT '0' COMMENT '启用状态(0:未启用,1:已启用)', + `carousel_url` text COMMENT '图片URL', + `navigation_type` varchar(1) DEFAULT '0' COMMENT '导航类型(0:无)', + `sort` int DEFAULT '0' COMMENT '排序', + `add_time` datetime DEFAULT NULL COMMENT '创建时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`id`) USING BTREE, + KEY `key_tenant_id` (`tenant_id`) USING BTREE, + KEY `key_openid` (`carousel_index`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='店铺首页轮播'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `sys_administrative_area_dict_info` +-- + +DROP TABLE IF EXISTS `sys_administrative_area_dict_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `sys_administrative_area_dict_info` ( + `id` varchar(255) NOT NULL COMMENT 'UUID', + `code` varchar(255) DEFAULT NULL COMMENT '编码', + `name` varchar(255) DEFAULT NULL COMMENT '名称', + `level` varchar(2) DEFAULT NULL COMMENT '区域等级', + `p_code` varchar(32) DEFAULT NULL COMMENT '上级单位编码', + `created_by` varchar(32) DEFAULT NULL COMMENT '操作人ID', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + `tenant_id` varchar(32) DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='地区信息'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `sys_dept` +-- + +DROP TABLE IF EXISTS `sys_dept`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `sys_dept` ( + `dept_id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `parent_id` bigint NOT NULL DEFAULT '0' COMMENT '父部门id', + `ancestors` varchar(50) NOT NULL COMMENT '祖级列表', + `dept_name` varchar(30) DEFAULT NULL COMMENT '部门名称', + `sort` int DEFAULT NULL COMMENT '显示顺序', + `leader` varchar(20) DEFAULT NULL COMMENT '负责人', + `phone` varchar(11) DEFAULT NULL COMMENT '联系电话', + `email` varchar(30) DEFAULT NULL COMMENT '邮箱', + `status` tinyint(1) DEFAULT '0' COMMENT '部门状态(0正常 1停用)', + `dept_level` int DEFAULT NULL COMMENT '部门级别', + `tenant_id` varchar(32) DEFAULT NULL COMMENT '租户ID', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`dept_id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=67 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='部门表'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `sys_dict` +-- + +DROP TABLE IF EXISTS `sys_dict`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `sys_dict` ( + `dict_id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `dict_type` varchar(30) NOT NULL COMMENT '字典类型', + `dict_name` varchar(30) DEFAULT NULL COMMENT '字典名称', + `status` tinyint(1) DEFAULT '0' COMMENT '状态(0正常 1停用)', + `remark` varchar(100) DEFAULT NULL COMMENT '备注', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`dict_id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='字典表'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `sys_dict_data` +-- + +DROP TABLE IF EXISTS `sys_dict_data`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `sys_dict_data` ( + `dict_data_id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `dict_type` varchar(30) NOT NULL COMMENT '字典类型', + `dict_label` varchar(30) DEFAULT NULL COMMENT '字典名称', + `dict_value` varchar(100) DEFAULT NULL COMMENT '字典值', + `sort` int DEFAULT NULL COMMENT '显示顺序', + `is_default` char(1) DEFAULT 'N' COMMENT '是否默认(Y是 N否)', + `list_class` varchar(100) DEFAULT NULL COMMENT '表格回显样式', + `status` tinyint(1) DEFAULT '0' COMMENT '状态(0正常 1停用)', + `remark` varchar(100) DEFAULT NULL COMMENT '备注', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`dict_data_id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='字典数据表'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `sys_login_log` +-- + +DROP TABLE IF EXISTS `sys_login_log`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `sys_login_log` ( + `login_id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `user_code` varchar(50) NOT NULL DEFAULT '0' COMMENT '用户账号', + `ipaddr` varchar(128) NOT NULL COMMENT '登录IP地址', + `login_location` varchar(255) DEFAULT NULL COMMENT '登录地点', + `browser` varchar(50) DEFAULT NULL COMMENT '浏览器类型', + `os` varchar(50) DEFAULT NULL COMMENT '操作系统', + `msg` varchar(255) DEFAULT NULL COMMENT '提示消息', + `status` tinyint(1) DEFAULT '0' COMMENT '登录状态(0成功 1失败)', + `login_time` datetime DEFAULT NULL COMMENT '访问时间', + `tenant_id` varchar(32) DEFAULT NULL COMMENT '租户ID', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`login_id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=913 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='系统访问日志表'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `sys_menu` +-- + +DROP TABLE IF EXISTS `sys_menu`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `sys_menu` ( + `menu_id` bigint NOT NULL AUTO_INCREMENT COMMENT '菜单ID', + `menu_name` varchar(64) DEFAULT NULL COMMENT '菜单名称', + `menu_code` varchar(20) DEFAULT NULL COMMENT '前端名称', + `icon` varchar(100) DEFAULT '#' COMMENT '菜单图标', + `permission` varchar(100) DEFAULT NULL COMMENT '授权标识', + `menu_level` bigint DEFAULT NULL COMMENT '菜单级别', + `sort` int DEFAULT NULL COMMENT '排序', + `parent_id` bigint DEFAULT NULL COMMENT '父ID', + `menu_type` tinyint unsigned NOT NULL DEFAULT '1' COMMENT '菜单类型;1:有界面可访问菜单,2:无界面可访问菜单,0:只作为菜单', + `status` tinyint unsigned NOT NULL DEFAULT '0' COMMENT '鐘舵€?1:鏄剧ず,0:涓嶆樉绀?', + `remark` varchar(255) DEFAULT NULL COMMENT '备注', + `path` varchar(200) DEFAULT NULL COMMENT '路由地址', + `component` varchar(200) DEFAULT NULL COMMENT '组件路径', + `router_query` varchar(200) DEFAULT NULL COMMENT '路由参数', + `is_frame` int DEFAULT '0' COMMENT '是否为外链(0否 1是)', + `visible` int DEFAULT '1' COMMENT '菜单是否显示;0:隐藏 1:显示', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + `perms` varchar(255) DEFAULT NULL, + PRIMARY KEY (`menu_id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=2105 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='菜单表'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `sys_operation_log` +-- + +DROP TABLE IF EXISTS `sys_operation_log`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `sys_operation_log` ( + `oper_id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `title` varchar(30) NOT NULL COMMENT '模块标题', + `business_type` int NOT NULL DEFAULT '0' COMMENT '业务类型(0其它 1新增 2修改 3删除)', + `method` varchar(100) DEFAULT NULL COMMENT '方法名称', + `request_method` varchar(10) DEFAULT NULL COMMENT '请求方式', + `operator_type` int DEFAULT '0' COMMENT '操作类别(0其它 1后台用户 2手机端用户)', + `oper_name` varchar(50) DEFAULT NULL COMMENT '操作人员', + `oper_url` varchar(255) DEFAULT '0' COMMENT '请求URL', + `oper_ip` varchar(128) DEFAULT NULL COMMENT '主机地址', + `oper_location` varchar(255) DEFAULT NULL COMMENT '操作地点', + `oper_param` varchar(2000) DEFAULT NULL COMMENT '请求参数', + `json_result` varchar(2000) DEFAULT NULL COMMENT '返回参数', + `status` int DEFAULT '0' COMMENT '操作状态(0正常 1异常)', + `error_msg` varchar(2000) DEFAULT NULL COMMENT '错误消息', + `oper_time` datetime DEFAULT NULL COMMENT '操作时间', + `dept_name` varchar(50) DEFAULT NULL COMMENT '部门名称', + `dept_id` bigint DEFAULT NULL COMMENT '部门id', + `tenant_id` varchar(32) DEFAULT NULL COMMENT '租户ID', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`oper_id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=1332 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='操作日志表'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `sys_role` +-- + +DROP TABLE IF EXISTS `sys_role`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `sys_role` ( + `role_id` bigint NOT NULL AUTO_INCREMENT COMMENT '角色ID', + `role_name` varchar(64) NOT NULL COMMENT '角色名称', + `description` varchar(100) DEFAULT NULL COMMENT '角色描述', + `role_key` varchar(100) DEFAULT NULL COMMENT '角色权限字符串', + `data_scope` tinyint DEFAULT '1' COMMENT '数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)', + `menu_check_strictly` tinyint(1) DEFAULT '1' COMMENT '菜单树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示)', + `dept_check_strictly` tinyint(1) DEFAULT '1' COMMENT '部门树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示)', + `status` tinyint unsigned NOT NULL DEFAULT '0' COMMENT '状态;0:正常;1:禁用', + `tenant_id` varchar(32) DEFAULT NULL COMMENT '租户ID', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`role_id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=146 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='角色表'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `sys_role_dept` +-- + +DROP TABLE IF EXISTS `sys_role_dept`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `sys_role_dept` ( + `role_dept_id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `dept_id` bigint NOT NULL COMMENT '部门ID', + `role_id` bigint NOT NULL COMMENT '角色ID', + `tenant_id` varchar(32) DEFAULT NULL COMMENT '租户ID', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`role_dept_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='角色部门关联表'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `sys_role_menu` +-- + +DROP TABLE IF EXISTS `sys_role_menu`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `sys_role_menu` ( + `role_menu_id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `menu_id` bigint NOT NULL COMMENT '菜单ID', + `role_id` bigint NOT NULL COMMENT '角色ID', + `tenant_id` varchar(32) DEFAULT NULL COMMENT '租户id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`role_menu_id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=5237 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='菜单角色关联表'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `sys_tenant` +-- + +DROP TABLE IF EXISTS `sys_tenant`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `sys_tenant` ( + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `tenant_type` tinyint unsigned NOT NULL DEFAULT '0' COMMENT '租户类型;0:公司;1:部门;2:个人;3:其他', + `tenant_status` tinyint unsigned NOT NULL DEFAULT '0' COMMENT '用户状态;0:正常,1:停用', + `tenant_code` varchar(32) DEFAULT NULL COMMENT '编码', + `tenant_name` varchar(64) DEFAULT NULL COMMENT '名称', + `tenant_logo` varchar(128) DEFAULT NULL COMMENT 'logo图', + `sort_order` int DEFAULT NULL COMMENT '显示顺序', + `home_url` varchar(64) DEFAULT NULL COMMENT '官方地址', + `phone` varchar(20) DEFAULT NULL COMMENT '电话', + `fax` varchar(15) DEFAULT NULL COMMENT '传真', + `email` varchar(20) DEFAULT NULL COMMENT '邮箱', + `address` varchar(128) DEFAULT NULL COMMENT '地址', + `user_name` varchar(20) DEFAULT NULL COMMENT '管理员账号', + `user_pwd` varchar(64) DEFAULT NULL COMMENT '管理员密码', + `package_id` varchar(32) DEFAULT NULL COMMENT '套餐id', + `tenant_time` datetime DEFAULT NULL COMMENT '租赁到期时间', + `remarks` varchar(255) DEFAULT NULL COMMENT '备注', + `tenant_key` varchar(255) DEFAULT NULL COMMENT '租户权限标识', + `app_id` varchar(2000) DEFAULT NULL COMMENT '微信公众号ID', + `secret` varchar(2000) DEFAULT NULL COMMENT '微信公众号的app secret', + `mch_id` varchar(2000) DEFAULT NULL COMMENT '商户ID', + `mch_key` varchar(2000) DEFAULT NULL COMMENT '商户秘钥', + `certificate_path` varchar(2000) DEFAULT NULL COMMENT '商户秘钥', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + `czcgtz_template_id` varchar(100) DEFAULT NULL COMMENT '充值成功通知', + `xdcgtz_template_id` varchar(100) DEFAULT NULL COMMENT '下单成功通知', + `sdxddtz_template_id` varchar(100) DEFAULT NULL COMMENT '收到新订单通知', + `rzsqshtx_template_id` varchar(100) DEFAULT NULL COMMENT '认证申请审核提醒', + `xdtx_template_id` varchar(100) DEFAULT NULL, + `rzsq_admin_template_id` varchar(100) DEFAULT NULL, + `dingdantousuchuli_template_id` varchar(100) DEFAULT NULL COMMENT '订单投诉处理id', + `jiedanchenggongtongzhi_template_id` varchar(100) DEFAULT NULL COMMENT '接单成功通知id', + `dingdanzhifuchenggongtongzhi_template_id` varchar(100) DEFAULT NULL COMMENT '订单支付成功通知', + `quxiaodingdantongzhi_template_id` varchar(100) DEFAULT NULL COMMENT '取消订单通知', + `dingdanwanchengtongzhi_template_id` varchar(100) DEFAULT NULL COMMENT '订单完成通知', + `chongzhichenggong_template_id` varchar(100) DEFAULT NULL COMMENT '充值成功通知', + `xindingdanshoulitongzhi_template_id` varchar(100) DEFAULT NULL COMMENT '新订单受理通知', + `profitsharing_rate` int DEFAULT '0' COMMENT '分账比例,数字,最小0,最大30', + PRIMARY KEY (`tenant_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='租户表'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `sys_tenant_package` +-- + +DROP TABLE IF EXISTS `sys_tenant_package`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `sys_tenant_package` ( + `package_id` varchar(32) NOT NULL COMMENT '套餐id', + `package_name` varchar(64) DEFAULT NULL COMMENT '名称', + `menu_ids` varchar(1000) DEFAULT NULL COMMENT '关联菜单id', + `status` tinyint unsigned NOT NULL DEFAULT '0' COMMENT '状态;0:正常,1:停用', + `remarks` varchar(255) DEFAULT NULL COMMENT '备注', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`package_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='租户套餐表'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `sys_tenant_recharge_info` +-- + +DROP TABLE IF EXISTS `sys_tenant_recharge_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `sys_tenant_recharge_info` ( + `id` varchar(32) NOT NULL COMMENT 'UUID', + `tenant_id` varchar(32) NOT NULL COMMENT '租户ID', + `recharge_amount` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '充值金额', + `recharge_user` varchar(255) DEFAULT NULL COMMENT '充值用户', + `recharge_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '充值时间', + `pay_method` varchar(255) DEFAULT NULL COMMENT '支付方式,1:微信支付,2:支付宝支付;3:银行卡支付', + `pay_account` varchar(255) DEFAULT NULL COMMENT '支付账号', + `remark` varchar(255) DEFAULT NULL COMMENT '备注', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`tenant_id`,`id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='租户充值信息'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `sys_user` +-- + +DROP TABLE IF EXISTS `sys_user`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `sys_user` ( + `user_id` varchar(32) NOT NULL COMMENT '用户ID', + `user_type` tinyint unsigned NOT NULL DEFAULT '1' COMMENT '用户类型;1:admin;2:会员', + `sex` tinyint NOT NULL DEFAULT '0' COMMENT '性别;0:保密,1:男,2:女', + `birthday` datetime DEFAULT NULL COMMENT '生日', + `last_login_time` datetime DEFAULT NULL COMMENT '最后登录时间', + `last_login_ip` varchar(15) NOT NULL DEFAULT '' COMMENT '最后登录ip', + `user_code` varchar(60) DEFAULT NULL COMMENT '用户名', + `pass_word` varchar(64) NOT NULL DEFAULT '' COMMENT '登录密码;cmf_password加密', + `real_name` varchar(20) DEFAULT NULL COMMENT '姓名', + `user_nickname` varchar(50) DEFAULT NULL COMMENT '用户昵称', + `user_email` varchar(100) NOT NULL DEFAULT '' COMMENT '用户登录邮箱', + `status` tinyint DEFAULT '0' COMMENT '状态 0:正常;1:停用 ', + `user_url` varchar(100) NOT NULL DEFAULT '' COMMENT '用户个人网址', + `avatar` varchar(255) NOT NULL DEFAULT '' COMMENT '用户头像', + `mobile` varchar(20) DEFAULT NULL, + `dept_id` bigint DEFAULT NULL COMMENT '部门id', + `add_time` datetime DEFAULT NULL COMMENT '新增时间', + `tenant_id` varchar(32) DEFAULT NULL COMMENT '租户ID', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + `super_admin` tinyint(1) DEFAULT '0', + `clerk_id` varchar(100) DEFAULT NULL, + PRIMARY KEY (`user_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='用户表'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `sys_user_role` +-- + +DROP TABLE IF EXISTS `sys_user_role`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `sys_user_role` ( + `user_role_id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `user_id` varchar(32) NOT NULL COMMENT '用户ID', + `role_id` bigint NOT NULL COMMENT '角色ID', + `tenant_id` varchar(32) DEFAULT NULL COMMENT '租户id', + `updated_time` datetime DEFAULT NULL COMMENT '修改时间', + `updated_by` varchar(32) DEFAULT NULL COMMENT '修改人的id', + `created_time` datetime DEFAULT NULL COMMENT '创建时间', + `created_by` varchar(32) DEFAULT NULL COMMENT '创建人的id', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除 1已删除 0未删除', + `version` int NOT NULL DEFAULT '1' COMMENT '数据版本', + PRIMARY KEY (`user_role_id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=100 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='用户角色关联表'; +/*!40101 SET character_set_client = @saved_cs_client */; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2025-04-24 23:27:24 + + +--- File: play-admin/src/main/resources/ip2region/ip2region.db --- +[Binary file: content not included] + +--- File: play-admin/src/main/resources/logback-spring.xml --- + + + logback + + + + + + + + + + + + + + + + + info + + + ${CONSOLE_LOG_PATTERN} + + UTF-8 + + + + + + ${log.path}/detail.log + + ${log.path}/detail/detail-%d{yyyy-MM-dd}.%i.log + + 100MB + + 7 + + + %d{MM/dd/yyyy HH:mm:ss} %-5level [%thread]%logger{16} - %msg%n + UTF-8 + + + + + + + ${log.path}/error.log + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n + UTF-8 + + + + ${log.path}/error/error-%d{yyyy-MM-dd}.%i.log + + 100MB + + + 10 + + + + ERROR + ACCEPT + DENY + + + + + + + + + + + + + + + + + + + + + + + + + +--- File: play-admin/src/main/resources/mapper/commodity/CommodityInfoMapper.xml --- + + + + + +--- File: play-admin/src/main/resources/mapper/coupon/CouponInfoMapper.xml --- + + + + + +--- File: play-admin/src/main/resources/mapper/platform/SysTenantMapper.xml --- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select tenant_id, + tenant_type, + tenant_status, + tenant_code, + tenant_name, + tenant_logo, + sort_order, + home_url, + phone, + fax, + email, + address, + user_name, + user_pwd, + package_id, + tenant_time, + remarks, + updated_time, + updated_by, + created_time, + created_by, + deleted, + version + from sys_tenant + + + + + + + + delete from sys_tenant where tenant_id in + + #{id} + + + + +--- File: play-admin/src/main/resources/mapper/platform/SysTenantPackageMapper.xml --- + + + + + + + + + + + + + + + + + + + select package_id, + package_name, + menu_ids, + status, + remarks, + updated_time, + updated_by, + created_time, + created_by, + deleted + from sys_tenant_package + + + + + + + + + +--- File: play-admin/src/main/resources/mapper/play/PlayResourcesInfoMapper.xml --- + + + + + +--- File: play-admin/src/main/resources/mapper/play/PlayUserInfoMapper.xml --- + + + + + +--- File: play-admin/src/main/resources/mapper/system/SysDeptMapper.xml --- + + + + + + + + + + + + + + + + + + + + + + + + + select d.dept_id, + d.parent_id, + d.ancestors, + d.dept_name, + d.sort, + d.leader, + d.phone, + d.email, + d.status, + d.dept_level, + d.created_by, + d.created_time + from sys_dept d + + + + + + + + delete from sys_dept where tenant_id in + + #{id} + + + + + + + +--- File: play-admin/src/main/resources/mapper/system/SysDictDataMapper.xml --- + + + + + + + + + + + + + + + + + + + + + + + select dict_data_id, + dict_type, + dict_label, + dict_value, + sort, + is_default, + list_class, + status, + remark, + updated_time, + updated_by, + created_time, + created_by, + deleted + from sys_dict_data + + + + + + + + + +--- File: play-admin/src/main/resources/mapper/system/SysDictMapper.xml --- + + + + + + + + + + + + + + + + + + + select dict_id, + dict_type, + dict_name, + status, + remark, + updated_time, + updated_by, + created_time, + created_by, + deleted + from sys_dict + + + + + + + +--- File: play-admin/src/main/resources/mapper/system/SysLoginLogMapper.xml --- + + + + + + + + + + + + + + + + + + + + + + + select login_id, + user_code, + ipaddr, + login_location, + browser, + os, + msg, + status, + login_time, + updated_time, + updated_by, + created_time, + created_by, + deleted + from sys_login_log + + + + + + + + truncate table sys_login_log + + + +--- File: play-admin/src/main/resources/mapper/system/SysMenuMapper.xml --- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +--- File: play-admin/src/main/resources/mapper/system/SysOperationLogMapper.xml --- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select oper_id, + title, + business_type, + method, + request_method, + operator_type, + oper_name, + oper_url, + oper_ip, + oper_location, + oper_param, + json_result, + status, + error_msg, + oper_time, + dept_name, + dept_id, + updated_time, + updated_by, + created_time, + created_by, + deleted + from sys_operation_log + + + + + + + +--- File: play-admin/src/main/resources/mapper/system/SysRoleDeptMapper.xml --- + + + + + + + + + + + + + + + + + + + delete from sys_role_dept where tenant_id in + + #{id} + + + + + delete from sys_role_dept where role_id = #{roleId} + + + + insert into sys_role_dept(role_id, dept_id) values + + (#{item.roleId},#{item.deptId}) + + + + + delete from sys_role_dept where role_id in + + #{roleId} + + + + + +--- File: play-admin/src/main/resources/mapper/system/SysRoleMapper.xml --- + + + + + + + + + + + + + + + + + + + + + + + select distinct r.role_id, + r.role_name, + r.role_key, + r.data_scope, + r.menu_check_strictly, + r.dept_check_strictly, + r.status, + r.created_time, + r.description + from sys_role r + left join sys_user_role ur on ur.role_id = r.role_id and ur.deleted = 0 + left join sys_user u on u.user_id = ur.user_id and u.deleted = 0 + + + + + + + + + + + + + + + + delete from sys_role where tenant_id in + + #{id} + + + + + + + +--- File: play-admin/src/main/resources/mapper/system/SysRoleMenuMapper.xml --- + + + + + + + + + + + + + + + + + + + delete from sys_role_menu where tenant_id = #{tenantId} + + + + delete from sys_role_menu where tenant_id in + + #{id} + + + + + delete from sys_role_menu where role_id in + + #{roleId} + + + + + +--- File: play-admin/src/main/resources/mapper/system/SysUserMapper.xml --- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select u.user_id, + u.real_name, + u.user_nickname, + u.user_email, + u.avatar, + u.user_code, + u.pass_word, + u.sex, + u.mobile, + u.status, + u.created_time, + u.dept_id, + u.tenant_id, + u.super_admin, + d.dept_name, + r.role_id, + r.role_name, + r.role_key, + r.data_scope, + r.status as role_status + from sys_user u + left join sys_user_role ur on u.user_id = ur.user_id and ur.deleted = 0 + left join sys_role r on r.role_id = ur.role_id and r.deleted = 0 + left join sys_dept d on u.dept_id = d.dept_id and d.deleted = 0 + + + + + + + + + + + + + + delete from sys_user where tenant_id in + + #{id} + + + + + + + + + +--- File: play-admin/src/main/resources/mapper/system/SysUserRoleMapper.xml --- + + + + + + + + + + + + + + + + + + + delete from sys_user_role where tenant_id in + + #{id} + + + + + delete from sys_user_role where user_id=#{userId} and role_id=#{roleId} + + + + delete from sys_user_role where role_id=#{roleId} and user_id in + + #{userId} + + + + + +--- File: play-admin/src/main/resources/mapper/weichat/WxMsgMapper.xml --- + + + + + + + + + +--- File: play-admin/src/main/resources/oss.properties --- +aliyun.endpoint=oss-cn-hangzhou.aliyuncs.com +aliyun.accessKeyId=LTAI5t9ojt6uovFZokYZfJx5 +aliyun.accessKeySecret=xfCyNM5BQlAkoaa5NbcpoeipmCKZgf +aliyun.bucketName=live-cloud-cvoon + +--- File: play-admin/src/main/resources/play.properties --- +#微信公众号或者小程序等的appid +wx.play.appId:xxxxxxxxxxxxx +#微信支付商户号 +wx.play.mchId:xxxxxxxxxxxxx +# 证书 +wx.play.apiclient_key.pem:xxxxxxxxx +# 证书 +wx.play.apiclient_cert.pem:xxxxxxxxx +# apiV3key +wx.play.apiV3key:xxxxxxxxxxxxxxxxxx +#支付回调通知地址 +wx.play.returnUrl:http://xxxxxxxxxx/wxPay/callBack +# 退款回调地址 +wx.play.refundUrl:http://xxxxxxxxxx/wxPay/refund + + +--- File: play-admin/src/main/resources/spy.properties --- +#3.2.1以上使用modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory +# 自定义日志打印 +logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger +#日志输出到控制台 +appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger +# 使用日志系统记录 sql +#appender=com.p6spy.engine.spy.appender.Slf4JLogger +# 设置 p6spy driver 代理 +deregisterdrivers=true +# 取消JDBC URL前缀 +useprefix=true +# 配置记录 Log 例外,可去掉的结果集error,info,batch,debug,statement,commit,rollback,result,resultset. +excludecategories=info,debug,result,commit,resultset +# 日期格式 +dateformat=yyyy-MM-dd HH:mm:ss +# 实际驱动可多个 +#driverlist=org.h2.Driver +# 是否开启慢SQL记录 +outagedetection=true +# 慢SQL记录标准 2 秒 +outagedetectioninterval=2 + +--- File: play-common/pom.xml --- + + + 4.0.0 + + com.starry + play-with + 1.0 + + + play-common + + + 11 + 11 + UTF-8 + + + + + + org.springframework.boot + spring-boot-starter-web + + + + + org.springframework.boot + spring-boot-starter-security + + + + + org.projectlombok + lombok + 1.18.30 + provided + + + + org.projectlombok + lombok-mapstruct-binding + 0.2.0 + + + + com.baomidou + mybatis-plus-boot-starter + + + com.github.yulichang + mybatis-plus-join-boot-starter + + + javax.persistence + javax.persistence-api + + + + com.alibaba + druid-spring-boot-starter + + + + com.github.xiaoymin + knife4j-spring-boot-starter + + + + org.apache.commons + commons-lang3 + + + + commons-io + commons-io + + + + com.github.oshi + oshi-core + + + + cn.hutool + hutool-all + + + + javax.validation + validation-api + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + com.alibaba.fastjson2 + fastjson2 + + + com.github.gavlyukovskiy + p6spy-spring-boot-starter + + + + + com.google.code.gson + gson + + + + + org.lionsoul + ip2region + + + + com.alibaba + transmittable-thread-local + + + + + +--- File: play-common/src/main/java/com/starry/common/annotation/DataScope.java --- +package com.starry.common.annotation; + +import java.lang.annotation.*; + +/** + * 数据权限过滤注解 + * + * @author admin + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface DataScope { + /** + * 部门表的别名 + */ + String deptAlias() default ""; + + /** + * 用户表的别名 + */ + String userAlias() default ""; + + /** + * 权限字符(用于多个角色匹配符合要求的权限)默认根据权限注解@ss获取,多个权限用逗号分隔开来 + */ + String permission() default ""; +} + + +--- File: play-common/src/main/java/com/starry/common/annotation/EnumValue.java --- +package com.starry.common.annotation; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import javax.validation.Constraint; +import javax.validation.Payload; + +/** + * 枚举参数校验注解 + * + * @author admin + */ +@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER}) +@Retention(RUNTIME) +@Documented +@Constraint(validatedBy = {EnumValueValidator.class}) +public @interface EnumValue { + + // 默认错误消息 + String message() default "必须为指定值"; + + String[] strValues() default {}; + + int[] intValues() default {}; + + // 分组 + Class[] groups() default {}; + + // 负载 + Class[] payload() default {}; + + // 指定多个时使用 + @Target({FIELD, METHOD, PARAMETER, ANNOTATION_TYPE}) + @Retention(RUNTIME) + @Documented + @interface List { + EnumValue[] value(); + } +} + + +--- File: play-common/src/main/java/com/starry/common/annotation/EnumValueValidator.java --- +package com.starry.common.annotation; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +/** + * 枚举校验注解处理类 + */ +public class EnumValueValidator implements ConstraintValidator { + + private String[] strValues; + private int[] intValues; + + @Override + public void initialize(EnumValue constraintAnnotation) { + strValues = constraintAnnotation.strValues(); + intValues = constraintAnnotation.intValues(); + } + + @Override + public boolean isValid(Object value, ConstraintValidatorContext context) { + if (value instanceof String) { + for (String s : strValues) { + if (s.equals(value)) { + return true; + } + } + } else if (value instanceof Integer) { + for (int s : intValues) { + if (s == (Integer) value) { + return true; + } + } + } + return false; + } +} + + +--- File: play-common/src/main/java/com/starry/common/annotation/Log.java --- +package com.starry.common.annotation; + +import com.starry.common.enums.BusinessType; +import java.lang.annotation.*; + +/** + * @author admin 自定义操作日志记录注解 + * @since 2022/7/22 + */ +@Target({ElementType.PARAMETER, ElementType.METHOD}) // 注解放置的目标位置,PARAMETER: 可用在参数上 METHOD:可用在方法级别上 +@Retention(RetentionPolicy.RUNTIME) // 指明修饰的注解的生存周期 RUNTIME:运行级别保留 +@Documented +public @interface Log { + + /** + * 模块 + */ + String title() default ""; + + /** + * 功能 + */ + BusinessType businessType() default BusinessType.OTHER; + + /** + * 是否保存请求的参数 + */ + boolean isSaveRequestData() default true; + + /** + * 是否保存响应的参数 + */ + boolean isSaveResponseData() default true; +} + + +--- File: play-common/src/main/java/com/starry/common/config/FastJson2JsonRedisSerializer.java --- +package com.starry.common.config; + +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONReader; +import com.alibaba.fastjson2.JSONWriter; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +/** + * Redis使用FastJson序列化 + * + * @author ruoyi + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8; + + private final Class clazz; + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + @Override + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, JSONWriter.Feature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + @Override + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return JSON.parseObject(str, clazz, JSONReader.Feature.SupportAutoType); + } +} + + +--- File: play-common/src/main/java/com/starry/common/config/RedisConfig.java --- +package com.starry.common.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @author admin redis 配置 + * @since 2022/10/18 + */ + +@Configuration +public class RedisConfig { + + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate<>(); + template.setConnectionFactory(connectionFactory); + FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer<>(Object.class); + // 使用StringRedisSerializer来序列化和反序列化redis的key值 + template.setKeySerializer(new StringRedisSerializer()); + template.setValueSerializer(serializer); + // Hash的key也采用StringRedisSerializer的序列化方式 + template.setHashKeySerializer(new StringRedisSerializer()); + template.setHashValueSerializer(serializer); + + template.afterPropertiesSet(); + return template; + } +} + + +--- File: play-common/src/main/java/com/starry/common/config/Swagger2Config.java --- +package com.starry.common.config; + +import java.util.ArrayList; +import java.util.List; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiKey; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc; + +/** + * @author admin swagger配置 + * @since 2021/9/1 + */ +@Configuration +@EnableSwagger2WebMvc +public class Swagger2Config { + + @Bean(value = "defaultApi2") + public Docket defaultApi2() { + Docket docket = new Docket(DocumentationType.SWAGGER_2) + .apiInfo(new ApiInfoBuilder().title("接口文档").description("# 接口文档") + .termsOfServiceUrl("http://www.xx.com/").contact("277769738@qq.com").version("1.0").build()) + // 分组名称 + .groupName("2.X版本").select() + // 这里指定Controller扫描包路径 + .apis(RequestHandlerSelectors.basePackage("com.starry.admin.modules")).paths(PathSelectors.any()) + .build(); + return docket; + } + + private List securitySchemes() { + // 设置请求头信息 + List result = new ArrayList<>(); + ApiKey apiKey = new ApiKey("Authorization", "Authorization", "header"); + result.add(apiKey); + return result; + } +} + + +--- File: play-common/src/main/java/com/starry/common/config/ThreadPoolConfig.java --- +package com.starry.common.config; + +import com.starry.common.utils.ThreadsUtils; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadPoolExecutor; +import org.apache.commons.lang3.concurrent.BasicThreadFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +/** + * @author admin 线程池配置 + * @since 2022/7/25 + */ +@Configuration +public class ThreadPoolConfig { + + /** + * 核心线程池大小 + **/ + private final int corePoolSize = 50; + /** + * 最大可创建的线程数 + **/ + private final int maxPoolSize = 200; + /** + * 队列最大长度 + **/ + private final int queueCapacity = 1000; + /** + * 线程池维护线程所允许的空闲时间 + **/ + private final int keepAliveSeconds = 300; + + @Bean(name = "threadPoolTaskExecutor") + public ThreadPoolTaskExecutor threadPoolTaskExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setMaxPoolSize(maxPoolSize); + executor.setCorePoolSize(corePoolSize); + executor.setQueueCapacity(queueCapacity); + executor.setKeepAliveSeconds(keepAliveSeconds); + // 线程池对拒绝任务(无线程可用)的处理策略 + executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); + return executor; + } + + /** + * 执行周期性或定时任务 + */ + @Bean(name = "scheduledExecutorService") + protected ScheduledExecutorService scheduledExecutorService() { + return new ScheduledThreadPoolExecutor(corePoolSize, + new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(), + new ThreadPoolExecutor.CallerRunsPolicy()) { + @Override + protected void afterExecute(Runnable r, Throwable t) { + super.afterExecute(r, t); + ThreadsUtils.printException(r, t); + } + }; + } + +} + + +--- File: play-common/src/main/java/com/starry/common/config/typehandler/ArrayLongTypeHandler.java --- +package com.starry.common.config.typehandler; + +import cn.hutool.json.JSONUtil; +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import org.apache.ibatis.type.BaseTypeHandler; +import org.apache.ibatis.type.JdbcType; +import org.apache.ibatis.type.MappedJdbcTypes; +import org.apache.ibatis.type.MappedTypes; + +/** + * 存储到数据库, 将LONG数组转换成字符串; 从数据库获取数据, 将字符串转为LONG数组. + */ +@MappedTypes({Long[].class}) +@MappedJdbcTypes({JdbcType.VARCHAR}) +public class ArrayLongTypeHandler extends BaseTypeHandler { + + private static final Long[] l = new Long[]{}; + + @Override + public void setNonNullParameter(PreparedStatement ps, int i, Long[] parameter, JdbcType jdbcType) + throws SQLException { + ps.setString(i, JSONUtil.toJsonStr(parameter)); + } + + @Override + public Long[] getNullableResult(ResultSet rs, String columnName) throws SQLException { + return JSONUtil.parseArray(rs.getString(columnName)).toArray(l); + } + + @Override + public Long[] getNullableResult(ResultSet rs, int columnIndex) throws SQLException { + return JSONUtil.parseArray(rs.getString(columnIndex)).toArray(l); + } + + @Override + public Long[] getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { + return JSONUtil.parseArray(cs.getString(columnIndex)).toArray(l); + } + +} + + +--- File: play-common/src/main/java/com/starry/common/config/typehandler/ArrayStringTypeHandler.java --- +package com.starry.common.config.typehandler; + +import cn.hutool.json.JSONUtil; +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import org.apache.ibatis.type.BaseTypeHandler; +import org.apache.ibatis.type.JdbcType; +import org.apache.ibatis.type.MappedJdbcTypes; +import org.apache.ibatis.type.MappedTypes; + +/** + * 存储到数据库, 将String数组转换成字符串; 从数据库获取数据, 将字符串转为LONG数组. + */ +@MappedTypes({String[].class}) +@MappedJdbcTypes({JdbcType.VARCHAR}) +public class ArrayStringTypeHandler extends BaseTypeHandler { + + private static final String[] l = new String[]{}; + + @Override + public void setNonNullParameter(PreparedStatement ps, int i, String[] parameter, JdbcType jdbcType) + throws SQLException { + ps.setString(i, JSONUtil.toJsonStr(parameter)); + } + + @Override + public String[] getNullableResult(ResultSet rs, String columnName) throws SQLException { + return JSONUtil.parseArray(rs.getString(columnName)).toArray(l); + } + + @Override + public String[] getNullableResult(ResultSet rs, int columnIndex) throws SQLException { + return JSONUtil.parseArray(rs.getString(columnIndex)).toArray(l); + } + + @Override + public String[] getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { + return JSONUtil.parseArray(cs.getString(columnIndex)).toArray(l); + } + +} + + +--- File: play-common/src/main/java/com/starry/common/config/typehandler/JsonTypeHandler.java --- +package com.starry.common.config.typehandler; + +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import org.apache.ibatis.type.BaseTypeHandler; +import org.apache.ibatis.type.JdbcType; +import org.apache.ibatis.type.MappedJdbcTypes; +import org.apache.ibatis.type.MappedTypes; + +/** + * 存储到数据库, 将JSON对象转换成字符串; 从数据库获取数据, 将字符串转为JSON对象. + */ +@MappedTypes({JSONObject.class}) +@MappedJdbcTypes({JdbcType.VARCHAR}) +public class JsonTypeHandler extends BaseTypeHandler { + + @Override + public void setNonNullParameter(PreparedStatement ps, int i, JSONObject parameter, JdbcType jdbcType) + throws SQLException { + + ps.setString(i, JSONUtil.toJsonStr(parameter)); + } + + @Override + public JSONObject getNullableResult(ResultSet rs, String columnName) throws SQLException { + + return JSONUtil.parseObj(rs.getString(columnName)).toBean(JSONObject.class); + } + + @Override + public JSONObject getNullableResult(ResultSet rs, int columnIndex) throws SQLException { + + return JSONUtil.parseObj(rs.getString(columnIndex)).toBean(JSONObject.class); + } + + @Override + public JSONObject getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { + + return JSONUtil.parseObj(cs.getString(columnIndex)).toBean(JSONObject.class); + } + +} + + +--- File: play-common/src/main/java/com/starry/common/constant/CacheConstants.java --- +package com.starry.common.constant; + +/** + * @author 缓存常量 + * @since 2022/8/26 + */ +public class CacheConstants { + + /** + * 字典管理 cache key + */ + public static final String SYS_DICT_KEY = "sys_dict:"; + + /** + * 登录用户 redis key + */ + public static final String LOGIN_TOKEN_KEY = "login_tokens:"; + + /** + * 验证码 redis key + */ + public static final String CAPTCHA_CODE_KEY = "captcha_codes:"; +} + + +--- File: play-common/src/main/java/com/starry/common/constant/Constants.java --- +package com.starry.common.constant; + +/** + * @author admin 通用常量信息 + */ +public class Constants { + + /** + * UTF-8 字符集 + */ + public static final String UTF8 = "UTF-8"; + + /** + * GBK 字符集 + */ + public static final String GBK = "GBK"; + + /** + * http请求 + */ + public static final String HTTP = "http://"; + + /** + * https请求 + */ + public static final String HTTPS = "https://"; + + /** + * 通用成功标识 + */ + public static final String SUCCESS = "0"; + + /** + * 通用失败标识 + */ + public static final String FAIL = "1"; + + /** + * 登录成功 + */ + public static final String LOGIN_SUCCESS = "Success"; + + /** + * 注销 + */ + public static final String LOGOUT = "Logout"; + + /** + * 登录失败 + */ + public static final String LOGIN_FAIL = "Error"; + + /** + * 令牌前缀 + */ + public static final String TOKEN_PREFIX = "Bearer "; + + public static final String CLERK_USER_LOGIN_TOKEN = "clerkusertoken"; + public static final String CUSTOM_USER_LOGIN_TOKEN = "customusertoken"; + + /** + * 令牌前缀 + */ + public static final String LOGIN_USER_KEY = "login_user_key"; + public static final String LOGIN_USER_KEY_MINI = "login_user_key_mini"; + public static final String LOGIN_USER_KEY_COSER = "login_user_key_coser"; + +} + + +--- File: play-common/src/main/java/com/starry/common/constant/HttpStatus.java --- +package com.starry.common.constant; + +/** + * 返回状态码 + * + * @author ruoyi + */ +@SuppressWarnings("") +public class HttpStatus { + /** + * 操作成功 + */ + public static final int SUCCESS = 200; + + /** + * 对象创建成功 + */ + public static final int CREATED = 201; + + /** + * 请求已经被接受 + */ + public static final int ACCEPTED = 202; + + /** + * 操作已经执行成功,但是没有返回数据 + */ + public static final int NO_CONTENT = 204; + + /** + * 资源已被移除 + */ + public static final int MOVED_PERM = 301; + + /** + * 重定向 + */ + public static final int SEE_OTHER = 303; + + /** + * 资源没有被修改 + */ + public static final int NOT_MODIFIED = 304; + + /** + * 参数列表错误(缺少,格式不匹配) + */ + public static final int BAD_REQUEST = 400; + + /** + * 未授权 + */ + public static final int UNAUTHORIZED = 401; + + /** + * 访问受限,授权过期 + */ + public static final int FORBIDDEN = 403; + + /** + * 资源,服务未找到 + */ + public static final int NOT_FOUND = 404; + + /** + * 不允许的http方法 + */ + public static final int BAD_METHOD = 405; + + /** + * 资源冲突,或者资源被锁 + */ + public static final int CONFLICT = 409; + + /** + * 不支持的数据,媒体类型 + */ + public static final int UNSUPPORTED_TYPE = 415; + + /** + * 系统内部错误 + */ + public static final int ERROR = 500; + + /** + * 接口未实现 + */ + public static final int NOT_IMPLEMENTED = 501; +} + + +--- File: play-common/src/main/java/com/starry/common/constant/SecurityConstants.java --- +package com.starry.common.constant; + +/** + * @author admin 权限相关常量 + */ +public class SecurityConstants { + /** + * 租户ID字段 + */ + public static final String DETAILS_TENANT_ID = "tenant_id"; + + /** + * 部门ID字段 + */ + public static final String DETAILS_DEPT_ID = "dept_id"; + + /** + * 用户ID字段 + */ + public static final String DETAILS_USER_ID = "user_id"; + + /** + * 用户名字段 + */ + public static final String DETAILS_USERNAME = "username"; + /** + * 用户标识 + */ + public static final String USER_KEY = "user_key"; + /** + * 登录用户 + */ + public static final String LOGIN_USER = "login_user"; + /** + * 角色权限 + */ + public static final String ROLE_PERMISSION = "role_permission"; +} + + +--- File: play-common/src/main/java/com/starry/common/constant/UserConstants.java --- +package com.starry.common.constant; + +/** + * @author 用户常量信息 + * @since 2022/7/4 + */ +public class UserConstants { + + /** + * 校验返回结果码 0:唯一 1:不唯一 + */ + public final static String UNIQUE = "0"; + public final static String NOT_UNIQUE = "1"; + + /** + * 是否菜单外链(否) + */ + public static final String NO_FRAME = "0"; + + /** + * 是否菜单外链(是) + */ + public static final String YES_FRAME = "1"; + + /** + * 菜单类型(目录) + */ + public static final String TYPE_DIR = "0"; + + /** + * 菜单类型(菜单) + */ + public static final String TYPE_MENU = "1"; + + /** + * 菜单类型(按钮) + */ + public static final String TYPE_BUTTON = "2"; + + /** + * Layout组件标识 + */ + public final static String LAYOUT = "Layout"; + + /** + * InnerLink组件标识 + */ + public final static String INNER_LINK = "InnerLink"; + + /** + * ParentView组件标识 + */ + public final static String PARENT_VIEW = "ParentView"; + + /** + * 部门正常状态 + */ + public static final String DEPT_NORMAL = "0"; + + /** + * 部门停用状态 + */ + public static final String DEPT_DISABLE = "1"; + + /** + * 用户名长度限制 + */ + public static final int USERNAME_MIN_LENGTH = 2; + + public static final int USERNAME_MAX_LENGTH = 20; + + /** + * 密码长度限制 + */ + public static final int PASSWORD_MIN_LENGTH = 5; + + public static final int PASSWORD_MAX_LENGTH = 20; +} + + +--- File: play-common/src/main/java/com/starry/common/context/CustomSecurityContextHolder.java --- +package com.starry.common.context; + +import cn.hutool.core.convert.Convert; +import com.alibaba.ttl.TransmittableThreadLocal; +import com.starry.common.constant.SecurityConstants; +import com.starry.common.utils.StringUtils; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author admin 获取当前线程变量中的 租户id 部门id 用户id、用户名称、Token等信息 + * @since 2023/3/6 + */ +public class CustomSecurityContextHolder { + + private static final TransmittableThreadLocal> THREAD_LOCAL = new TransmittableThreadLocal<>(); + + public static void set(String key, Object value) { + Map map = getLocalMap(); + map.put(key, value == null ? StringUtils.EMPTY : value); + } + + public static String get(String key) { + Map map = getLocalMap(); + return Convert.toStr(map.getOrDefault(key, StringUtils.EMPTY)); + } + + public static T get(String key, Class clazz) { + Map map = getLocalMap(); + return StringUtils.cast(map.getOrDefault(key, null)); + } + + public static Map getLocalMap() { + Map map = THREAD_LOCAL.get(); + if (map == null) { + map = new ConcurrentHashMap<>(); + THREAD_LOCAL.set(map); + } + return map; + } + + public static void setLocalMap(Map threadLocalMap) { + THREAD_LOCAL.set(threadLocalMap); + } + + public static String getTenantId() { + return Convert.toStr(get(SecurityConstants.DETAILS_TENANT_ID), "9999"); + } + + public static void setTenantId(String tenantId) { + set(SecurityConstants.DETAILS_TENANT_ID, tenantId); + } + + public static Long getDeptId() { + return Convert.toLong(get(SecurityConstants.DETAILS_DEPT_ID)); + } + + public static String getUserId() { + return Convert.toStr(get(SecurityConstants.DETAILS_USER_ID)); + } + + public static void setDeptId(String deptId) { + set(SecurityConstants.DETAILS_DEPT_ID, deptId); + } + + public static String getPermission() { + return get(SecurityConstants.ROLE_PERMISSION); + } + + public static void setPermission(String permissions) { + set(SecurityConstants.ROLE_PERMISSION, permissions); + } + + public static void remove() { + THREAD_LOCAL.remove(); + } +} + + +--- File: play-common/src/main/java/com/starry/common/controller/CaptchaController.java --- +package com.starry.common.controller; + +import com.starry.common.domain.Captcha; +import com.starry.common.redis.CaptchaService; +import com.starry.common.result.R; +import io.swagger.annotations.ApiOperation; +import javax.annotation.Resource; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author admin 验证码前端控制器 + * @since 2022/7/7 + */ +@RestController +@RequestMapping("/captcha") +public class CaptchaController { + + @Resource + private CaptchaService captchaService; + + @ApiOperation(value = "生成验证码拼图") + @PostMapping("get-captcha") + public R getCaptcha(@RequestBody Captcha captcha) { + return R.ok(captchaService.getCaptcha(captcha)); + } + +} + + +--- File: play-common/src/main/java/com/starry/common/domain/BaseEntity.java --- +package com.starry.common.domain; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import javax.persistence.MappedSuperclass; +import javax.persistence.Transient; +import lombok.Getter; +import lombok.Setter; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * @author admin 基类 + * @since 2022/7/14 + */ +@Getter +@Setter +@MappedSuperclass +public class BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableField(fill = FieldFill.INSERT) + @ApiModelProperty(value = "逻辑删除 1已删除 0未删除") + private Boolean deleted; + + @TableField(fill = FieldFill.INSERT) + @ApiModelProperty(value = "创建人") + private String createdBy; + + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + @ApiModelProperty(value = "创建时间") + private Date createdTime; + + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + @ApiModelProperty(value = "更新时间") + private Date updatedTime; + + @TableField(fill = FieldFill.UPDATE) + @ApiModelProperty(value = "更新人") + private String updatedBy; + + /** + * 搜索值 + */ + @TableField(exist = false) + private String searchValue; + + /** + * 开始日期 + */ + @TableField(exist = false) + private String beginTime; + + /** + * 结束日期 + */ + @TableField(exist = false) + private String endTime; + + /** + * 请求参数 + */ + @Transient + @TableField(exist = false) + private Map params = new HashMap<>(); + +} + + +--- File: play-common/src/main/java/com/starry/common/domain/BasePageEntity.java --- +package com.starry.common.domain; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import java.util.Date; +import lombok.Data; +import lombok.experimental.Accessors; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * @author admin 分页基类 + * @since 2021/9/2 + */ +@Data +@Accessors(chain = true) +public class BasePageEntity implements Serializable { + + @ApiModelProperty(value = "当前页码", example = "1", notes = "默认为1") + private int currentPage = 1; + + @ApiModelProperty(value = "每页记录数", example = "10", notes = "默认为10") + private int pageSize = 10; + + @ApiModelProperty(value = "页码", example = "1", notes = "与currentPage相同,默认为1") + private int pageNum = 1; + + @TableField(fill = FieldFill.INSERT) + @ApiModelProperty(value = "是否已删除", example = "false", hidden = true) + private Boolean deleted = Boolean.FALSE; + + @TableField(fill = FieldFill.INSERT) + @ApiModelProperty(value = "创建人", hidden = true) + private String createdBy; + + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(fill = FieldFill.INSERT) + @ApiModelProperty(value = "创建时间", hidden = true) + private Date createdTime; + + @TableField(fill = FieldFill.UPDATE) + @ApiModelProperty(value = "更新时间", hidden = true) + private Date updatedTime; + + @TableField(fill = FieldFill.UPDATE) + @ApiModelProperty(value = "更新人", hidden = true) + private String updatedBy; + + /** + * 开始日期 + */ + @TableField(exist = false) + @ApiModelProperty(value = "开始日期", example = "2024-01-01 00:00:00", notes = "格式:yyyy-MM-dd HH:mm:ss") + private String beginTime; + + /** + * 结束日期 + */ + @TableField(exist = false) + @ApiModelProperty(value = "结束日期", example = "2024-12-31 23:59:59", notes = "格式:yyyy-MM-dd HH:mm:ss") + private String endTime; + +} + + +--- File: play-common/src/main/java/com/starry/common/domain/Captcha.java --- +package com.starry.common.domain; + +import lombok.Data; + +/** + * @author admin 验证码拼图类 + */ +@Data +public class Captcha { + + /** + * 随机字符串 + **/ + private String nonceStr; + /** + * 验证值 + **/ + private String value; + /** + * 生成的画布的base64 + **/ + private String canvasSrc; + /** + * 画布宽度 + **/ + private Integer canvasWidth; + /** + * 画布高度 + **/ + private Integer canvasHeight; + /** + * 生成的阻塞块的base64 + **/ + private String blockSrc; + /** + * 阻塞块宽度 + **/ + private Integer blockWidth; + /** + * 阻塞块高度 + **/ + private Integer blockHeight; + /** + * 阻塞块凸凹半径 + **/ + private Integer blockRadius; + /** + * 阻塞块的横轴坐标 + **/ + private Integer blockX; + /** + * 阻塞块的纵轴坐标 + **/ + private Integer blockY; + /** + * 图片获取位置 + **/ + private Integer place; +} + + +--- File: play-common/src/main/java/com/starry/common/enums/BusinessType.java --- +package com.starry.common.enums; + +/** + * @author admin 业务操作类型 + * @since 2022/7/22 + */ +public enum BusinessType { + /** + * 其它 + */ + OTHER, + + /** + * 新增 + */ + INSERT, + + /** + * 修改 + */ + UPDATE, + + /** + * 删除 + */ + DELETE, + /** + * 导出 + */ + EXPORT, + + /** + * 导入 + */ + IMPORT, + /** + * 生成代码 + */ + GENCODE, + /** + * 清空数据 + */ + CLEAN, + /** + * 强退 + */ + FORCE, + /** + * 授权 + */ + GRANT, +} + + +--- File: play-common/src/main/java/com/starry/common/filter/RepeatableFilter.java --- +package com.starry.common.filter; + +import com.starry.common.utils.StringUtils; +import java.io.IOException; +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import org.springframework.http.MediaType; + +/** + * Repeatable 过滤器 + * + * @author ruoyi + */ +public class RepeatableFilter implements Filter { + @Override + public void init(FilterConfig filterConfig) throws ServletException { + + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + ServletRequest requestWrapper = null; + if (request instanceof HttpServletRequest + && StringUtils.equalsAnyIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE)) { + requestWrapper = new RepeatedlyRequestWrapper((HttpServletRequest) request, response); + } + if (null == requestWrapper) { + chain.doFilter(request, response); + } else { + chain.doFilter(requestWrapper, response); + } + } + + @Override + public void destroy() { + + } +} + + +--- File: play-common/src/main/java/com/starry/common/filter/RepeatedlyRequestWrapper.java --- +package com.starry.common.filter; + +import com.starry.common.utils.http.HttpHelper; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; + +/** + * 构建可重复读取inputStream的request + * + * @author ruoyi + */ +public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper { + private final byte[] body; + + public RepeatedlyRequestWrapper(HttpServletRequest request, ServletResponse response) throws IOException { + super(request); + request.setCharacterEncoding("UTF-8"); + response.setCharacterEncoding("UTF-8"); + + body = HttpHelper.getBodyString(request).getBytes("UTF-8"); + } + + @Override + public BufferedReader getReader() throws IOException { + return new BufferedReader(new InputStreamReader(getInputStream())); + } + + @Override + public ServletInputStream getInputStream() throws IOException { + + final ByteArrayInputStream bais = new ByteArrayInputStream(body); + + return new ServletInputStream() { + + @Override + public int read() throws IOException { + return bais.read(); + } + + @Override + public boolean isFinished() { + return false; + } + + @Override + public boolean isReady() { + return false; + } + + @Override + public void setReadListener(ReadListener readListener) { + + } + }; + } +} + + +--- File: play-common/src/main/java/com/starry/common/filter/XssFilter.java --- +package com.starry.common.filter; + +import cn.hutool.core.util.StrUtil; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * 防止XSS攻击的过滤器 + * + * @author ruoyi + */ +public class XssFilter implements Filter { + /** + * 排除链接 + */ + public List excludes = new ArrayList<>(); + + /** + * xss过滤开关 + */ + public boolean enabled = false; + + @Override + public void init(FilterConfig filterConfig) { + String tempExcludes = filterConfig.getInitParameter("excludes"); + String tempEnabled = filterConfig.getInitParameter("enabled"); + if (StrUtil.isNotBlank(tempExcludes)) { + String[] url = tempExcludes.split(","); + excludes.addAll(Arrays.asList(url)); + } + if (StrUtil.isNotBlank(tempEnabled)) { + enabled = Boolean.parseBoolean(tempEnabled); + } + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + HttpServletRequest req = (HttpServletRequest) request; + HttpServletResponse resp = (HttpServletResponse) response; + if (handleExcludeURL(req, resp)) { + chain.doFilter(request, response); + return; + } + XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request); + chain.doFilter(xssRequest, response); + } + + private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response) { + if (!enabled) { + return true; + } + if (excludes == null || excludes.isEmpty()) { + return false; + } + String url = request.getServletPath(); + for (String pattern : excludes) { + Pattern p = Pattern.compile("^" + pattern); + Matcher m = p.matcher(url); + if (m.find()) { + return true; + } + } + return false; + } + + @Override + public void destroy() { + + } +} + + +--- File: play-common/src/main/java/com/starry/common/filter/XssHttpServletRequestWrapper.java --- +package com.starry.common.filter; + +import com.starry.common.utils.StringUtils; +import com.starry.common.utils.html.EscapeUtil; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import org.apache.commons.io.IOUtils; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; + +/** + * XSS过滤处理 + * + * @author ruoyi + */ +public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { + /** + * @param request + */ + public XssHttpServletRequestWrapper(HttpServletRequest request) { + super(request); + } + + @Override + public String[] getParameterValues(String name) { + String[] values = super.getParameterValues(name); + if (values != null) { + int length = values.length; + String[] escapseValues = new String[length]; + for (int i = 0; i < length; i++) { + // 防xss攻击和过滤前后空格 + escapseValues[i] = EscapeUtil.clean(values[i]).trim(); + } + return escapseValues; + } + return super.getParameterValues(name); + } + + @Override + public ServletInputStream getInputStream() throws IOException { + // 非json类型,直接返回 + if (!isJsonRequest()) { + return super.getInputStream(); + } + + // 为空,直接返回 + String json = IOUtils.toString(super.getInputStream(), StandardCharsets.UTF_8); + if (StringUtils.isEmpty(json)) { + return super.getInputStream(); + } + + // xss过滤 + json = EscapeUtil.clean(json).trim(); + final ByteArrayInputStream bis = new ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8)); + return new ServletInputStream() { + @Override + public boolean isFinished() { + return true; + } + + @Override + public boolean isReady() { + return true; + } + + @Override + public void setReadListener(ReadListener readListener) { + } + + @Override + public int read() throws IOException { + return bis.read(); + } + }; + } + + /** + * 是否是Json请求 + */ + public boolean isJsonRequest() { + String header = super.getHeader(HttpHeaders.CONTENT_TYPE); + return MediaType.APPLICATION_JSON_VALUE.equalsIgnoreCase(header); + } +} + + +--- File: play-common/src/main/java/com/starry/common/redis/CaptchaService.java --- +package com.starry.common.redis; + +import cn.hutool.core.util.StrUtil; +import com.starry.common.constant.CacheConstants; +import com.starry.common.domain.Captcha; +import com.starry.common.utils.CaptchaUtils; +import java.awt.image.BufferedImage; +import java.util.UUID; +import java.util.concurrent.TimeUnit; +import javax.annotation.Resource; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.data.redis.core.ValueOperations; +import org.springframework.stereotype.Service; + +/** + * 验证码服务 + * + * @author admin + */ +@Service +public class CaptchaService { + /** + * 拼图验证码允许偏差 + **/ + private static final Integer ALLOW_DEVIATION = 3; + + @Resource + private StringRedisTemplate stringRedisTemplate; + + /** + * 校验验证码 + * + * @param imageKey + * @param imageCode + * @return boolean + **/ + public String checkImageCode(String imageKey, String imageCode) { + ValueOperations ops = stringRedisTemplate.opsForValue(); + String text = ops.get(CacheConstants.CAPTCHA_CODE_KEY + imageKey); + if (StrUtil.isBlank(text)) { + return "验证码已失效"; + } + // 根据移动距离判断验证是否成功 + if (Math.abs(Integer.parseInt(text) - Integer.parseInt(imageCode)) > ALLOW_DEVIATION) { + return "验证失败,请控制拼图对齐缺口"; + } + return null; + } + + /** + * 缓存验证码,有效期15分钟 + * + * @param key + * @param code + **/ + public void saveImageCode(String key, String code) { + ValueOperations ops = stringRedisTemplate.opsForValue(); + ops.set(CacheConstants.CAPTCHA_CODE_KEY + key, code, 15, TimeUnit.MINUTES); + } + + /** + * 获取验证码拼图(生成的抠图和带抠图阴影的大图及抠图坐标) + **/ + public Object getCaptcha(Captcha captcha) { + // 参数校验 + CaptchaUtils.checkCaptcha(captcha); + // 获取画布的宽高 + int canvasWidth = captcha.getCanvasWidth(); + int canvasHeight = captcha.getCanvasHeight(); + // 获取阻塞块的宽高/半径 + int blockWidth = captcha.getBlockWidth(); + int blockHeight = captcha.getBlockHeight(); + int blockRadius = captcha.getBlockRadius(); + // 获取资源图 + BufferedImage canvasImage = CaptchaUtils.getBufferedImage(captcha.getPlace()); + // 调整原图到指定大小 + canvasImage = CaptchaUtils.imageResize(canvasImage, canvasWidth, canvasHeight); + // 随机生成阻塞块坐标 + int blockX = CaptchaUtils.getNonceByRange(blockWidth, canvasWidth - blockWidth - 10); + int blockY = CaptchaUtils.getNonceByRange(10, canvasHeight - blockHeight + 1); + // 阻塞块 + BufferedImage blockImage = new BufferedImage(blockWidth, blockHeight, BufferedImage.TYPE_4BYTE_ABGR); + // 新建的图像根据轮廓图颜色赋值,源图生成遮罩 + CaptchaUtils.cutByTemplate(canvasImage, blockImage, blockWidth, blockHeight, blockRadius, blockX, blockY); + // 移动横坐标 + String nonceStr = UUID.randomUUID().toString().replaceAll("-", ""); + // 缓存 + saveImageCode(nonceStr, String.valueOf(blockX)); + // 设置返回参数 + captcha.setNonceStr(nonceStr); + captcha.setBlockY(blockY); + captcha.setBlockSrc(CaptchaUtils.toBase64(blockImage, "png")); + captcha.setCanvasSrc(CaptchaUtils.toBase64(canvasImage, "png")); + return captcha; + } +} + + +--- File: play-common/src/main/java/com/starry/common/redis/RedisCache.java --- +package com.starry.common.redis; + +import java.util.Collection; +import java.util.concurrent.TimeUnit; +import javax.annotation.Resource; +import org.springframework.dao.QueryTimeoutException; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.ValueOperations; +import org.springframework.stereotype.Component; + +/** + * @author rieds 工具类 + * @since 2022/8/26 + */ +@Component +public class RedisCache { + + @Resource + public RedisTemplate redisTemplate; + + /** + * 获得缓存的基本对象。 + * + * @param key + * 缓存键值 + * @return 缓存键值对应的数据 + */ + public T getCacheObject(final String key) { + ValueOperations operations = redisTemplate.opsForValue(); + try { + return (T) operations.get(key); + } catch (QueryTimeoutException e) { + throw new RuntimeException("系统错误,通讯异常"); + } + + } + + /** + * 缓存基本的对象,Integer、String、实体类等 + * + * @param key + * 缓存的键值 + * @param value + * 缓存的值 + */ + public void setCacheObject(final String key, final T value) { + redisTemplate.opsForValue().set(key, value); + } + + /** + * 缓存基本的对象,Integer、String、实体类等 + * + * @param key + * 缓存的键值 + * @param value + * 缓存的值 + * @param timeout + * 过期时间 + * @param timeUnit + * 时间颗粒度 + */ + public void setCacheObject(final String key, final T value, final Long timeout, final TimeUnit timeUnit) { + redisTemplate.opsForValue().set(key, value, timeout, timeUnit); + } + + /** + * 删除单个对象 + * + * @param key + */ + public boolean deleteObject(final String key) { + return redisTemplate.delete(key); + } + + /** + * 获得缓存的基本对象列表 + * + * @param pattern + * 字符串前缀 + * @return 对象列表 + */ + public Collection keys(final String pattern) { + return redisTemplate.keys(pattern); + } + + /** + * 删除集合对象 + * + * @param collection + * 多个对象 + * @return + */ + public long deleteObject(final Collection collection) { + return redisTemplate.delete(collection); + } +} + + +--- File: play-common/src/main/java/com/starry/common/result/IBaseEnum.java --- +package com.starry.common.result; + +/** + * @author admin + */ +public interface IBaseEnum { + + /** + * 获取枚举值 + */ + int getCode(); + + /** + * 获取枚举描述 + */ + String getMessage(); +} + + +--- File: play-common/src/main/java/com/starry/common/result/R.java --- +package com.starry.common.result; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.beans.ConstructorProperties; +import java.io.Serializable; +import lombok.Data; + +/** + * @author admin + * @since 2021/9/1 + */ +@Data +@ApiModel(value = "全局统一返回结果") +public class R implements Serializable { + + public final static String OK_MSG = "请求成功"; + public final static String FAIL_MSG = "请求失败"; + + @ApiModelProperty(value = "是否成功") + private boolean success; + + @ApiModelProperty(value = "返回码") + private Integer code; + + @ApiModelProperty(value = "返回消息") + private String message; + + @ApiModelProperty(value = "返回数据") + private Object data; + + @ApiModelProperty(value = "总条数") + private Long total; + + @ApiModelProperty(value = "分页信息") + private PageInfo pageInfo; + + private R() { + } + + private R(int code, Boolean success, String msg, Object data) { + this.code = code; + this.success = success; + this.message = msg; + if (data instanceof Page) { + Page page = (Page) data; + this.total = page.getTotal(); + this.data = page.getRecords(); + this.pageInfo = new PageInfo((int) page.getCurrent(), (int) page.getSize(), page.getTotal(), + page.getPages()); + } else { + this.data = data; + } + } + + public static R ok() { + R r = new R(); + r.setSuccess(true); + r.setCode(ResultCodeEnum.SUCCESS.getCode()); + r.setMessage(ResultCodeEnum.SUCCESS.getMessage()); + return r; + } + + public static R ok(Object data) { + return new R(ResultCodeEnum.SUCCESS.getCode(), true, ResultCodeEnum.SUCCESS.getMessage(), data); + } + + public static R ok(String msg, Object data) { + return new R(ResultCodeEnum.SUCCESS.getCode(), true, msg, data); + } + + public static R error() { + R r = new R(); + r.setSuccess(false); + r.setCode(ResultCodeEnum.FAILED.getCode()); + r.setMessage(ResultCodeEnum.FAILED.getMessage()); + return r; + } + + public static R error(String msg) { + return new R(ResultCodeEnum.FAILED.getCode(), false, msg, null); + } + + public static R error(int errorCode, String msg) { + return new R(errorCode, false, msg, null); + } + + public static R unauthorized() { + return new R(ResultCodeEnum.UNAUTHORIZED.getCode(), false, ResultCodeEnum.UNAUTHORIZED.getMessage(), null); + } + + public R message(String message) { + this.setMessage(message); + return this; + } + + public R code(Integer code) { + this.setCode(code); + return this; + } + + public R data(Object data) { + this.setData(data); + return this; + } + + @Data + public static class PageInfo { + + @ApiModelProperty("当前页") + protected int currentPage; + @ApiModelProperty("页大小") + protected int pageSize; + @ApiModelProperty("总记录数") + protected long totalCount; + @ApiModelProperty("总页数") + protected long totalPage; + + public PageInfo() { + } + + @ConstructorProperties({"currentPage", "pageSize", "totalCount", "totalPage"}) + public PageInfo(int currentPage, int pageSize, long totalCount, long totalPage) { + this.currentPage = currentPage; + this.pageSize = pageSize; + this.totalCount = totalCount; + this.totalPage = totalPage; + } + } + +} + + +--- File: play-common/src/main/java/com/starry/common/result/ResultCodeEnum.java --- +package com.starry.common.result; + +/** + * @author admin 返回码枚举 + */ +public enum ResultCodeEnum implements IBaseEnum { + + SUCCESS(200, "操作成功"), FAILED(500, "操作失败"), VALIDATE_FAILED(404, "参数检验失败"), UNAUTHORIZED(401, + "无效的会话,或者会话已过期,请重新登录。"), FORBIDDEN(403, "没有相关权限"), TENANT_NOT_FOUND(403, "租户不存在"); + + private final int code; + private final String message; + + ResultCodeEnum(int code, String message) { + this.code = code; + this.message = message; + } + + @Override + public int getCode() { + return code; + } + + @Override + public String getMessage() { + return message; + } +} + + +--- File: play-common/src/main/java/com/starry/common/sensitive/Sensitive.java --- +package com.starry.common.sensitive; + +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 脱敏注解 + * + * @author admin + **/ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +@JacksonAnnotationsInside +@JsonSerialize(using = SensitiveSerialize.class) +public @interface Sensitive { + + /** + * 脱敏数据类型 + */ + SensitiveTypeEnum type(); + +} + + +--- File: play-common/src/main/java/com/starry/common/sensitive/SensitiveSerialize.java --- +package com.starry.common.sensitive; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.BeanProperty; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.ContextualSerializer; +import java.io.IOException; +import java.util.Objects; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; + +/** + * @author admin + *

+ * 脱敏序列化 + */ +@NoArgsConstructor +@AllArgsConstructor +public class SensitiveSerialize extends JsonSerializer implements ContextualSerializer { + + private SensitiveTypeEnum type; + + @Override + public void serialize(final String originStr, final JsonGenerator jsonGenerator, + final SerializerProvider serializerProvider) throws IOException { + switch (type) { + case CHINESE_NAME : + jsonGenerator.writeString(SensitiveUtils.chineseName(originStr)); + break; + case MOBILE_PHONE : + jsonGenerator.writeString(SensitiveUtils.mobilePhone(originStr)); + break; + case EMAIL : + jsonGenerator.writeString(SensitiveUtils.email(originStr)); + break; + case PASSWORD : + jsonGenerator.writeString(SensitiveUtils.password(originStr)); + break; + case KEY : + jsonGenerator.writeString(SensitiveUtils.key(originStr)); + break; + default : + throw new IllegalArgumentException("未定义的敏感信息枚举类" + type); + } + } + + @Override + public JsonSerializer createContextual(final SerializerProvider serializerProvider, + final BeanProperty beanProperty) throws JsonMappingException { + if (beanProperty != null) { + if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) { + Sensitive sensitive = beanProperty.getAnnotation(Sensitive.class); + if (sensitive == null) { + sensitive = beanProperty.getContextAnnotation(Sensitive.class); + } + if (sensitive != null) { + return new SensitiveSerialize(sensitive.type()); + } + } + return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty); + } + return serializerProvider.findNullValueSerializer(null); + } + +} + + +--- File: play-common/src/main/java/com/starry/common/sensitive/SensitiveTypeEnum.java --- +package com.starry.common.sensitive; + +/** + * 敏感信息枚举类 + * + * @author admin + **/ +public enum SensitiveTypeEnum { + + /** + * 用户名, 李*天, 张* + */ + CHINESE_NAME, + /** + * 手机号, 185****1653 + */ + MOBILE_PHONE, + /** + * 电子邮件, r*****o@qq.com + */ + EMAIL, + /** + * 密码, ****** + */ + PASSWORD, + /** + * 密钥, 最后三位其他都是*** + */ + KEY + +} + + +--- File: play-common/src/main/java/com/starry/common/sensitive/SensitiveUtils.java --- +package com.starry.common.sensitive; + +import cn.hutool.core.util.StrUtil; + +/** + * 数据脱敏工具类 + * + * @author admin + * @since 2021/7/19 16:21 + */ +public class SensitiveUtils { + + /** + * 默认填充字符 + */ + public static final String DEFAULT_PAD_STR = "*"; + + /** + * 数据脱敏 + */ + public static String process(String data) { + return process(data, 2, 1, DEFAULT_PAD_STR); + } + + /** + * 数据脱敏 + */ + public static String process(String data, Integer leftLen, Integer rightLen) { + return process(data, leftLen, rightLen, DEFAULT_PAD_STR); + } + + /** + * 对字符串进行脱敏操作 + * + * @param originStr + * 原始字符串 + * @param prefixNoMaskLen + * 左侧需要保留几位明文字段 + * @param suffixNoMaskLen + * 右侧需要保留几位明文字段 + * @param maskStr + * 用于遮罩的字符串, 如'*' + * @return 脱敏后结果 + */ + public static String process(String originStr, int prefixNoMaskLen, int suffixNoMaskLen, String maskStr) { + if (originStr == null) { + return null; + } + + StringBuilder sb = new StringBuilder(); + for (int i = 0, n = originStr.length(); i < n; i++) { + if (i < prefixNoMaskLen) { + sb.append(originStr.charAt(i)); + continue; + } + if (i > (n - suffixNoMaskLen - 1)) { + sb.append(originStr.charAt(i)); + continue; + } + sb.append(maskStr); + } + return sb.toString(); + } + + /** + * 中文姓名只显示最后一个汉字 + * + * @param fullName + * 姓名 + * @return + */ + public static String chineseName(String fullName) { + if (fullName == null) { + return null; + } + return process(fullName, 0, 1, DEFAULT_PAD_STR); + } + + /** + * 手机号码前三位,后四位,如186****2356 + * + * @param num + * 手机号码 + * @return + */ + public static String mobilePhone(String num) { + return process(num, 0, 4, DEFAULT_PAD_STR); + } + + /** + * 地址只显示到地区 + * + * @param address + * 地址 + * @return + */ + public static String address(String address) { + return process(address, 6, 0, DEFAULT_PAD_STR); + } + + /** + * 电子邮箱 仅显示第一个字母,@后面的地址显示,比如:r**@qq.com + * + * @param email + * 电子邮箱 + * @return + */ + public static String email(String email) { + if (email == null) { + return null; + } + int index = StrUtil.indexOf(email, '@'); + if (index <= 1) { + return email; + } + String preEmail = process(email.substring(0, index), 1, 0, DEFAULT_PAD_STR); + return preEmail + email.substring(index); + + } + + /** + * 密码的全部字符,如:****** + * + * @param password + * 密码 + * @return + */ + public static String password(String password) { + if (password == null) { + return null; + } + return "******"; + } + + /** + * 密钥除了最后三位,全部,比如:***klo + * + * @param key + * 密钥 + * @return 结果 + */ + public static String key(String key) { + if (key == null) { + return null; + } + int viewLength = 6; + StringBuilder tmpKey = new StringBuilder(process(key, 0, 3, DEFAULT_PAD_STR)); + if (tmpKey.length() > viewLength) { + return tmpKey.substring(tmpKey.length() - viewLength); + } else if (tmpKey.length() < viewLength) { + int buffLength = viewLength - tmpKey.length(); + for (int i = 0; i < buffLength; i++) { + tmpKey.insert(0, DEFAULT_PAD_STR); + } + return tmpKey.toString(); + } else { + return tmpKey.toString(); + } + } + + public static void main(String[] args) { + String s = mobilePhone("18653653621"); + System.out.println(s); + } +} + + +--- File: play-common/src/main/java/com/starry/common/utils/Arith.java --- +package com.starry.common.utils; + +import java.math.BigDecimal; +import java.math.RoundingMode; + +/** + * 精确的浮点数运算 + * + * @author ruoyi + */ +public class Arith { + + /** + * 默认除法运算精度 + */ + private static final int DEF_DIV_SCALE = 10; + + /** + * 这个类不能实例化 + */ + private Arith() { + } + + /** + * 提供精确的加法运算。 + * + * @param v1 + * 被加数 + * @param v2 + * 加数 + * @return 两个参数的和 + */ + public static double add(double v1, double v2) { + BigDecimal b1 = new BigDecimal(Double.toString(v1)); + BigDecimal b2 = new BigDecimal(Double.toString(v2)); + return b1.add(b2).doubleValue(); + } + + /** + * 提供精确的减法运算。 + * + * @param v1 + * 被减数 + * @param v2 + * 减数 + * @return 两个参数的差 + */ + public static double sub(double v1, double v2) { + BigDecimal b1 = new BigDecimal(Double.toString(v1)); + BigDecimal b2 = new BigDecimal(Double.toString(v2)); + return b1.subtract(b2).doubleValue(); + } + + /** + * 提供精确的乘法运算。 + * + * @param v1 + * 被乘数 + * @param v2 + * 乘数 + * @return 两个参数的积 + */ + public static double mul(double v1, double v2) { + BigDecimal b1 = new BigDecimal(Double.toString(v1)); + BigDecimal b2 = new BigDecimal(Double.toString(v2)); + return b1.multiply(b2).doubleValue(); + } + + /** + * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到 小数点以后10位,以后的数字四舍五入。 + * + * @param v1 + * 被除数 + * @param v2 + * 除数 + * @return 两个参数的商 + */ + public static double div(double v1, double v2) { + return div(v1, v2, DEF_DIV_SCALE); + } + + /** + * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指 定精度,以后的数字四舍五入。 + * + * @param v1 + * 被除数 + * @param v2 + * 除数 + * @param scale + * 表示表示需要精确到小数点以后几位。 + * @return 两个参数的商 + */ + public static double div(double v1, double v2, int scale) { + if (scale < 0) { + throw new IllegalArgumentException("The scale must be a positive integer or zero"); + } + BigDecimal b1 = new BigDecimal(Double.toString(v1)); + BigDecimal b2 = new BigDecimal(Double.toString(v2)); + if (b1.compareTo(BigDecimal.ZERO) == 0) { + return BigDecimal.ZERO.doubleValue(); + } + return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue(); + } + + /** + * 提供精确的小数位四舍五入处理。 + * + * @param v + * 需要四舍五入的数字 + * @param scale + * 小数点后保留几位 + * @return 四舍五入后的结果 + */ + public static double round(double v, int scale) { + if (scale < 0) { + throw new IllegalArgumentException("The scale must be a positive integer or zero"); + } + BigDecimal b = new BigDecimal(Double.toString(v)); + BigDecimal one = BigDecimal.ONE; + return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue(); + } +} + + +--- File: play-common/src/main/java/com/starry/common/utils/CaptchaUtils.java --- +package com.starry.common.utils; + +import com.starry.common.domain.Captcha; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.util.Base64; +import java.util.Objects; +import java.util.Random; +import javax.imageio.ImageIO; +import org.apache.commons.lang3.RandomUtils; + +/** + * @author 拼图验证码工具类 + * @since 2022/9/6 + */ +public class CaptchaUtils { + + /** + * 网络图片地址 + **/ + private final static String IMG_URL = "https://loyer.wang/view/ftp/wallpaper/%s.jpg"; + + /** + * 本地图片地址 + **/ + private final static String IMG_PATH = "E:/Temp/wallpaper/%s.jpg"; + + /** + * 入参校验设置默认值 + **/ + public static void checkCaptcha(Captcha captcha) { + // 设置画布宽度默认值 + if (captcha.getCanvasWidth() == null) { + captcha.setCanvasWidth(320); + } + // 设置画布高度默认值 + if (captcha.getCanvasHeight() == null) { + captcha.setCanvasHeight(155); + } + // 设置阻塞块宽度默认值 + if (captcha.getBlockWidth() == null) { + captcha.setBlockWidth(65); + } + // 设置阻塞块高度默认值 + if (captcha.getBlockHeight() == null) { + captcha.setBlockHeight(55); + } + // 设置阻塞块凹凸半径默认值 + if (captcha.getBlockRadius() == null) { + captcha.setBlockRadius(9); + } + // 设置图片来源默认值 + if (captcha.getPlace() == null) { + captcha.setPlace(0); + } + } + + /** + * 获取指定范围内的随机数 + **/ + public static int getNonceByRange(int start, int end) { + Random random = new Random(); + return random.nextInt(end - start + 1) + start; + } + + /** + * 获取验证码资源图 + **/ + public static BufferedImage getBufferedImage(Integer place) { + try { + // 随机图片 + int nonce = getNonceByRange(0, 1000); + // 获取网络资源图片 + if (0 == place) { + String imgUrl = String.format(IMG_URL, nonce); + URL url = new URL(imgUrl); + return ImageIO.read(url.openStream()); + } + // 获取本地图片 + else { + String imgPath = String.format(IMG_PATH, nonce); + File file = new File(imgPath); + return ImageIO.read(file); + } + } catch (Exception e) { + System.out.println("获取拼图资源失败"); + // 异常处理 + return null; + } + } + + /** + * 调整图片大小 + **/ + public static BufferedImage imageResize(BufferedImage bufferedImage, int width, int height) { + Image image = bufferedImage.getScaledInstance(width, height, Image.SCALE_SMOOTH); + BufferedImage resultImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + Graphics2D graphics2D = resultImage.createGraphics(); + graphics2D.drawImage(image, 0, 0, null); + graphics2D.dispose(); + return resultImage; + } + + /** + * 抠图,并生成阻塞块 + **/ + public static void cutByTemplate(BufferedImage canvasImage, BufferedImage blockImage, int blockWidth, + int blockHeight, int blockRadius, int blockX, int blockY) { + BufferedImage waterImage = new BufferedImage(blockWidth, blockHeight, BufferedImage.TYPE_4BYTE_ABGR); + // 阻塞块的轮廓图 + int[][] blockData = getBlockData(blockWidth, blockHeight, blockRadius); + // 创建阻塞块具体形状 + for (int i = 0; i < blockWidth; i++) { + for (int j = 0; j < blockHeight; j++) { + try { + // 原图中对应位置变色处理 + if (blockData[i][j] == 1) { + // 背景设置为黑色 + waterImage.setRGB(i, j, Color.BLACK.getRGB()); + blockImage.setRGB(i, j, canvasImage.getRGB(blockX + i, blockY + j)); + // 轮廓设置为白色,取带像素和无像素的界点,判断该点是不是临界轮廓点 + if (blockData[i + 1][j] == 0 || blockData[i][j + 1] == 0 || blockData[i - 1][j] == 0 + || blockData[i][j - 1] == 0) { + blockImage.setRGB(i, j, Color.WHITE.getRGB()); + waterImage.setRGB(i, j, Color.WHITE.getRGB()); + } + } + // 这里把背景设为透明 + else { + blockImage.setRGB(i, j, Color.TRANSLUCENT); + waterImage.setRGB(i, j, Color.TRANSLUCENT); + } + } catch (ArrayIndexOutOfBoundsException e) { + // 防止数组下标越界异常 + } + } + } + // 在画布上添加阻塞块水印 + addBlockWatermark(canvasImage, waterImage, blockX, blockY); + } + + /** + * 构建拼图轮廓轨迹 + **/ + private static int[][] getBlockData(int blockWidth, int blockHeight, int blockRadius) { + int[][] data = new int[blockWidth][blockHeight]; + double po = Math.pow(blockRadius, 2); + // 随机生成两个圆的坐标,在4个方向上 随机找到2个方向添加凸/凹 + // 凸/凹1 + int face1 = RandomUtils.nextInt(0, 4); + // 凸/凹2 + int face2; + // 保证两个凸/凹不在同一位置 + do { + face2 = RandomUtils.nextInt(0, 4); + } while (face1 == face2); + // 获取凸/凹起位置坐标 + int[] circle1 = getCircleCoords(face1, blockWidth, blockHeight, blockRadius); + int[] circle2 = getCircleCoords(face2, blockWidth, blockHeight, blockRadius); + // 随机凸/凹类型 + int shape = getNonceByRange(0, 1); + // 圆的标准方程 (x-a)²+(y-b)²=r²,标识圆心(a,b),半径为r的圆 + // 计算需要的小图轮廓,用二维数组来表示,二维数组有两张值,0和1,其中0表示没有颜色,1有颜色 + for (int i = 0; i < blockWidth; i++) { + for (int j = 0; j < blockHeight; j++) { + data[i][j] = 0; + // 创建中间的方形区域 + if ((i >= blockRadius && i <= blockWidth - blockRadius && j >= blockRadius + && j <= blockHeight - blockRadius)) { + data[i][j] = 1; + } + double d1 = Math.pow(i - Objects.requireNonNull(circle1)[0], 2) + Math.pow(j - circle1[1], 2); + double d2 = Math.pow(i - Objects.requireNonNull(circle2)[0], 2) + Math.pow(j - circle2[1], 2); + // 创建两个凸/凹 + if (d1 <= po || d2 <= po) { + data[i][j] = shape; + } + } + } + return data; + } + + /** + * 根据朝向获取圆心坐标 + */ + private static int[] getCircleCoords(int face, int blockWidth, int blockHeight, int blockRadius) { + // 上 + if (0 == face) { + return new int[]{blockWidth / 2 - 1, blockRadius}; + } + // 左 + else if (1 == face) { + return new int[]{blockRadius, blockHeight / 2 - 1}; + } + // 下 + else if (2 == face) { + return new int[]{blockWidth / 2 - 1, blockHeight - blockRadius - 1}; + } + // 右 + else if (3 == face) { + return new int[]{blockWidth - blockRadius - 1, blockHeight / 2 - 1}; + } + return null; + } + + /** + * 在画布上添加阻塞块水印 + */ + private static void addBlockWatermark(BufferedImage canvasImage, BufferedImage blockImage, int x, int y) { + Graphics2D graphics2D = canvasImage.createGraphics(); + graphics2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.8f)); + graphics2D.drawImage(blockImage, x, y, null); + graphics2D.dispose(); + } + + /** + * BufferedImage转BASE64 + */ + public static String toBase64(BufferedImage bufferedImage, String type) { + try { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + ImageIO.write(bufferedImage, type, byteArrayOutputStream); + String base64 = Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray()); + return String.format("data:image/%s;base64,%s", type, base64); + } catch (IOException e) { + System.out.println("图片资源转换BASE64失败"); + // 异常处理 + return null; + } + } +} + + +--- File: play-common/src/main/java/com/starry/common/utils/ConvertUtil.java --- +package com.starry.common.utils; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; + +/** + * @author admin + */ +@Slf4j +public class ConvertUtil { + + public static T entityToVo(Object source, Class target) { + if (source == null) { + return null; + } + T targetObject = null; + try { + targetObject = target.newInstance(); + BeanUtils.copyProperties(source, targetObject); + } catch (Exception e) { + log.error("entityToVo error,source = {},target={}", source, target, e); + } + return targetObject; + } + + public static List entityToVoList(Collection sourceList, Class target) { + if (sourceList == null) { + return null; + } + List targetList = new ArrayList<>(sourceList.size()); + + try { + for (Object source : sourceList) { + T targetObject = target.newInstance(); + BeanUtils.copyProperties(source, targetObject); + targetList.add(targetObject); + } + } catch (Exception e) { + log.error("entityToVo error,source = {},target={}", sourceList, target, e); + } + return targetList; + } + +} + + +--- File: play-common/src/main/java/com/starry/common/utils/HttpUtils.java --- +package com.starry.common.utils; + +import java.io.*; +import java.net.ConnectException; +import java.net.SocketTimeoutException; +import java.net.URL; +import java.net.URLConnection; +import java.nio.charset.StandardCharsets; +import java.security.cert.X509Certificate; +import javax.net.ssl.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * 通用http发送方法 + * + * @author ruoyi + */ +public class HttpUtils { + private static final Logger log = LoggerFactory.getLogger(HttpUtils.class); + + /** + * 向指定 URL 发送GET方法的请求 + * + * @param url + * 发送请求的 URL + * @return 所代表远程资源的响应结果 + */ + public static String sendGet(String url) { + return sendGet(url, StringUtils.EMPTY); + } + + /** + * 向指定 URL 发送GET方法的请求 + * + * @param url + * 发送请求的 URL + * @param param + * 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 + * @return 所代表远程资源的响应结果 + */ + public static String sendGet(String url, String param) { + return sendGet(url, param, "utf-8"); + } + + /** + * 向指定 URL 发送GET方法的请求 + * + * @param url + * 发送请求的 URL + * @param param + * 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 + * @param contentType + * 编码类型 + * @return 所代表远程资源的响应结果 + */ + public static String sendGet(String url, String param, String contentType) { + StringBuilder result = new StringBuilder(); + BufferedReader in = null; + try { + String urlNameString = StringUtils.isNotBlank(param) ? url + "?" + param : url; + log.info("sendGet - {}", urlNameString); + URL realUrl = new URL(urlNameString); + URLConnection connection = realUrl.openConnection(); + connection.setRequestProperty("accept", "*/*"); + connection.setRequestProperty("connection", "Keep-Alive"); + connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + connection.connect(); + in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType)); + String line; + while ((line = in.readLine()) != null) { + result.append(line); + } + log.info("recv - {}", result); + } catch (ConnectException e) { + log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e); + } catch (SocketTimeoutException e) { + log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e); + } catch (IOException e) { + log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e); + } catch (Exception e) { + log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e); + } finally { + try { + if (in != null) { + in.close(); + } + } catch (Exception ex) { + log.error("调用in.close Exception, url=" + url + ",param=" + param, ex); + } + } + return result.toString(); + } + + /** + * 向指定 URL 发送POST方法的请求 + * + * @param url + * 发送请求的 URL + * @param param + * 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 + * @return 所代表远程资源的响应结果 + */ + public static String sendPost(String url, String param) { + PrintWriter out = null; + BufferedReader in = null; + StringBuilder result = new StringBuilder(); + try { + log.info("sendPost - {}", url); + URL realUrl = new URL(url); + URLConnection conn = realUrl.openConnection(); + conn.setRequestProperty("accept", "*/*"); + conn.setRequestProperty("connection", "Keep-Alive"); + conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + conn.setRequestProperty("Accept-Charset", "utf-8"); + conn.setRequestProperty("contentType", "utf-8"); + conn.setDoOutput(true); + conn.setDoInput(true); + out = new PrintWriter(conn.getOutputStream()); + out.print(param); + out.flush(); + in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8)); + String line; + while ((line = in.readLine()) != null) { + result.append(line); + } + log.info("recv - {}", result); + } catch (ConnectException e) { + log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e); + } catch (SocketTimeoutException e) { + log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e); + } catch (IOException e) { + log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e); + } catch (Exception e) { + log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e); + } finally { + try { + if (out != null) { + out.close(); + } + if (in != null) { + in.close(); + } + } catch (IOException ex) { + log.error("调用in.close Exception, url=" + url + ",param=" + param, ex); + } + } + return result.toString(); + } + + public static String sendSSLPost(String url, String param) { + StringBuilder result = new StringBuilder(); + String urlNameString = url + "?" + param; + try { + log.info("sendSSLPost - {}", urlNameString); + SSLContext sc = SSLContext.getInstance("SSL"); + sc.init(null, new TrustManager[]{new TrustAnyTrustManager()}, new java.security.SecureRandom()); + URL console = new URL(urlNameString); + HttpsURLConnection conn = (HttpsURLConnection) console.openConnection(); + conn.setRequestProperty("accept", "*/*"); + conn.setRequestProperty("connection", "Keep-Alive"); + conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + conn.setRequestProperty("Accept-Charset", "utf-8"); + conn.setRequestProperty("contentType", "utf-8"); + conn.setDoOutput(true); + conn.setDoInput(true); + + conn.setSSLSocketFactory(sc.getSocketFactory()); + conn.setHostnameVerifier(new TrustAnyHostnameVerifier()); + conn.connect(); + InputStream is = conn.getInputStream(); + BufferedReader br = new BufferedReader(new InputStreamReader(is)); + String ret = ""; + while ((ret = br.readLine()) != null) { + if (ret != null && !"".equals(ret.trim())) { + result.append(new String(ret.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8)); + } + } + log.info("recv - {}", result); + conn.disconnect(); + br.close(); + } catch (ConnectException e) { + log.error("调用HttpUtils.sendSSLPost ConnectException, url=" + url + ",param=" + param, e); + } catch (SocketTimeoutException e) { + log.error("调用HttpUtils.sendSSLPost SocketTimeoutException, url=" + url + ",param=" + param, e); + } catch (IOException e) { + log.error("调用HttpUtils.sendSSLPost IOException, url=" + url + ",param=" + param, e); + } catch (Exception e) { + log.error("调用HttpsUtil.sendSSLPost Exception, url=" + url + ",param=" + param, e); + } + return result.toString(); + } + + private static class TrustAnyTrustManager implements X509TrustManager { + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) { + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) { + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[]{}; + } + } + + private static class TrustAnyHostnameVerifier implements HostnameVerifier { + @Override + public boolean verify(String hostname, SSLSession session) { + return true; + } + } +} + + +--- File: play-common/src/main/java/com/starry/common/utils/IdUtils.java --- +package com.starry.common.utils; + +import cn.hutool.core.util.RandomUtil; + +/** + * @author admin + * @since 2024/5/13 下午11:07 + **/ +public class IdUtils { + + /** + * 生成8位的UUID + * + * @return UUID + */ + public static String getUuid() { + return RandomUtil.randomString(9).toLowerCase(); + } +} + + +--- File: play-common/src/main/java/com/starry/common/utils/RegionUtils.java --- +package com.starry.common.utils; + +/** + * @author admin + * @since 2024/7/25 下午3:15 + **/ + +import java.io.File; +import java.io.InputStream; +import java.lang.reflect.Method; +import java.util.Objects; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.FileUtils; +import org.lionsoul.ip2region.DataBlock; +import org.lionsoul.ip2region.DbConfig; +import org.lionsoul.ip2region.DbSearcher; +import org.lionsoul.ip2region.Util; +import org.springframework.core.io.ClassPathResource; + +/** + * 根据ip离线查询地址 + * + * @author admin + */ +@Slf4j +public class RegionUtils { + + private static final String JAVA_TEMP_DIR = "java.io.tmpdir"; + + static DbConfig config = null; + static DbSearcher searcher = null; + + /** + * 初始化IP库 + */ + static { + try { + // 因为jar无法读取文件,复制创建临时文件 + String dbPath = Objects.requireNonNull(RegionUtils.class.getResource("/ip2region/ip2region.db")).getPath(); + File file = new File(dbPath); + if (!file.exists()) { + String tmpDir = System.getProperties().getProperty(JAVA_TEMP_DIR); + dbPath = tmpDir + "ip2region.db"; + file = new File(dbPath); + ClassPathResource cpr = new ClassPathResource("ip2region" + File.separator + "ip2region.db"); + InputStream resourceAsStream = cpr.getInputStream(); + FileUtils.copyInputStreamToFile(resourceAsStream, file); + } + config = new DbConfig(); + searcher = new DbSearcher(config, dbPath); + log.info("bean [{}]", config); + log.info("bean [{}]", searcher); + } catch (Exception e) { + log.error("init ip region error:", e); + } + } + + /** + * 解析IP + * + * @param ip + * @return + */ + public static String getRegion(String ip) { + try { + // db + if (searcher == null || StringUtils.isEmpty(ip)) { + log.error("DbSearcher is null"); + return StringUtils.EMPTY; + } + long startTime = System.currentTimeMillis(); + // 查询算法 + int algorithm = DbSearcher.MEMORY_ALGORITYM; + Method method = null; + switch (algorithm) { + case DbSearcher.BTREE_ALGORITHM : + method = searcher.getClass().getMethod("btreeSearch", String.class); + break; + case DbSearcher.BINARY_ALGORITHM : + method = searcher.getClass().getMethod("binarySearch", String.class); + break; + case DbSearcher.MEMORY_ALGORITYM : + method = searcher.getClass().getMethod("memorySearch", String.class); + break; + default : + return StringUtils.EMPTY; + } + + DataBlock dataBlock = null; + if (!Util.isIpAddress(ip)) { + log.warn("warning: Invalid ip address"); + } + dataBlock = (DataBlock) method.invoke(searcher, ip); + String result = dataBlock.getRegion(); + long endTime = System.currentTimeMillis(); + log.debug("region use time[{}] result[{}]", endTime - startTime, result); + return result; + + } catch (Exception e) { + log.error("error:", e); + } + return StringUtils.EMPTY; + } + +} + + +--- File: play-common/src/main/java/com/starry/common/utils/ServletUtils.java --- +package com.starry.common.utils; + +import cn.hutool.core.convert.Convert; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.net.URLEncoder; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +/** + * 客户端工具类 + * + * @author ruoyi + */ +public class ServletUtils { + /** + * 获取String参数 + */ + public static String getParameter(String name) { + return getRequest().getParameter(name); + } + + /** + * 获取String参数 + */ + public static String getParameter(String name, String defaultValue) { + return Convert.toStr(getRequest().getParameter(name), defaultValue); + } + + /** + * 获取Integer参数 + */ + public static Integer getParameterToInt(String name) { + return Convert.toInt(getRequest().getParameter(name)); + } + + /** + * 获取Integer参数 + */ + public static Integer getParameterToInt(String name, Integer defaultValue) { + return Convert.toInt(getRequest().getParameter(name), defaultValue); + } + + /** + * 获取Boolean参数 + */ + public static Boolean getParameterToBool(String name) { + return Convert.toBool(getRequest().getParameter(name)); + } + + /** + * 获取Boolean参数 + */ + public static Boolean getParameterToBool(String name, Boolean defaultValue) { + return Convert.toBool(getRequest().getParameter(name), defaultValue); + } + + /** + * 获取request + */ + public static HttpServletRequest getRequest() { + return getRequestAttributes().getRequest(); + } + + /** + * 获取response + */ + public static HttpServletResponse getResponse() { + return getRequestAttributes().getResponse(); + } + + /** + * 获取session + */ + public static HttpSession getSession() { + return getRequest().getSession(); + } + + public static ServletRequestAttributes getRequestAttributes() { + RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); + return (ServletRequestAttributes) attributes; + } + + /** + * 将字符串渲染到客户端 + * + * @param response + * 渲染对象 + * @param string + * 待渲染的字符串 + */ + public static void renderString(HttpServletResponse response, String string) { + try { + response.setStatus(200); + response.setContentType("application/json"); + response.setCharacterEncoding("utf-8"); + response.getWriter().print(string); + } catch (IOException e) { + + } + } + + /** + * 是否是Ajax异步请求 + * + * @param request + */ + /* + * public static boolean isAjaxRequest(HttpServletRequest request) { String + * accept = request.getHeader("accept"); if (accept != null && + * accept.contains("application/json")) { return true; } + * + * String xRequestedWith = request.getHeader("X-Requested-With"); if + * (xRequestedWith != null && xRequestedWith.contains("XMLHttpRequest")) { + * return true; } + * + * String uri = request.getRequestURI(); if (StringUtils.inStringIgnoreCase(uri, + * ".json", ".xml")) { return true; } + * + * String ajax = request.getParameter("__ajax"); return + * StringUtils.inStringIgnoreCase(ajax, "json", "xml"); } + */ + + /** + * 内容编码 + * + * @param str + * 内容 + * @return 编码后的内容 + */ + public static String urlEncode(String str) { + try { + return URLEncoder.encode(str, "UTF-8"); + } catch (UnsupportedEncodingException e) { + return StringUtils.EMPTY; + } + } + + /** + * 内容解码 + * + * @param str + * 内容 + * @return 解码后的内容 + */ + public static String urlDecode(String str) { + try { + return URLDecoder.decode(str, "UTF-8"); + } catch (UnsupportedEncodingException e) { + return StringUtils.EMPTY; + } + } +} + + +--- File: play-common/src/main/java/com/starry/common/utils/SpringUtils.java --- +package com.starry.common.utils; + +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @author admin spring工具类 方便在非spring管理环境中获取bean + * @since 2022/7/28 + */ +@Component +public class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware { + + /** + * Spring应用上下文环境 + */ + private static ConfigurableListableBeanFactory beanFactory; + + private static ApplicationContext applicationContext; + + /** + * 获取类型为requiredType的对象 + * + * @param clz + * @return + * @throws BeansException + */ + public static T getBean(Class clz) throws BeansException { + T result = (T) beanFactory.getBean(clz); + return result; + } + + /** + * 获取对象 + * + * @param name + * @return Object 一个以所给名字注册的bean的实例 + * @throws BeansException + */ + @SuppressWarnings("unchecked") + public static T getBean(String name) throws BeansException { + return (T) beanFactory.getBean(name); + } + + /** + * 获取aop代理对象 + * + * @param invoker + * @return + */ + @SuppressWarnings("unchecked") + public static T getAopProxy(T invoker) { + return (T) AopContext.currentProxy(); + } + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { + SpringUtils.beanFactory = beanFactory; + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + SpringUtils.applicationContext = applicationContext; + } +} + + +--- File: play-common/src/main/java/com/starry/common/utils/StringUtils.java --- +package com.starry.common.utils; + +import cn.hutool.core.text.StrFormatter; +import java.util.Collection; +import java.util.Map; + +/** + * @author admin 字符串工具类 + * @since 2022/7/19 + */ +public class StringUtils extends org.apache.commons.lang3.StringUtils { + + /** + * 空字符串 + */ + private static final String NULLSTR = ""; + + /** + * 下划线 + */ + private static final char SEPARATOR = '_'; + + /** + * 驼峰转下划线命名 + */ + public static String toUnderScoreCase(String str) { + if (str == null) { + return null; + } + StringBuilder sb = new StringBuilder(); + // 前置字符是否大写 + boolean preCharIsUpperCase = true; + // 当前字符是否大写 + boolean curreCharIsUpperCase = true; + // 下一字符是否大写 + boolean nexteCharIsUpperCase = true; + for (int i = 0; i < str.length(); i++) { + char c = str.charAt(i); + if (i > 0) { + preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1)); + } else { + preCharIsUpperCase = false; + } + + curreCharIsUpperCase = Character.isUpperCase(c); + + if (i < (str.length() - 1)) { + nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1)); + } + + if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase) { + sb.append(SEPARATOR); + } else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase) { + sb.append(SEPARATOR); + } + sb.append(Character.toLowerCase(c)); + } + + return sb.toString(); + } + + /** + * 判断一个对象是否为空 + * + * @param object + * Object + * @return true:为空 false:非空 + */ + public static boolean isNull(Object object) { + return object == null; + } + + /** + * 判断一个对象是否非空 + * + * @param object + * Object + * @return true:非空 false:空 + */ + public static boolean isNotNull(Object object) { + return !isNull(object); + } + + /** + * 判断一个对象数组是否为空 + * + * @param objects + * 要判断的对象数组 * @return true:为空 false:非空 + */ + public static boolean isEmpty(Object[] objects) { + return isNull(objects) || (objects.length == 0); + } + + /** + * 判断一个Map是否为空 + * + * @param map + * 要判断的Map + * @return true:为空 false:非空 + */ + public static boolean isEmpty(Map map) { + return isNull(map) || map.isEmpty(); + } + + /** + * 判断一个Map是否为空 + * + * @param map + * 要判断的Map + * @return true:非空 false:空 + */ + public static boolean isNotEmpty(Map map) { + return !isEmpty(map); + } + + /** + * 判断一个Collection是否非空,包含List,Set,Queue + * + * @param coll + * 要判断的Collection + * @return true:非空 false:空 + */ + public static boolean isNotEmpty(Collection coll) { + return !isEmpty(coll); + } + + /** + * 判断一个Collection是否为空, 包含List,Set,Queue + * + * @param coll + * 要判断的Collection + * @return true:为空 false:非空 + */ + public static boolean isEmpty(Collection coll) { + return isNull(coll) || coll.isEmpty(); + } + + /** + * 格式化文本, {} 表示占位符
+ * 此方法只是简单将占位符 {} 按照顺序替换为参数
+ * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可
+ * 例:
+ * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b
+ * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a
+ * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b
+ * + * @param template + * 文本模板,被替换的部分用 {} 表示 + * @param params + * 参数值 + * @return 格式化后的文本 + */ + public static String format(String template, Object... params) { + if (isEmpty(params) || isEmpty(template)) { + return template; + } + return StrFormatter.format(template, params); + } + + /** + * 判断给定的set列表中是否包含数组array 判断给定的数组array中是否包含给定的元素value + * + * @param collection + * 给定的集合 + * @param array + * 给定的数组 + * @return boolean 结果 + */ + public static boolean containsAny(Collection collection, String... array) { + if (isEmpty(collection) || isEmpty(array)) { + return false; + } else { + for (String str : array) { + if (collection.contains(str)) { + return true; + } + } + return false; + } + } + + /** + * 驼峰式命名法 例如:user_name->userName + */ + public static String toCamelCase(String s) { + if (org.apache.commons.lang3.StringUtils.isNotBlank(s)) { + // 小写 + s = s.toLowerCase(); + StringBuilder sb = new StringBuilder(s.length()); + // 大写 + boolean upperCase = false; + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (c == '_') { + upperCase = true; + } else if (upperCase) { + sb.append(Character.toUpperCase(c)); + upperCase = false; + } else { + sb.append(c); + } + } + return sb.toString(); + } + return s; + } + + /** + * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD -> + * HelloWorld + * + * @param name + * 转换前的下划线大写方式命名的字符串 + * @return 转换后的驼峰式命名的字符串 + */ + public static String convertToCamelCase(String name) { + StringBuilder result = new StringBuilder(); + if (org.apache.commons.lang3.StringUtils.isBlank(name)) { + return ""; + } else if (!name.contains("_")) { + // 不含下划线,仅将首字母大写 + return name.substring(0, 1).toUpperCase() + name.substring(1); + } + String[] camels = name.split("_"); + for (String camel : camels) { + // 跳过原始字符串中开头、结尾的下换线或双重下划线 + if (camel.isEmpty()) { + continue; + } + // 首字母大写 + result.append(camel.substring(0, 1).toUpperCase()); + result.append(camel.substring(1).toLowerCase()); + } + return result.toString(); + } + + public static T cast(Object obj) { + return (T) obj; + } +} + + +--- File: play-common/src/main/java/com/starry/common/utils/ThreadsUtils.java --- +package com.starry.common.utils; + +import java.util.concurrent.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author admin 线程相关工具类 + * @since 2022/7/25 + */ +public class ThreadsUtils { + private static final Logger logger = LoggerFactory.getLogger(ThreadsUtils.class); + + /** + * 停止线程池 先使用shutdown, 停止接收新任务并尝试完成所有已存在任务. 如果超时, 则调用shutdownNow, + * 取消在workQueue中Pending的任务,并中断所有阻塞函数. 如果仍然超時,則強制退出. 另对在shutdown时线程本身被调用中断做了处理. + */ + public static void shutdownAndAwaitTermination(ExecutorService pool) { + if (pool != null && !pool.isShutdown()) { + pool.shutdown(); + try { + if (!pool.awaitTermination(120, TimeUnit.SECONDS)) { + pool.shutdownNow(); + if (!pool.awaitTermination(120, TimeUnit.SECONDS)) { + logger.info("Pool did not terminate"); + } + } + } catch (InterruptedException ie) { + pool.shutdownNow(); + Thread.currentThread().interrupt(); + } + } + } + + /** + * 打印线程异常信息 + */ + public static void printException(Runnable r, Throwable t) { + if (t == null && r instanceof Future) { + try { + Future future = (Future) r; + if (future.isDone()) { + future.get(); + } + } catch (CancellationException ce) { + t = ce; + } catch (ExecutionException ee) { + t = ee.getCause(); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + } + } + if (t != null) { + logger.error(t.getMessage(), t); + } + } +} + + +--- File: play-common/src/main/java/com/starry/common/utils/VerificationCodeUtils.java --- +package com.starry.common.utils; + +/** + * @author admin + * @since 2024/4/9 13:53 + **/ +public class VerificationCodeUtils { + + public static String getVerificationCode(int codeLength) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < codeLength; i++) { + sb.append((int) (Math.random() * 10)); + } + return sb.toString(); + } +} + + +--- File: play-common/src/main/java/com/starry/common/utils/file/FileUploadUtils.java --- +package com.starry.common.utils.file; + +import java.util.Objects; +import org.springframework.web.multipart.MultipartFile; + +/** + * @author admin 文件上传工具类 + * @since 2022/10/28 + */ +public class FileUploadUtils { + + /** + * 默认大小 50M + */ + public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024; + + /** + * 默认的文件名最大长度 100 + */ + public static final int DEFAULT_FILE_NAME_LENGTH = 100; + + public static String upload(String baseDir, MultipartFile file, String[] allowedExtension) { + int fileNameLength = Objects.requireNonNull(file.getOriginalFilename()).length(); + if (fileNameLength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) { + throw new RuntimeException("文件名超过默认的最大长度"); + } + return null; + } + +} + + +--- File: play-common/src/main/java/com/starry/common/utils/html/EscapeUtil.java --- +package com.starry.common.utils.html; + +import com.starry.common.utils.StringUtils; + +/** + * 转义和反转义工具类 + * + * @author ruoyi + */ +public class EscapeUtil { + public static final String RE_HTML_MARK = "(<[^<]*?>)|(<[\\s]*?/[^<]*?>)|(<[^<]*?/[\\s]*?>)"; + + private static final char[][] TEXT = new char[64][]; + + static { + for (int i = 0; i < 64; i++) { + TEXT[i] = new char[]{(char) i}; + } + + // special HTML characters + TEXT['\''] = "'".toCharArray(); // 单引号 + TEXT['"'] = """.toCharArray(); // 单引号 + TEXT['&'] = "&".toCharArray(); // &符 + TEXT['<'] = "<".toCharArray(); // 小于号 + TEXT['>'] = ">".toCharArray(); // 大于号 + } + + /** + * 转义文本中的HTML字符为安全的字符 + * + * @param text + * 被转义的文本 + * @return 转义后的文本 + */ + public static String escape(String text) { + return encode(text); + } + + /** + * 还原被转义的HTML特殊字符 + * + * @param content + * 包含转义符的HTML内容 + * @return 转换后的字符串 + */ + public static String unescape(String content) { + return decode(content); + } + + /** + * 清除所有HTML标签,但是不删除标签内的内容 + * + * @param content + * 文本 + * @return 清除标签后的文本 + */ + public static String clean(String content) { + return new HTMLFilter().filter(content); + } + + /** + * Escape编码 + * + * @param text + * 被编码的文本 + * @return 编码后的字符 + */ + private static String encode(String text) { + int len; + if ((text == null) || ((len = text.length()) == 0)) { + return StringUtils.EMPTY; + } + StringBuilder buffer = new StringBuilder(len + (len >> 2)); + char c; + for (int i = 0; i < len; i++) { + c = text.charAt(i); + if (c < 64) { + buffer.append(TEXT[c]); + } else { + buffer.append(c); + } + } + return buffer.toString(); + } + + /** + * Escape解码 + * + * @param content + * 被转义的内容 + * @return 解码后的字符串 + */ + public static String decode(String content) { + if (StringUtils.isEmpty(content)) { + return content; + } + + StringBuilder tmp = new StringBuilder(content.length()); + int lastPos = 0, pos = 0; + char ch; + while (lastPos < content.length()) { + pos = content.indexOf("%", lastPos); + if (pos == lastPos) { + if (content.charAt(pos + 1) == 'u') { + ch = (char) Integer.parseInt(content.substring(pos + 2, pos + 6), 16); + tmp.append(ch); + lastPos = pos + 6; + } else { + ch = (char) Integer.parseInt(content.substring(pos + 1, pos + 3), 16); + tmp.append(ch); + lastPos = pos + 3; + } + } else { + if (pos == -1) { + tmp.append(content.substring(lastPos)); + lastPos = content.length(); + } else { + tmp.append(content, lastPos, pos); + lastPos = pos; + } + } + } + return tmp.toString(); + } + + public static void main(String[] args) { + String html = ""; + // String html = "ipt>alert(\"XSS\")ipt>"; + // String html = "<123"; + // String html = "123>"; + System.out.println(EscapeUtil.clean(html)); + System.out.println(EscapeUtil.escape(html)); + System.out.println(EscapeUtil.unescape(html)); + } +} + + +--- File: play-common/src/main/java/com/starry/common/utils/html/HTMLFilter.java --- +package com.starry.common.utils.html; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * HTML过滤器,用于去除XSS漏洞隐患。 + * + * @author ruoyi + */ +public final class HTMLFilter { + /** + * regex flag union representing /si modifiers in php + **/ + private static final int REGEX_FLAGS_SI = Pattern.CASE_INSENSITIVE | Pattern.DOTALL; + private static final Pattern P_COMMENTS = Pattern.compile("", Pattern.DOTALL); + private static final Pattern P_COMMENT = Pattern.compile("^!--(.*)--$", REGEX_FLAGS_SI); + private static final Pattern P_TAGS = Pattern.compile("<(.*?)>", Pattern.DOTALL); + private static final Pattern P_END_TAG = Pattern.compile("^/([a-z0-9]+)", REGEX_FLAGS_SI); + private static final Pattern P_START_TAG = Pattern.compile("^([a-z0-9]+)(.*?)(/?)$", REGEX_FLAGS_SI); + private static final Pattern P_QUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)=([\"'])(.*?)\\2", REGEX_FLAGS_SI); + private static final Pattern P_UNQUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)(=)([^\"\\s']+)", REGEX_FLAGS_SI); + private static final Pattern P_PROTOCOL = Pattern.compile("^([^:]+):", REGEX_FLAGS_SI); + private static final Pattern P_ENTITY = Pattern.compile("&#(\\d+);?"); + private static final Pattern P_ENTITY_UNICODE = Pattern.compile("&#x([0-9a-f]+);?"); + private static final Pattern P_ENCODE = Pattern.compile("%([0-9a-f]{2});?"); + private static final Pattern P_VALID_ENTITIES = Pattern.compile("&([^&;]*)(?=(;|&|$))"); + private static final Pattern P_VALID_QUOTES = Pattern.compile("(>|^)([^<]+?)(<|$)", Pattern.DOTALL); + private static final Pattern P_END_ARROW = Pattern.compile("^>"); + private static final Pattern P_BODY_TO_END = Pattern.compile("<([^>]*?)(?=<|$)"); + private static final Pattern P_XML_CONTENT = Pattern.compile("(^|>)([^<]*?)(?=>)"); + private static final Pattern P_STRAY_LEFT_ARROW = Pattern.compile("<([^>]*?)(?=<|$)"); + private static final Pattern P_STRAY_RIGHT_ARROW = Pattern.compile("(^|>)([^<]*?)(?=>)"); + private static final Pattern P_AMP = Pattern.compile("&"); + private static final Pattern P_QUOTE = Pattern.compile("\""); + private static final Pattern P_LEFT_ARROW = Pattern.compile("<"); + private static final Pattern P_RIGHT_ARROW = Pattern.compile(">"); + private static final Pattern P_BOTH_ARROWS = Pattern.compile("<>"); + + // @xxx could grow large... maybe use sesat's ReferenceMap + private static final ConcurrentMap P_REMOVE_PAIR_BLANKS = new ConcurrentHashMap<>(); + private static final ConcurrentMap P_REMOVE_SELF_BLANKS = new ConcurrentHashMap<>(); + + /** + * set of allowed html elements, along with allowed attributes for each element + **/ + private final Map> vAllowed; + /** + * counts of open tags for each (allowable) html element + **/ + private final Map vTagCounts = new HashMap<>(); + + /** + * html elements which must always be self-closing (e.g. "") + **/ + private final String[] vSelfClosingTags; + /** + * html elements which must always have separate opening and closing tags (e.g. + * "") + **/ + private final String[] vNeedClosingTags; + /** + * set of disallowed html elements + **/ + private final String[] vDisallowed; + /** + * attributes which should be checked for valid protocols + **/ + private final String[] vProtocolAtts; + /** + * allowed protocols + **/ + private final String[] vAllowedProtocols; + /** + * tags which should be removed if they contain no content (e.g. "" or + * "") + **/ + private final String[] vRemoveBlanks; + /** + * entities allowed within html markup + **/ + private final String[] vAllowedEntities; + /** + * flag determining whether comments are allowed in input String. + */ + private final boolean stripComment; + private final boolean encodeQuotes; + /** + * flag determining whether to try to make tags when presented with "unbalanced" + * angle brackets (e.g. "" becomes " text "). If set to + * false, unbalanced angle brackets will be html escaped. + */ + private final boolean alwaysMakeTags; + + /** + * Default constructor. + */ + public HTMLFilter() { + vAllowed = new HashMap<>(); + + final ArrayList a_atts = new ArrayList<>(); + a_atts.add("href"); + a_atts.add("target"); + vAllowed.put("a", a_atts); + + final ArrayList img_atts = new ArrayList<>(); + img_atts.add("src"); + img_atts.add("width"); + img_atts.add("height"); + img_atts.add("alt"); + vAllowed.put("img", img_atts); + + final ArrayList no_atts = new ArrayList<>(); + vAllowed.put("b", no_atts); + vAllowed.put("strong", no_atts); + vAllowed.put("i", no_atts); + vAllowed.put("em", no_atts); + + vSelfClosingTags = new String[]{"img"}; + vNeedClosingTags = new String[]{"a", "b", "strong", "i", "em"}; + vDisallowed = new String[]{}; + vAllowedProtocols = new String[]{"http", "mailto", "https"}; // no ftp. + vProtocolAtts = new String[]{"src", "href"}; + vRemoveBlanks = new String[]{"a", "b", "strong", "i", "em"}; + vAllowedEntities = new String[]{"amp", "gt", "lt", "quot"}; + stripComment = true; + encodeQuotes = true; + alwaysMakeTags = false; + } + + /** + * Map-parameter configurable constructor. + * + * @param conf + * map containing configuration. keys match field names. + */ + @SuppressWarnings("unchecked") + public HTMLFilter(final Map conf) { + + assert conf.containsKey("vAllowed") : "configuration requires vAllowed"; + assert conf.containsKey("vSelfClosingTags") : "configuration requires vSelfClosingTags"; + assert conf.containsKey("vNeedClosingTags") : "configuration requires vNeedClosingTags"; + assert conf.containsKey("vDisallowed") : "configuration requires vDisallowed"; + assert conf.containsKey("vAllowedProtocols") : "configuration requires vAllowedProtocols"; + assert conf.containsKey("vProtocolAtts") : "configuration requires vProtocolAtts"; + assert conf.containsKey("vRemoveBlanks") : "configuration requires vRemoveBlanks"; + assert conf.containsKey("vAllowedEntities") : "configuration requires vAllowedEntities"; + + vAllowed = Collections.unmodifiableMap((HashMap>) conf.get("vAllowed")); + vSelfClosingTags = (String[]) conf.get("vSelfClosingTags"); + vNeedClosingTags = (String[]) conf.get("vNeedClosingTags"); + vDisallowed = (String[]) conf.get("vDisallowed"); + vAllowedProtocols = (String[]) conf.get("vAllowedProtocols"); + vProtocolAtts = (String[]) conf.get("vProtocolAtts"); + vRemoveBlanks = (String[]) conf.get("vRemoveBlanks"); + vAllowedEntities = (String[]) conf.get("vAllowedEntities"); + stripComment = conf.containsKey("stripComment") ? (Boolean) conf.get("stripComment") : true; + encodeQuotes = conf.containsKey("encodeQuotes") ? (Boolean) conf.get("encodeQuotes") : true; + alwaysMakeTags = conf.containsKey("alwaysMakeTags") ? (Boolean) conf.get("alwaysMakeTags") : true; + } + + // --------------------------------------------------------------- + // my versions of some PHP library functions + public static String chr(final int decimal) { + return String.valueOf((char) decimal); + } + + public static String htmlSpecialChars(final String s) { + String result = s; + result = regexReplace(P_AMP, "&", result); + result = regexReplace(P_QUOTE, """, result); + result = regexReplace(P_LEFT_ARROW, "<", result); + result = regexReplace(P_RIGHT_ARROW, ">", result); + return result; + } + + private static String regexReplace(final Pattern regex_pattern, final String replacement, final String s) { + Matcher m = regex_pattern.matcher(s); + return m.replaceAll(replacement); + } + + // --------------------------------------------------------------- + + private static boolean inArray(final String s, final String[] array) { + for (String item : array) { + if (item != null && item.equals(s)) { + return true; + } + } + return false; + } + + private void reset() { + vTagCounts.clear(); + } + + /** + * given a user submitted input String, filter out any invalid or restricted + * html. + * + * @param input + * text (i.e. submitted by a user) than may contain html + * @return "clean" version of input, with only valid, whitelisted html elements + * allowed + */ + public String filter(final String input) { + reset(); + String s = input; + + s = escapeComments(s); + + s = balanceHTML(s); + + s = checkTags(s); + + s = processRemoveBlanks(s); + + // s = validateEntities(s); + + return s; + } + + public boolean isAlwaysMakeTags() { + return alwaysMakeTags; + } + + public boolean isStripComments() { + return stripComment; + } + + private String escapeComments(final String s) { + final Matcher m = P_COMMENTS.matcher(s); + final StringBuffer buf = new StringBuffer(); + if (m.find()) { + final String match = m.group(1); // (.*?) + m.appendReplacement(buf, Matcher.quoteReplacement("")); + } + m.appendTail(buf); + + return buf.toString(); + } + + private String balanceHTML(String s) { + if (alwaysMakeTags) { + // + // try and form html + // + s = regexReplace(P_END_ARROW, "", s); + // 不追加结束标签 + s = regexReplace(P_BODY_TO_END, "<$1>", s); + s = regexReplace(P_XML_CONTENT, "$1<$2", s); + + } else { + // + // escape stray brackets + // + s = regexReplace(P_STRAY_LEFT_ARROW, "<$1", s); + s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2><", s); + + // + // the last regexp causes '<>' entities to appear + // (we need to do a lookahead assertion so that the last bracket can + // be used in the next pass of the regexp) + // + s = regexReplace(P_BOTH_ARROWS, "", s); + } + + return s; + } + + private String checkTags(String s) { + Matcher m = P_TAGS.matcher(s); + + final StringBuffer buf = new StringBuffer(); + while (m.find()) { + String replaceStr = m.group(1); + replaceStr = processTag(replaceStr); + m.appendReplacement(buf, Matcher.quoteReplacement(replaceStr)); + } + m.appendTail(buf); + + // these get tallied in processTag + // (remember to reset before subsequent calls to filter method) + final StringBuilder sBuilder = new StringBuilder(buf.toString()); + for (String key : vTagCounts.keySet()) { + for (int ii = 0; ii < vTagCounts.get(key); ii++) { + sBuilder.append(""); + } + } + s = sBuilder.toString(); + + return s; + } + + private String processRemoveBlanks(final String s) { + String result = s; + for (String tag : vRemoveBlanks) { + if (!P_REMOVE_PAIR_BLANKS.containsKey(tag)) { + P_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?>")); + } + result = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), "", result); + if (!P_REMOVE_SELF_BLANKS.containsKey(tag)) { + P_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?/>")); + } + result = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), "", result); + } + + return result; + } + + private String processTag(final String s) { + // ending tags + Matcher m = P_END_TAG.matcher(s); + if (m.find()) { + final String name = m.group(1).toLowerCase(); + if (allowed(name)) { + if (false == inArray(name, vSelfClosingTags)) { + if (vTagCounts.containsKey(name)) { + vTagCounts.put(name, vTagCounts.get(name) - 1); + return ""; + } + } + } + } + + // starting tags + m = P_START_TAG.matcher(s); + if (m.find()) { + final String name = m.group(1).toLowerCase(); + final String body = m.group(2); + String ending = m.group(3); + + // debug( "in a starting tag, name='" + name + "'; body='" + body + "'; + // ending='" + ending + "'" ); + if (allowed(name)) { + final StringBuilder params = new StringBuilder(); + + final Matcher m2 = P_QUOTED_ATTRIBUTES.matcher(body); + final Matcher m3 = P_UNQUOTED_ATTRIBUTES.matcher(body); + final List paramNames = new ArrayList<>(); + final List paramValues = new ArrayList<>(); + while (m2.find()) { + paramNames.add(m2.group(1)); // ([a-z0-9]+) + paramValues.add(m2.group(3)); // (.*?) + } + while (m3.find()) { + paramNames.add(m3.group(1)); // ([a-z0-9]+) + paramValues.add(m3.group(3)); // ([^\"\\s']+) + } + + String paramName, paramValue; + for (int ii = 0; ii < paramNames.size(); ii++) { + paramName = paramNames.get(ii).toLowerCase(); + paramValue = paramValues.get(ii); + + // debug( "paramName='" + paramName + "'" ); + // debug( "paramValue='" + paramValue + "'" ); + // debug( "allowed? " + vAllowed.get( name ).contains( paramName ) ); + + if (allowedAttribute(name, paramName)) { + if (inArray(paramName, vProtocolAtts)) { + paramValue = processParamProtocol(paramValue); + } + params.append(' ').append(paramName).append("=\"").append(paramValue).append("\""); + } + } + + if (inArray(name, vSelfClosingTags)) { + ending = " /"; + } + + if (inArray(name, vNeedClosingTags)) { + ending = ""; + } + + if (ending == null || ending.isEmpty()) { + if (vTagCounts.containsKey(name)) { + vTagCounts.put(name, vTagCounts.get(name) + 1); + } else { + vTagCounts.put(name, 1); + } + } else { + ending = " /"; + } + return "<" + name + params + ending + ">"; + } else { + return ""; + } + } + + // comments + m = P_COMMENT.matcher(s); + if (!stripComment && m.find()) { + return "<" + m.group() + ">"; + } + + return ""; + } + + private String processParamProtocol(String s) { + s = decodeEntities(s); + final Matcher m = P_PROTOCOL.matcher(s); + if (m.find()) { + final String protocol = m.group(1); + if (!inArray(protocol, vAllowedProtocols)) { + // bad protocol, turn into local anchor link instead + s = "#" + s.substring(protocol.length() + 1); + if (s.startsWith("#//")) { + s = "#" + s.substring(3); + } + } + } + + return s; + } + + private String decodeEntities(String s) { + StringBuffer buf = new StringBuffer(); + + Matcher m = P_ENTITY.matcher(s); + while (m.find()) { + final String match = m.group(1); + final int decimal = Integer.decode(match); + m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); + } + m.appendTail(buf); + s = buf.toString(); + + buf = new StringBuffer(); + m = P_ENTITY_UNICODE.matcher(s); + while (m.find()) { + final String match = m.group(1); + final int decimal = Integer.valueOf(match, 16); + m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); + } + m.appendTail(buf); + s = buf.toString(); + + buf = new StringBuffer(); + m = P_ENCODE.matcher(s); + while (m.find()) { + final String match = m.group(1); + final int decimal = Integer.valueOf(match, 16); + m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); + } + m.appendTail(buf); + s = buf.toString(); + + s = validateEntities(s); + return s; + } + + private String validateEntities(final String s) { + StringBuffer buf = new StringBuffer(); + + // validate entities throughout the string + Matcher m = P_VALID_ENTITIES.matcher(s); + while (m.find()) { + final String one = m.group(1); // ([^&;]*) + final String two = m.group(2); // (?=(;|&|$)) + m.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two))); + } + m.appendTail(buf); + + return encodeQuotes(buf.toString()); + } + + private String encodeQuotes(final String s) { + if (encodeQuotes) { + StringBuffer buf = new StringBuffer(); + Matcher m = P_VALID_QUOTES.matcher(s); + while (m.find()) { + final String one = m.group(1); // (>|^) + final String two = m.group(2); // ([^<]+?) + final String three = m.group(3); // (<|$) + // 不替换双引号为",防止json格式无效 regexReplace(P_QUOTE, """, two) + m.appendReplacement(buf, Matcher.quoteReplacement(one + two + three)); + } + m.appendTail(buf); + return buf.toString(); + } else { + return s; + } + } + + private String checkEntity(final String preamble, final String term) { + + return ";".equals(term) && isValidEntity(preamble) ? '&' + preamble : "&" + preamble; + } + + private boolean isValidEntity(final String entity) { + return inArray(entity, vAllowedEntities); + } + + private boolean allowed(final String name) { + return (vAllowed.isEmpty() || vAllowed.containsKey(name)) && !inArray(name, vDisallowed); + } + + private boolean allowedAttribute(final String name, final String paramName) { + return allowed(name) && (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName)); + } +} + + +--- File: play-common/src/main/java/com/starry/common/utils/http/HttpHelper.java --- +package com.starry.common.utils.http; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import javax.servlet.ServletRequest; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * 通用http工具封装 + * + * @author ruoyi + */ +public class HttpHelper { + private static final Logger LOGGER = LoggerFactory.getLogger(HttpHelper.class); + + public static String getBodyString(ServletRequest request) { + StringBuilder sb = new StringBuilder(); + BufferedReader reader = null; + try (InputStream inputStream = request.getInputStream()) { + reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); + String line = ""; + while ((line = reader.readLine()) != null) { + sb.append(line); + } + } catch (IOException e) { + LOGGER.warn("getBodyString出现问题!"); + } finally { + if (reader != null) { + try { + reader.close(); + } catch (IOException e) { + LOGGER.error(ExceptionUtils.getMessage(e)); + } + } + } + return sb.toString(); + } +} + + +--- File: play-common/src/main/java/com/starry/common/utils/http/HttpUtils.java --- +package com.starry.common.utils.http; + +import com.starry.common.constant.Constants; +import java.io.*; +import java.net.ConnectException; +import java.net.SocketTimeoutException; +import java.net.URL; +import java.net.URLConnection; +import java.nio.charset.StandardCharsets; +import java.security.cert.X509Certificate; +import javax.net.ssl.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * 通用http发送方法 + * + * @author ruoyi + */ +public class HttpUtils { + private static final Logger log = LoggerFactory.getLogger(HttpUtils.class); + + /** + * 向指定 URL 发送GET方法的请求 + * + * @param url + * 发送请求的 URL + * @param param + * 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 + * @return 所代表远程资源的响应结果 + */ + public static String sendGet(String url, String param) { + return sendGet(url, param, Constants.UTF8); + } + + /** + * 向指定 URL 发送GET方法的请求 + * + * @param url + * 发送请求的 URL + * @param param + * 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 + * @param contentType + * 编码类型 + * @return 所代表远程资源的响应结果 + */ + public static String sendGet(String url, String param, String contentType) { + StringBuilder result = new StringBuilder(); + BufferedReader in = null; + try { + String urlNameString = url + "?" + param; + log.info("sendGet - {}", urlNameString); + URL realUrl = new URL(urlNameString); + URLConnection connection = realUrl.openConnection(); + connection.setRequestProperty("accept", "*/*"); + connection.setRequestProperty("connection", "Keep-Alive"); + connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + connection.connect(); + in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType)); + String line; + while ((line = in.readLine()) != null) { + result.append(line); + } + log.info("recv - {}", result); + } catch (ConnectException e) { + log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e); + } catch (SocketTimeoutException e) { + log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e); + } catch (IOException e) { + log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e); + } catch (Exception e) { + log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e); + } finally { + try { + if (in != null) { + in.close(); + } + } catch (Exception ex) { + log.error("调用in.close Exception, url=" + url + ",param=" + param, ex); + } + } + return result.toString(); + } + + /** + * 向指定 URL 发送POST方法的请求 + * + * @param url + * 发送请求的 URL + * @param param + * 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 + * @return 所代表远程资源的响应结果 + */ + public static String sendPost(String url, String param) { + PrintWriter out = null; + BufferedReader in = null; + StringBuilder result = new StringBuilder(); + try { + log.info("sendPost - {}", url); + URL realUrl = new URL(url); + URLConnection conn = realUrl.openConnection(); + conn.setRequestProperty("accept", "*/*"); + conn.setRequestProperty("connection", "Keep-Alive"); + conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + conn.setRequestProperty("Accept-Charset", "utf-8"); + conn.setRequestProperty("contentType", "utf-8"); + conn.setDoOutput(true); + conn.setDoInput(true); + out = new PrintWriter(conn.getOutputStream()); + out.print(param); + out.flush(); + in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8)); + String line; + while ((line = in.readLine()) != null) { + result.append(line); + } + log.info("recv - {}", result); + } catch (ConnectException e) { + log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e); + } catch (SocketTimeoutException e) { + log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e); + } catch (IOException e) { + log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e); + } catch (Exception e) { + log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e); + } finally { + try { + if (out != null) { + out.close(); + } + if (in != null) { + in.close(); + } + } catch (IOException ex) { + log.error("调用in.close Exception, url=" + url + ",param=" + param, ex); + } + } + return result.toString(); + } + + public static String sendSSLPost(String url, String param) { + StringBuilder result = new StringBuilder(); + String urlNameString = url + "?" + param; + try { + log.info("sendSSLPost - {}", urlNameString); + SSLContext sc = SSLContext.getInstance("SSL"); + sc.init(null, new TrustManager[]{new TrustAnyTrustManager()}, new java.security.SecureRandom()); + URL console = new URL(urlNameString); + HttpsURLConnection conn = (HttpsURLConnection) console.openConnection(); + conn.setRequestProperty("accept", "*/*"); + conn.setRequestProperty("connection", "Keep-Alive"); + conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + conn.setRequestProperty("Accept-Charset", "utf-8"); + conn.setRequestProperty("contentType", "utf-8"); + conn.setDoOutput(true); + conn.setDoInput(true); + + conn.setSSLSocketFactory(sc.getSocketFactory()); + conn.setHostnameVerifier(new TrustAnyHostnameVerifier()); + conn.connect(); + InputStream is = conn.getInputStream(); + BufferedReader br = new BufferedReader(new InputStreamReader(is)); + String ret = ""; + while ((ret = br.readLine()) != null) { + if (!ret.trim().isEmpty()) { + result.append(new String(ret.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8)); + } + } + log.info("recv - {}", result); + conn.disconnect(); + br.close(); + } catch (ConnectException e) { + log.error("调用HttpUtils.sendSSLPost ConnectException, url=" + url + ",param=" + param, e); + } catch (SocketTimeoutException e) { + log.error("调用HttpUtils.sendSSLPost SocketTimeoutException, url=" + url + ",param=" + param, e); + } catch (IOException e) { + log.error("调用HttpUtils.sendSSLPost IOException, url=" + url + ",param=" + param, e); + } catch (Exception e) { + log.error("调用HttpsUtil.sendSSLPost Exception, url=" + url + ",param=" + param, e); + } + return result.toString(); + } + + private static class TrustAnyTrustManager implements X509TrustManager { + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) { + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) { + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[]{}; + } + } + + private static class TrustAnyHostnameVerifier implements HostnameVerifier { + @Override + public boolean verify(String hostname, SSLSession session) { + return true; + } + } +} + + +--- File: play-common/src/main/java/com/starry/common/utils/ip/AddressUtils.java --- +package com.starry.common.utils.ip; + +import com.starry.common.utils.RegionUtils; +import com.starry.common.utils.StringUtils; +import lombok.extern.slf4j.Slf4j; + +/** + * @author admin 获取地址工具类 + * @since 2022/7/25 + */ +@Slf4j +public class AddressUtils { + + /** + * 未知地址 + **/ + public static final String UNKNOWN = "XX XX"; + + public static String getRealAddressByIp(String ip) { + if ("127.0.0.1".equals(ip) || "0:0:0:0:0:0:0:1".equals(ip)) { + return "内网IP"; + } + try { + String rspStr = RegionUtils.getRegion(ip); + if (StringUtils.isEmpty(rspStr)) { + log.error("获取地理位置异常 {}", ip); + return UNKNOWN; + } + String[] obj = rspStr.split("\\|"); + String region = obj[2]; + String city = obj[3]; + return String.format("%s %s", region, city); + } catch (Exception e) { + log.error("获取地理位置异常", e); + } + return UNKNOWN; + } +} + + +--- File: play-common/src/main/java/com/starry/common/utils/ip/IpUtils.java --- +package com.starry.common.utils.ip; + +import com.starry.common.utils.StringUtils; +import java.net.InetAddress; +import java.net.UnknownHostException; +import javax.servlet.http.HttpServletRequest; + +/** + * 获取IP方法 + * + * @author ruoyi + */ +public class IpUtils { + /** + * 获取客户端IP + * + * @param request + * 请求对象 + * @return IP地址 + */ + public static String getIpAddr(HttpServletRequest request) { + if (request == null) { + return "unknown"; + } + String ip = request.getHeader("x-forwarded-for"); + if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("X-Forwarded-For"); + } + if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("X-Real-IP"); + } + + if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + + return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : getMultistageReverseProxyIp(ip); + } + + /** + * 检查是否为内部IP地址 + * + * @param ip + * IP地址 + * @return 结果 + */ + public static boolean internalIp(String ip) { + byte[] addr = textToNumericFormatV4(ip); + return internalIp(addr) || "127.0.0.1".equals(ip); + } + + /** + * 检查是否为内部IP地址 + * + * @param addr + * byte地址 + * @return 结果 + */ + private static boolean internalIp(byte[] addr) { + if (StringUtils.isNull(addr) || addr.length < 2) { + return true; + } + final byte b0 = addr[0]; + final byte b1 = addr[1]; + // 10.x.x.x/8 + final byte SECTION_1 = 0x0A; + // 172.16.x.x/12 + final byte SECTION_2 = (byte) 0xAC; + final byte SECTION_3 = (byte) 0x10; + final byte SECTION_4 = (byte) 0x1F; + // 192.168.x.x/16 + final byte SECTION_5 = (byte) 0xC0; + final byte SECTION_6 = (byte) 0xA8; + switch (b0) { + case SECTION_1 : + return true; + case SECTION_2 : + if (b1 >= SECTION_3 && b1 <= SECTION_4) { + return true; + } + case SECTION_5 : + switch (b1) { + case SECTION_6 : + return true; + } + default : + return false; + } + } + + /** + * 将IPv4地址转换成字节 + * + * @param text + * IPv4地址 + * @return byte 字节 + */ + public static byte[] textToNumericFormatV4(String text) { + if (text.isEmpty()) { + return null; + } + + byte[] bytes = new byte[4]; + String[] elements = text.split("\\.", -1); + try { + long l; + int i; + switch (elements.length) { + case 1 : + l = Long.parseLong(elements[0]); + if ((l < 0L) || (l > 4294967295L)) { + return null; + } + bytes[0] = (byte) (int) (l >> 24 & 0xFF); + bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF); + bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF); + bytes[3] = (byte) (int) (l & 0xFF); + break; + case 2 : + l = Integer.parseInt(elements[0]); + if ((l < 0L) || (l > 255L)) { + return null; + } + bytes[0] = (byte) (int) (l & 0xFF); + l = Integer.parseInt(elements[1]); + if ((l < 0L) || (l > 16777215L)) { + return null; + } + bytes[1] = (byte) (int) (l >> 16 & 0xFF); + bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF); + bytes[3] = (byte) (int) (l & 0xFF); + break; + case 3 : + for (i = 0; i < 2; ++i) { + l = Integer.parseInt(elements[i]); + if ((l < 0L) || (l > 255L)) { + return null; + } + bytes[i] = (byte) (int) (l & 0xFF); + } + l = Integer.parseInt(elements[2]); + if ((l < 0L) || (l > 65535L)) { + return null; + } + bytes[2] = (byte) (int) (l >> 8 & 0xFF); + bytes[3] = (byte) (int) (l & 0xFF); + break; + case 4 : + for (i = 0; i < 4; ++i) { + l = Integer.parseInt(elements[i]); + if ((l < 0L) || (l > 255L)) { + return null; + } + bytes[i] = (byte) (int) (l & 0xFF); + } + break; + default : + return null; + } + } catch (NumberFormatException e) { + return null; + } + return bytes; + } + + /** + * 获取IP地址 + * + * @return 本地IP地址 + */ + public static String getHostIp() { + try { + return InetAddress.getLocalHost().getHostAddress(); + } catch (UnknownHostException e) { + } + return "127.0.0.1"; + } + + /** + * 获取主机名 + * + * @return 本地主机名 + */ + public static String getHostName() { + try { + return InetAddress.getLocalHost().getHostName(); + } catch (UnknownHostException e) { + } + return "未知"; + } + + /** + * 从多级反向代理中获得第一个非unknown IP地址 + * + * @param ip + * 获得的IP地址 + * @return 第一个非unknown IP地址 + */ + public static String getMultistageReverseProxyIp(String ip) { + // 多级反向代理检测 + if (ip != null && ip.indexOf(",") > 0) { + final String[] ips = ip.trim().split(","); + for (String subIp : ips) { + if (false == isUnknown(subIp)) { + ip = subIp; + break; + } + } + } + return ip; + } + + /** + * 检测给定字符串是否为未知,多用于检测HTTP请求相关 + * + * @param checkString + * 被检测的字符串 + * @return 是否未知 + */ + public static boolean isUnknown(String checkString) { + return StringUtils.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString); + } +} + + +--- File: play-generator/README.md --- +# Play Generator - 代码生成器 + +这是一个独立的代码生成器工具,可以通过 main 方法直接运行生成代码。 + +## 功能特性 + +- 支持 MySQL 数据库表结构读取 +- 自动生成 Entity、Mapper、Service、Controller 等代码文件 +- 基于 Velocity 模板引擎 +- 支持批量生成多个表 +- 可自定义输出目录和包名 + +## 使用方法 + +提供两种方式来使用代码生成器: + +### 方式一:使用配置文件(推荐) + +#### 1. 修改配置文件 + +编辑 `src/main/resources/config.properties` 文件: + +```properties +# 数据库配置 +db.url=jdbc:mysql://localhost:3306/your_database?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai +db.driver=com.mysql.cj.jdbc.Driver +db.username=your_username +db.password=your_password + +# 代码生成配置 +gen.author=your_name +gen.packageName=com.your.package +gen.outputDir=./generated-code +gen.autoRemovePre=false +gen.tablePrefix=sys_ +gen.tplCategory=crud + +# 要生成的表名,多个表名用逗号分隔 +gen.tableNames=your_table1,your_table2,your_table3 +``` + +#### 2. 运行生成器 + +直接运行 `MainGeneratorWithConfig.main()` 方法或使用脚本: +- Windows: 双击 `run.bat` +- Linux/Mac: 执行 `./run.sh` + +### 方式二:代码配置 + +#### 1. 配置数据库连接 + +编辑 `MainGenerator.java` 文件中的数据库配置: + +```java +// 数据库配置 +GeneratorConfig config = new GeneratorConfig(); +config.setUrl("jdbc:mysql://localhost:3306/your_database?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai"); +config.setDriverName("com.mysql.cj.jdbc.Driver"); +config.setUsername("your_username"); +config.setPassword("your_password"); +``` + +#### 2. 配置生成参数 + +```java +// 生成配置 +config.setAuthor("your_name"); +config.setPackageName("com.your.package"); +config.setOutputDir("./generated-code"); +config.setAutoRemovePre(false); +config.setTablePrefix("sys_"); +``` + +#### 3. 指定要生成的表名 + +```java +// 要生成的表名(可以配置多个) +String[] tableNames = { + "your_table1", + "your_table2", + "your_table3" +}; +``` + +### 4. 运行生成器 + +#### 方式一:通过 Maven 运行 +```bash +mvn clean compile exec:java +``` + +#### 方式二:通过 IDE 运行 +直接运行 `MainGenerator.main()` 方法 + +#### 方式三:打包后运行 +```bash +mvn clean package +java -cp target/classes:target/lib/* com.starry.generator.MainGenerator +``` + +## 生成的代码结构 + +``` +generated-code/ +├── src/main/java/com/your/package/ +│ ├── entity/ # 实体类 +│ ├── mapper/ # Mapper 接口 +│ ├── service/ # Service 接口 +│ ├── service/impl/ # Service 实现类 +│ └── controller/ # Controller 类 +└── src/main/resources/ + └── mapper/ # MyBatis XML 文件 +``` + +## 配置参数说明 + +| 参数 | 说明 | 默认值 | +|------|------|--------| +| url | 数据库连接地址 | - | +| driverName | 数据库驱动类名 | com.mysql.cj.jdbc.Driver | +| username | 数据库用户名 | - | +| password | 数据库密码 | - | +| author | 代码作者 | admin | +| packageName | 生成代码的包名 | com.starry.play | +| outputDir | 代码输出目录 | ./generated-code | +| autoRemovePre | 是否自动移除表前缀 | false | +| tablePrefix | 表前缀 | sys_ | +| tplCategory | 模板类型(crud/tree/sub) | crud | + +## 注意事项 + +1. **重要**:首次使用前,请修改 `src/main/resources/config.properties` 文件中的数据库连接信息 +2. 确保数据库连接正常,数据库服务器可访问 +3. 确保指定的表存在于数据库中 +4. 生成的代码会覆盖同名文件,请注意备份 +5. 支持的数据库类型:MySQL 5.7+ +6. 确保数据库用户有足够的权限读取表结构信息 + +## 常见问题 + +### Q: 如何自定义模板? +A: 模板文件位于 `src/main/resources/vm/` 目录下,可以根据需要修改 `.vm` 文件。 + +### Q: 如何修改生成的文件结构? +A: 修改 `CodeGenerator.getFileName()` 方法中的文件路径逻辑。 + +### Q: 支持其他数据库吗? +A: 目前只支持 MySQL,如需支持其他数据库,需要修改 SQL 查询语句和驱动配置。 + +--- File: play-generator/pom.xml --- + + + 4.0.0 + + com.starry + play-with + 1.0 + + + play-generator + + + 11 + 11 + UTF-8 + + + + + + + org.apache.velocity + velocity-engine-core + + + + + com.starry + play-common + 1.0 + + + + + org.springframework.boot + spring-boot-starter-validation + + + + + org.projectlombok + lombok + 1.18.30 + provided + + + + org.projectlombok + lombok-mapstruct-binding + 0.2.0 + + + + + mysql + mysql-connector-java + 8.0.33 + + + + + ch.qos.logback + logback-classic + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +--- File: play-generator/run.bat --- +@echo off +echo 开始编译和运行代码生成器... +mvn clean compile exec:java +pause + +--- File: play-generator/run.sh --- +#!/bin/bash +echo "开始编译和运行代码生成器..." +mvn clean compile exec:java + +--- File: play-generator/src/main/java/com/starry/generator/MainGenerator.java --- +package com.starry.generator; + +import com.starry.generator.config.GeneratorConfig; +import com.starry.generator.core.CodeGenerator; + +/** + * 代码生成器主类 通过main方法直接运行生成代码 + * + * @author admin + * @since 2024-01-01 + */ +public class MainGenerator { + + public static void main(String[] args) { + // 数据库配置 + GeneratorConfig config = new GeneratorConfig(); + config.setUrl( + "jdbc:mysql://122.51.20.105:3306/play-with?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai"); + config.setDriverName("com.mysql.cj.jdbc.Driver"); + config.setUsername("root"); + config.setPassword("KdaKRZ2trpdhNePa"); + + // 生成配置 + config.setAuthor("huchuansai"); + config.setPackageName("com.starry.admin"); + config.setOutputDir("./generated-code"); + config.setAutoRemovePre(false); + config.setTablePrefix("sys_"); + + // 要生成的表名(可以配置多个) + String[] tableNames = {"sys_role",}; + + // 创建代码生成器并执行生成 + CodeGenerator generator = new CodeGenerator(config); + + try { + System.out.println("开始生成代码..."); + generator.generateCode(tableNames); + System.out.println("代码生成完成!输出目录:" + config.getOutputDir()); + } catch (Exception e) { + System.err.println("代码生成失败:" + e.getMessage()); + e.printStackTrace(); + } + } +} + + +--- File: play-generator/src/main/java/com/starry/generator/MainGeneratorWithConfig.java --- +package com.starry.generator; + +import com.starry.generator.config.GeneratorConfig; +import com.starry.generator.core.CodeGenerator; +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +/** + * 代码生成器主类 - 支持配置文件版本 通过读取 config.properties 配置文件来生成代码 + * + * @author admin + * @since 2024-01-01 + */ +public class MainGeneratorWithConfig { + + public static void main(String[] args) { + try { + // 读取配置文件 + GeneratorConfig config = loadConfig(); + + // 获取要生成的表名 + String tableNamesStr = getProperty("gen.tableNames", ""); + if (tableNamesStr.isEmpty()) { + System.err.println("错误:未配置要生成的表名,请在 config.properties 中设置 gen.tableNames"); + return; + } + String[] tableNames = tableNamesStr.split(","); + + // 清理表名(去除前后空格) + for (int i = 0; i < tableNames.length; i++) { + tableNames[i] = tableNames[i].trim(); + } + + // 创建代码生成器并执行生成 + CodeGenerator generator = new CodeGenerator(config); + + System.out.println("=== 代码生成器配置信息 ==="); + System.out.println("数据库地址: " + config.getUrl()); + System.out.println("包名: " + config.getPackageName()); + System.out.println("输出目录: " + config.getOutputDir()); + System.out.println("作者: " + config.getAuthor()); + System.out.println("要生成的表: " + String.join(", ", tableNames)); + System.out.println("========================"); + System.out.println(); + + System.out.println("开始生成代码..."); + generator.generateCode(tableNames); + System.out.println(); + System.out.println("代码生成完成!输出目录:" + config.getOutputDir()); + + } catch (Exception e) { + System.err.println("代码生成失败:" + e.getMessage()); + e.printStackTrace(); + } + } + + private static Properties properties; + + private static GeneratorConfig loadConfig() throws IOException { + // 加载配置文件 + properties = new Properties(); + try (InputStream input = MainGeneratorWithConfig.class.getClassLoader() + .getResourceAsStream("config.properties")) { + if (input == null) { + throw new IOException("配置文件 config.properties 未找到"); + } + properties.load(input); + } + + // 创建配置对象 + GeneratorConfig config = new GeneratorConfig(); + + // 数据库配置 + config.setUrl(getProperty("db.url", "")); + config.setDatabaseName(getProperty("db.name", "")); + config.setDriverName(getProperty("db.driver", "com.mysql.cj.jdbc.Driver")); + config.setUsername(getProperty("db.username", "")); + config.setPassword(getProperty("db.password", "")); + + // 生成配置 + config.setAuthor(getProperty("gen.author", "admin")); + config.setPackageName(getProperty("gen.packageName", "com.starry.play")); + config.setOutputDir(getProperty("gen.outputDir", "./generated-code")); + config.setAutoRemovePre(Boolean.parseBoolean(getProperty("gen.autoRemovePre", "false"))); + config.setTablePrefix(getProperty("gen.tablePrefix", "sys_")); + config.setTplCategory(getProperty("gen.tplCategory", "crud")); + + // 验证必需的配置 + if (config.getUrl().isEmpty()) { + throw new IllegalArgumentException("数据库连接地址不能为空,请配置 db.url"); + } + if (config.getUsername().isEmpty()) { + throw new IllegalArgumentException("数据库用户名不能为空,请配置 db.username"); + } + + return config; + } + + private static String getProperty(String key, String defaultValue) { + return properties.getProperty(key, defaultValue); + } +} + + +--- File: play-generator/src/main/java/com/starry/generator/config/GenConfig.java --- +package com.starry.generator.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.PropertySource; +import org.springframework.stereotype.Component; + +/** + * @author admin 读取代码生成相关配置 + * @since 2022/7/15 + */ +@Component +@ConfigurationProperties(prefix = "gen") +@PropertySource(value = {"classpath:generator.yml"}) +public class GenConfig { + + /** + * 作者 + */ + public static String author; + + /** + * 生成包路径 + */ + public static String packageName; + + /** + * 自动去除表前缀,默认是false + */ + public static boolean autoRemovePre; + + /** + * 表前缀(类名不会包含表前缀) + */ + public static String tablePrefix; + + public static String getAuthor() { + return author; + } + + @Value("${author}") + public void setAuthor(String author) { + GenConfig.author = author; + } + + public static String getPackageName() { + return packageName; + } + + @Value("${packageName}") + public void setPackageName(String packageName) { + GenConfig.packageName = packageName; + } + + public static boolean getAutoRemovePre() { + return autoRemovePre; + } + + @Value("${autoRemovePre}") + public void setAutoRemovePre(boolean autoRemovePre) { + GenConfig.autoRemovePre = autoRemovePre; + } + + public static String getTablePrefix() { + return tablePrefix; + } + + @Value("${tablePrefix}") + public void setTablePrefix(String tablePrefix) { + GenConfig.tablePrefix = tablePrefix; + } +} + + +--- File: play-generator/src/main/java/com/starry/generator/config/GeneratorConfig.java --- +package com.starry.generator.config; + +import lombok.Data; + +/** + * 代码生成器配置类 用于配置数据库连接和生成参数 + * + * @author admin + * @since 2024-01-01 + */ +@Data +public class GeneratorConfig { + + // 数据库连接配置 + private String url; + private String driverName; + private String username; + private String password; + private String databaseName; + + // 代码生成配置 + private String author; + private String packageName; + private String outputDir; + private boolean autoRemovePre; + private String tablePrefix; + + // 模板类型 (crud, tree, sub) + private String tplCategory = "crud"; + + // 功能名称 + private String functionName; + + // 模块名 + private String moduleName; + + // 业务名 + private String businessName; + + public GeneratorConfig() { + // 设置默认值 + this.author = "admin"; + this.packageName = "com.starry.play"; + this.outputDir = "./generated-code"; + this.autoRemovePre = false; + this.tablePrefix = "sys_"; + this.tplCategory = "crud"; + } + + /** + * 从URL中获取数据库名 + */ + public String getDatabaseName() { + if (databaseName != null && !databaseName.isEmpty()) { + return databaseName; + } + + // 如果没有手动设置数据库名,从URL中解析 + if (url != null) { + String dbName = url.substring(url.lastIndexOf("/") + 1); + if (dbName.contains("?")) { + dbName = dbName.substring(0, dbName.indexOf("?")); + } + return dbName; + } + return ""; + } +} + + +--- File: play-generator/src/main/java/com/starry/generator/constant/GenConstants.java --- +package com.starry.generator.constant; + +/** + * @author admin 代码生成通用常量 + */ +public class GenConstants { + + /** + * 单表(增删改查) + */ + public static final String TPL_CRUD = "crud"; + + /** + * 树表(增删改查) + */ + public static final String TPL_TREE = "tree"; + + /** + * 主子表(增删改查) + */ + public static final String TPL_SUB = "sub"; + + /** + * 树编码字段 + */ + public static final String TREE_CODE = "treeCode"; + + /** + * 树父编码字段 + */ + public static final String TREE_PARENT_CODE = "treeParentCode"; + + /** + * 树名称字段 + */ + public static final String TREE_NAME = "treeName"; + + /** + * 上级菜单ID字段 + */ + public static final String PARENT_MENU_ID = "parentMenuId"; + + /** + * 上级菜单名称字段 + */ + public static final String PARENT_MENU_NAME = "parentMenuName"; + + /** + * 数据库字符串类型 + */ + public static final String[] COLUMN_TYPE_STR = {"char", "varchar", "nvarchar", "varchar2"}; + + /** + * 数据库文本类型 + */ + public static final String[] COLUMN_TYPE_TEXT = {"tinytext", "text", "mediumtext", "longtext"}; + + /** + * 数据库时间类型 + */ + public static final String[] COLUMN_TYPE_TIME = {"datetime", "time", "date", "timestamp"}; + + /** + * 数据库数字类型 + */ + public static final String[] COLUMNTYPE_NUMBER = {"tinyint", "smallint", "mediumint", "int", "number", "integer", + "bit", "bigint", "float", "double", "decimal"}; + + /** + * 页面不需要编辑字段 + */ + public static final String[] COLUMN_NAME_NOT_EDIT = {"id", "create_by", "create_time", "del_flag"}; + + /** + * 页面不需要显示的列表字段 + */ + public static final String[] COLUMN_NAME_NOT_LIST = {"id", "create_by", "create_time", "del_flag", "update_by", + "update_time"}; + + /** + * 页面不需要查询字段 + */ + public static final String[] COLUMN_NAME_NOT_QUERY = {"id", "create_by", "create_time", "del_flag", "update_by", + "update_time", "remark"}; + + /** + * Entity基类字段 + */ + public static final String[] BASE_ENTITY = {"createBy", "createTime", "updateBy", "updateTime", "remark"}; + + /** + * Tree基类字段 + */ + public static final String[] TREE_ENTITY = {"parentName", "parentId", "orderNum", "ancestors", "children"}; + + /** + * 文本框 + */ + public static final String HTML_INPUT = "input"; + + /** + * 文本域 + */ + public static final String HTML_TEXTAREA = "textarea"; + + /** + * 下拉框 + */ + public static final String HTML_SELECT = "select"; + + /** + * 单选框 + */ + public static final String HTML_RADIO = "radio"; + + /** + * 复选框 + */ + public static final String HTML_CHECKBOX = "checkbox"; + + /** + * 日期控件 + */ + public static final String HTML_DATETIME = "datetime"; + + /** + * 图片上传控件 + */ + public static final String HTML_IMAGE_UPLOAD = "imageUpload"; + + /** + * 文件上传控件 + */ + public static final String HTML_FILE_UPLOAD = "fileUpload"; + + /** + * 富文本控件 + */ + public static final String HTML_EDITOR = "editor"; + + /** + * 字符串类型 + */ + public static final String TYPE_STRING = "String"; + + /** + * 整型 + */ + public static final String TYPE_INTEGER = "Integer"; + + /** + * 长整型 + */ + public static final String TYPE_LONG = "Long"; + + /** + * 浮点型 + */ + public static final String TYPE_DOUBLE = "Double"; + + /** + * 高精度计算类型 + */ + public static final String TYPE_BIGDECIMAL = "BigDecimal"; + + /** + * 时间类型 + */ + public static final String TYPE_DATE = "Date"; + + /** + * 模糊查询 + */ + public static final String QUERY_LIKE = "LIKE"; + + /** + * 相等查询 + */ + public static final String QUERY_EQ = "EQ"; + + /** + * 需要 + */ + public static final String REQUIRE = "1"; +} + + +--- File: play-generator/src/main/java/com/starry/generator/controller/GenController.java --- +package com.starry.generator.controller; + +import cn.hutool.core.convert.Convert; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.starry.common.annotation.Log; +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import com.starry.generator.entity.GenTableEntity; +import com.starry.generator.entity.vo.GenTableVo; +import com.starry.generator.service.GenTableService; +import io.swagger.annotations.ApiOperation; +import java.io.IOException; +import java.util.List; +import java.util.Map; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import org.apache.commons.io.IOUtils; +import org.springframework.web.bind.annotation.*; + +/** + * @author admin + * @since 2022/7/14 + */ +@RestController +@RequestMapping("/tool/gen") +public class GenController { + + @Resource + private GenTableService genTableService; + + @ApiOperation(value = "查询数据库列表") + @GetMapping("/db/list") + public R dataList(GenTableEntity genTableEntity) { + IPage list = genTableService.selectDbTableList(genTableEntity); + return R.ok(list); + } + + @ApiOperation(value = "保存表结构") + @PostMapping("/importTable") + public R importTableSave(String tables) { + String[] tableNames = Convert.toStrArray(tables); + // 查询表信息 + List tableList = genTableService.selectDbTableListByNames(tableNames); + genTableService.importGenTable(tableList); + return R.ok(); + } + + @ApiOperation(value = "查询生成表列表") + @GetMapping("/list") + public R genList(GenTableVo vo) { + return R.ok(genTableService.selectGenTableList(vo)); + } + + @ApiOperation(value = "预览代码") + @GetMapping("/preview/{tableId}") + public R preview(@PathVariable("tableId") Long tableId) { + Map dataMap = genTableService.previewCode(tableId); + return R.ok(dataMap); + } + + @ApiOperation(value = "生成代码(下载方式)") + @GetMapping("/download/{tableName}") + public void download(HttpServletResponse response, @PathVariable("tableName") String tableName) throws IOException { + byte[] data = genTableService.downloadCode(tableName); + genCode(response, data); + } + + @Log(title = "代码生成", businessType = BusinessType.GENCODE) + @ApiOperation(value = "批量生成代码") + @GetMapping("/download/batch") + public void batchGenCode(HttpServletResponse response, String tables) throws IOException { + String[] tableNames = Convert.toStrArray(tables); + byte[] data = genTableService.downloadCode(tableNames); + genCode(response, data); + } + + @ApiOperation(value = "删除代码生成") + @DeleteMapping("/{tableIds}") + public R remove(@PathVariable Long[] tableIds) { + genTableService.deleteGenTableByIds(tableIds); + return R.ok(); + } + + private void genCode(HttpServletResponse response, byte[] data) throws IOException { + response.reset(); + response.addHeader("Access-Control-Allow-Origin", "*"); + response.addHeader("Access-Control-Expose-Headers", "Content-Disposition"); + response.setHeader("Content-Disposition", "attachment; filename=\"admin.zip\""); + response.addHeader("Content-Length", "" + data.length); + response.setContentType("application/octet-stream; charset=UTF-8"); + IOUtils.write(data, response.getOutputStream()); + } +} + + +--- File: play-generator/src/main/java/com/starry/generator/core/CodeGenerator.java --- +package com.starry.generator.core; + +import com.starry.generator.config.GeneratorConfig; +import com.starry.generator.entity.GenTableColumnEntity; +import com.starry.generator.entity.GenTableEntity; +import com.starry.generator.utils.GenUtils; +import com.starry.generator.utils.VelocityInitializer; +import com.starry.generator.utils.VelocityUtils; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.StringWriter; +import java.sql.*; +import java.util.ArrayList; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.Velocity; + +/** + * 核心代码生成器 + * + * @author admin + * @since 2024-01-01 + */ +@Slf4j +public class CodeGenerator { + + private final GeneratorConfig config; + + public CodeGenerator(GeneratorConfig config) { + this.config = config; + } + + /** + * 生成代码 + * + * @param tableNames + * 表名数组 + */ + public void generateCode(String[] tableNames) throws Exception { + // 初始化 Velocity + VelocityInitializer.initVelocity(); + + // 创建输出目录 + createOutputDirectory(); + + for (String tableName : tableNames) { + log.info("开始生成表 {} 的代码", tableName); + generateTableCode(tableName); + log.info("表 {} 代码生成完成", tableName); + } + } + + /** + * 生成单个表的代码 + * + * @param tableName + * 表名 + */ + private void generateTableCode(String tableName) throws Exception { + // 获取表信息 + GenTableEntity table = getTableInfo(tableName); + if (table == null) { + log.warn("表 {} 不存在,跳过生成", tableName); + return; + } + + // 获取表字段信息 + List columns = getTableColumns(tableName); + table.setColumns(columns); + + // 初始化表信息 + initTableInfo(table); + + // 初始化字段信息 + initColumnInfo(table); + + // 设置主键列信息 + setPkColumn(table); + + // 设置模板变量信息 + VelocityContext context = VelocityUtils.prepareContext(table); + + // 获取模版列表 + List templates = VelocityUtils.getTemplateList(table.getTplCategory()); + + for (String template : templates) { + // 渲染模板 + StringWriter sw = new StringWriter(); + Template tpl = Velocity.getTemplate(template, "UTF-8"); + tpl.merge(context, sw); + + // 写入文件 + writeToFile(template, table, sw.toString()); + } + } + + /** + * 获取表信息 + */ + private GenTableEntity getTableInfo(String tableName) throws Exception { + String sql = "SELECT table_name, table_comment FROM information_schema.tables " + + "WHERE table_schema = ? AND table_name = ?"; + + try (Connection conn = getConnection(); PreparedStatement stmt = conn.prepareStatement(sql)) { + + String dbName = getDatabaseName(); + log.info("查询表信息 - 数据库名: {}, 表名: {}", dbName, tableName); + + stmt.setString(1, dbName); + stmt.setString(2, tableName); + + try (ResultSet rs = stmt.executeQuery()) { + if (rs.next()) { + GenTableEntity table = new GenTableEntity(); + table.setTableName(rs.getString("table_name")); + table.setTableComment(rs.getString("table_comment")); + log.info("找到表: {}, 注释: {}", table.getTableName(), table.getTableComment()); + return table; + } else { + // 如果找不到表,尝试查询所有表来调试 + log.warn("未找到表 {},正在查询数据库 {} 中的所有表...", tableName, dbName); + showAllTables(conn, dbName); + } + } + } + return null; + } + + /** + * 显示数据库中的所有表(用于调试) + */ + private void showAllTables(Connection conn, String dbName) throws Exception { + String sql = "SELECT table_name FROM information_schema.tables WHERE table_schema = ? LIMIT 10"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setString(1, dbName); + try (ResultSet rs = stmt.executeQuery()) { + log.info("数据库 {} 中的表:", dbName); + boolean hasTable = false; + while (rs.next()) { + hasTable = true; + log.info(" - {}", rs.getString("table_name")); + } + if (!hasTable) { + log.warn("数据库 {} 中没有找到任何表,请检查数据库名称是否正确", dbName); + } + } + } + } + + /** + * 获取表字段信息 + */ + private List getTableColumns(String tableName) throws Exception { + List columns = new ArrayList<>(); + + String sql = "SELECT column_name, data_type, column_comment, is_nullable, " + + "column_key, column_default, extra FROM information_schema.columns " + + "WHERE table_schema = ? AND table_name = ? ORDER BY ordinal_position"; + + try (Connection conn = getConnection(); PreparedStatement stmt = conn.prepareStatement(sql)) { + + String dbName = getDatabaseName(); + stmt.setString(1, dbName); + stmt.setString(2, tableName); + + try (ResultSet rs = stmt.executeQuery()) { + while (rs.next()) { + GenTableColumnEntity column = new GenTableColumnEntity(); + column.setColumnName(rs.getString("column_name")); + column.setColumnType(rs.getString("data_type")); + column.setColumnComment(rs.getString("column_comment")); + column.setIsRequired("NO".equals(rs.getString("is_nullable")) ? "1" : "0"); + column.setIsPk("PRI".equals(rs.getString("column_key")) ? "1" : "0"); + column.setIsIncrement("auto_increment".equals(rs.getString("extra")) ? "1" : "0"); + + columns.add(column); + } + } + } + + return columns; + } + + /** + * 初始化表信息 + */ + private void initTableInfo(GenTableEntity table) { + table.setClassName(GenUtils.convertClassName(table.getTableName())); + table.setPackageName(config.getPackageName()); + table.setModuleName(GenUtils.getModuleName(config.getPackageName())); + table.setBusinessName(GenUtils.getBusinessName(table.getTableName())); + table.setFunctionName(table.getTableComment()); + table.setFunctionAuthor(config.getAuthor()); + table.setTplCategory(config.getTplCategory()); + } + + /** + * 初始化字段信息 + */ + private void initColumnInfo(GenTableEntity table) { + if (table.getColumns() != null) { + for (GenTableColumnEntity column : table.getColumns()) { + GenUtils.initColumnField(column, table); + } + } + } + + /** + * 设置主键列信息 + */ + private void setPkColumn(GenTableEntity table) { + for (GenTableColumnEntity column : table.getColumns()) { + if ("1".equals(column.getIsPk())) { + table.setPkColumn(column); + break; + } + } + + if (table.getPkColumn() == null) { + table.setPkColumn(table.getColumns().get(0)); + } + } + + /** + * 写入文件 + */ + private void writeToFile(String template, GenTableEntity table, String content) throws IOException { + String fileName = getFileName(template, table); + File file = new File(fileName); + + // 创建父目录 + file.getParentFile().mkdirs(); + + try (FileWriter writer = new FileWriter(file)) { + writer.write(content); + } + + log.info("生成文件:{}", fileName); + } + + /** + * 获取文件名 + */ + private String getFileName(String template, GenTableEntity table) { + String outputDir = config.getOutputDir(); + String packageName = table.getPackageName(); + String moduleName = table.getModuleName(); + String businessName = table.getBusinessName(); + String className = table.getClassName(); + + String javaPath = outputDir + "/src/main/java/" + packageName.replace(".", "/"); + String resourcesPath = outputDir + "/src/main/resources"; + + if (template.contains("entity.java.vm")) { + return javaPath + "/entity/" + className + "Entity.java"; + } else if (template.contains("mapper.java.vm")) { + return javaPath + "/mapper/" + className + "Mapper.java"; + } else if (template.contains("service.java.vm")) { + return javaPath + "/service/I" + className + "Service.java"; + } else if (template.contains("serviceImpl.java.vm")) { + return javaPath + "/service/impl/" + className + "ServiceImpl.java"; + } else if (template.contains("controller.java.vm")) { + return javaPath + "/controller/" + className + "Controller.java"; + } else if (template.contains("queryVo.java.vm")) { + return javaPath + "/vo/" + className + "QueryVo.java"; + } else if (template.contains("addVo.java.vm")) { + return javaPath + "/vo/" + className + "AddVo.java"; + } else if (template.contains("mapper.xml.vm")) { + return resourcesPath + "/mapper/" + className + "Mapper.xml"; + } else if (template.contains("sql.vm")) { + return outputDir + "/" + businessName + "Menu.sql"; + } else if (template.contains("api.js.vm")) { + return outputDir + "/api/" + moduleName + "/" + businessName + ".js"; + } else if (template.contains("index.vue.vm")) { + return outputDir + "/views/" + moduleName + "/" + businessName + "/index.vue"; + } + + return outputDir + "/" + template.replace(".vm", ""); + } + + /** + * 获取数据库连接 + */ + private Connection getConnection() throws Exception { + Class.forName(config.getDriverName()); + return DriverManager.getConnection(config.getUrl(), config.getUsername(), config.getPassword()); + } + + /** + * 从URL中获取数据库名 + */ + private String getDatabaseName() { + return config.getDatabaseName(); + } + + /** + * 创建输出目录 + */ + private void createOutputDirectory() { + File outputDir = new File(config.getOutputDir()); + if (!outputDir.exists()) { + outputDir.mkdirs(); + } + } +} + + +--- File: play-generator/src/main/java/com/starry/generator/entity/GenTableColumnEntity.java --- +package com.starry.generator.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.common.domain.BaseEntity; +import com.starry.common.utils.StringUtils; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; +import javax.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * @author admin 代码生成业务字段表 gen_table_column + * @since 2022/7/14 + */ +@Getter +@Setter +@TableName("gen_table_column") +@ApiModel(value = "GenTableColumn对象", description = "代码生成业务表字段") +public class GenTableColumnEntity extends BaseEntity implements Serializable { + + /** + * 编号 + */ + @ApiModelProperty("主键ID") + @TableId(value = "table_id", type = IdType.AUTO) + private Long columnId; + + /** + * 归属表编号 + */ + private Long tableId; + + /** + * 列名称 + */ + private String columnName; + + /** + * 列描述 + */ + private String columnComment; + + /** + * 列类型 + */ + private String columnType; + + /** + * JAVA类型 + */ + private String javaType; + + /** + * JAVA字段名 + */ + @NotBlank(message = "Java属性不能为空") + private String javaField; + + /** + * 是否主键(1是) + */ + private String isPk; + + /** + * 是否自增(1是) + */ + private String isIncrement; + + /** + * 是否必填(1是) + */ + private String isRequired; + + /** + * 是否为插入字段(1是) + */ + private String isInsert; + + /** + * 是否编辑字段(1是) + */ + private String isEdit; + + /** + * 是否列表字段(1是) + */ + private String isList; + + /** + * 是否查询字段(1是) + */ + private String isQuery; + + /** + * 查询方式(EQ等于、NE不等于、GT大于、LT小于、LIKE模糊、BETWEEN范围) + */ + private String queryType; + + /** + * 显示类型(input文本框、textarea文本域、select下拉框、checkbox复选框、radio单选框、datetime日期控件、image图片上传控件、upload文件上传控件、editor富文本控件) + */ + private String htmlType; + + /** + * 字典类型 + */ + private String dictType; + + /** + * 排序 + */ + private Integer sort; + + public static boolean isSuperColumn(String javaField) { + return StringUtils.equalsAnyIgnoreCase(javaField, + // BaseEntity + "createdBy", "createdTime", "updatedBy", "updatedTime", "deleted", + // TreeEntity + "parentName", "parentId", "orderNum", "ancestors"); + } + + public boolean isSuperColumn() { + return isSuperColumn(this.javaField); + } + + public String getCapJavaField() { + return StringUtils.capitalize(javaField); + } + +} + + +--- File: play-generator/src/main/java/com/starry/generator/entity/GenTableEntity.java --- +package com.starry.generator.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.starry.common.domain.BaseEntity; +import com.starry.common.utils.StringUtils; +import com.starry.generator.constant.GenConstants; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import javax.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * @author admin 业务表 gen_table + * @since 2022/7/14 + */ +@Getter +@Setter +@TableName("gen_table") +@ApiModel(value = "GenTable对象", description = "代码生成业务表") +public class GenTableEntity extends BaseEntity { + + @ApiModelProperty("主键ID") + @TableId(value = "table_id", type = IdType.AUTO) + private Long tableId; + + /** + * 表名称 + */ + @NotBlank(message = "表名称不能为空") + private String tableName; + + /** + * 表描述 + */ + @NotBlank(message = "表描述不能为空") + private String tableComment; + + /** + * 关联父表的表名 + */ + private String subTableName; + + /** + * 本表关联父表的外键名 + */ + private String subTableFkName; + + /** + * 实体类名称(首字母大写) + */ + @NotBlank(message = "实体类名称不能为空") + private String className; + + /** + * 使用的模板(crud单表操作 tree树表操作 sub主子表操作) + */ + private String tplCategory; + + /** + * 生成包路径 + */ + @NotBlank(message = "生成包路径不能为空") + private String packageName; + + /** + * 生成模块名 + */ + @NotBlank(message = "生成模块名不能为空") + private String moduleName; + + /** + * 生成业务名 + */ + @NotBlank(message = "生成业务名不能为空") + private String businessName; + + /** + * 生成功能名 + */ + @NotBlank(message = "生成功能名不能为空") + private String functionName; + + /** + * 生成作者 + */ + @NotBlank(message = "作者不能为空") + private String functionAuthor; + + /** + * 生成代码方式(0zip压缩包 1自定义路径) + */ + private String genType; + + /** + * 生成路径(不填默认项目路径) + */ + private String genPath; + + /** + * 主键信息 + */ + @TableField(exist = false) + private GenTableColumnEntity pkColumn; + + /** + * 子表信息 + */ + @TableField(exist = false) + private GenTableEntity subTable; + + /** + * 表列信息 + */ + @TableField(exist = false) + private List columns; + + /** + * 其它生成选项 + */ + private String options; + + /** + * 树编码字段 + */ + @TableField(exist = false) + private String treeCode; + + /** + * 树父编码字段 + */ + @TableField(exist = false) + private String treeParentCode; + + /** + * 树名称字段 + */ + @TableField(exist = false) + private String treeName; + + /** + * 上级菜单ID字段 + */ + @TableField(exist = false) + private String parentMenuId; + + /** + * 上级菜单名称字段 + */ + @TableField(exist = false) + private String parentMenuName; + + public static boolean isCrud(String tplCategory) { + return tplCategory != null && StringUtils.equals(GenConstants.TPL_CRUD, tplCategory); + } + + public static boolean isTree(String tplCategory) { + return tplCategory != null && StringUtils.equals(GenConstants.TPL_TREE, tplCategory); + } + + public boolean isCrud() { + return isCrud(this.tplCategory); + } + + public boolean isTree() { + return isTree(this.tplCategory); + } +} + + +--- File: play-generator/src/main/java/com/starry/generator/entity/vo/GenTableVo.java --- +package com.starry.generator.entity.vo; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.starry.common.domain.BasePageEntity; +import com.starry.generator.entity.GenTableColumnEntity; +import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import javax.validation.constraints.NotBlank; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @author admin 业务表 gen_table + * @since 2022/7/14 + */ + +@EqualsAndHashCode(callSuper = true) +@Data +public class GenTableVo extends BasePageEntity { + + @ApiModelProperty("主键ID") + @TableId(value = "table_id", type = IdType.AUTO) + private Long tableId; + + /** + * 表名称 + */ + @NotBlank(message = "表名称不能为空") + private String tableName; + + /** + * 表描述 + */ + @NotBlank(message = "表描述不能为空") + private String tableComment; + + /** + * 关联父表的表名 + */ + private String subTableName; + + /** + * 本表关联父表的外键名 + */ + private String subTableFkName; + + /** + * 实体类名称(首字母大写) + */ + @NotBlank(message = "实体类名称不能为空") + private String className; + + /** + * 使用的模板(crud单表操作 tree树表操作 sub主子表操作) + */ + private String tplCategory; + + /** + * 生成包路径 + */ + @NotBlank(message = "生成包路径不能为空") + private String packageName; + + /** + * 生成模块名 + */ + @NotBlank(message = "生成模块名不能为空") + private String moduleName; + + /** + * 生成业务名 + */ + @NotBlank(message = "生成业务名不能为空") + private String businessName; + + /** + * 生成功能名 + */ + @NotBlank(message = "生成功能名不能为空") + private String functionName; + + /** + * 生成作者 + */ + @NotBlank(message = "作者不能为空") + private String functionAuthor; + + /** + * 生成代码方式(0zip压缩包 1自定义路径) + */ + private String genType; + + /** + * 生成路径(不填默认项目路径) + */ + private String genPath; + + /** + * 主键信息 + */ + @TableField(exist = false) + private GenTableColumnEntity pkColumn; + + /** + * 子表信息 + */ + @TableField(exist = false) + private GenTableVo subTable; + + /** + * 表列信息 + */ + @TableField(exist = false) + private List columns; + + /** + * 其它生成选项 + */ + private String options; + + /** + * 树编码字段 + */ + @TableField(exist = false) + private String treeCode; + + /** + * 树父编码字段 + */ + @TableField(exist = false) + private String treeParentCode; + + /** + * 树名称字段 + */ + @TableField(exist = false) + private String treeName; + + /** + * 上级菜单ID字段 + */ + @TableField(exist = false) + private String parentMenuId; + + /** + * 上级菜单名称字段 + */ + @TableField(exist = false) + private String parentMenuName; + +} + + +--- File: play-generator/src/main/java/com/starry/generator/mapper/GenTableColumnMapper.java --- +package com.starry.generator.mapper; + +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.starry.generator.entity.GenTableColumnEntity; +import java.util.List; + +/** + *

+ * 代码生成业务表字段 Mapper 接口 + *

+ * + * @author admin + * @since 2022-07-15 + */ +public interface GenTableColumnMapper extends BaseMapper { + + /** + * 根据表名称查询列信息 + * + * @param tableName + * 表名称 + * @return 列信息 + */ + @InterceptorIgnore(tenantLine = "1") + List selectDbTableColumnsByName(String tableName); + +} + + +--- File: play-generator/src/main/java/com/starry/generator/mapper/GenTableMapper.java --- +package com.starry.generator.mapper; + +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.starry.generator.entity.GenTableEntity; +import com.starry.generator.entity.vo.GenTableVo; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +/** + * @author admin 业务 数据层 + * @since 2022/7/14 + */ +public interface GenTableMapper extends BaseMapper { + + /** + * 查询业务列表 + * + * @param genTableEntity + * 业务信息 + * @return 业务集合 + */ + + IPage selectGenTableList(Page page, + @Param(value = "genTableEntity") GenTableVo genTableEntity); + + @InterceptorIgnore(tenantLine = "1") + IPage selectDbTableList(Page page, @Param("genTableEntity") GenTableEntity genTableEntity); + + /** + * 查询数据库列表 + * + * @param tableNames + * 表名称组 + * @return 数据库表集合 + */ + @InterceptorIgnore(tenantLine = "1") + List selectDbTableListByNames(String[] tableNames); + + /** + * 查询所有表信息 + * + * @return 表信息集合 + */ + List selectGenTableAll(); + + /** + * 查询表ID业务信息 + * + * @param id + * 业务ID + * @return 业务信息 + */ + GenTableEntity selectGenTableById(Long id); + + /** + * 查询表名称业务信息 + * + * @param tableName + * 表名称 + * @return 业务信息 + */ + GenTableEntity selectGenTableByName(String tableName); +} + + +--- File: play-generator/src/main/java/com/starry/generator/service/GenTableService.java --- +package com.starry.generator.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.starry.generator.entity.GenTableEntity; +import com.starry.generator.entity.vo.GenTableVo; +import java.util.List; +import java.util.Map; + +/** + * @author admin + * @since 2022/7/14 + */ +public interface GenTableService extends IService { + + /** + * 查询数据库列表 + * + * @param genTableEntity + * 业务信息 + * @return 数据库表集合 + */ + /* List selectDbTableList(GenTableEntity genTableEntity); */ + + IPage selectDbTableList(GenTableEntity genTableEntity); + + /** + * 查询据库列表 + * + * @param tableNames + * 表名称组 + * @return 数据库表集合 + */ + List selectDbTableListByNames(String[] tableNames); + + /** + * 导入表结构 + * + * @param tableList + * 导入表列表 + */ + void importGenTable(List tableList); + + /** + * 查询业务列表 + * + * @param genTableEntity + * 业务信息 + * @return 业务集合 + */ + IPage selectGenTableList(GenTableVo genTableEntity); + + /** + * 预览代码 + * + * @param tableId + * 表编号 + * @return 预览数据列表 + */ + Map previewCode(Long tableId); + + /** + * 生成代码(下载方式) + * + * @param tableName + * 表名称 + * @return 数据 + */ + byte[] downloadCode(String tableName); + + /** + * 批量生成代码(下载方式) + * + * @param tableNames + * 表数组 + * @return 数据 + */ + byte[] downloadCode(String[] tableNames); + + /** + * 删除业务信息 + * + * @param tableIds + * 需要删除的表数据ID + */ + void deleteGenTableByIds(Long[] tableIds); +} + + +--- File: play-generator/src/main/java/com/starry/generator/service/GenTableServiceImpl.java --- +package com.starry.generator.service; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.convert.Convert; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.starry.common.utils.ServletUtils; +import com.starry.common.utils.StringUtils; +import com.starry.generator.constant.GenConstants; +import com.starry.generator.entity.GenTableColumnEntity; +import com.starry.generator.entity.GenTableEntity; +import com.starry.generator.entity.vo.GenTableVo; +import com.starry.generator.mapper.GenTableColumnMapper; +import com.starry.generator.mapper.GenTableMapper; +import com.starry.generator.utils.GenUtils; +import com.starry.generator.utils.VelocityInitializer; +import com.starry.generator.utils.VelocityUtils; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.StringWriter; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.IOUtils; +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.Velocity; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * @author admin + * @since 2022/7/14 + */ +@Slf4j +@Service +public class GenTableServiceImpl extends ServiceImpl implements GenTableService { + + @Resource + private GenTableColumnMapper genTableColumnMapper; + + /* + * @Override public List selectDbTableList(GenTableEntity + * genTableEntity) { return baseMapper.selectDbTableList(genTableEntity); } + */ + @Override + public IPage selectDbTableList(GenTableEntity genTableEntity) { + Page mpPage = new Page(Convert.toLong(ServletUtils.getParameterToInt("pageNum"), 1L), + Convert.toLong(ServletUtils.getParameterToInt("pageSize"), 10L)); + return baseMapper.selectDbTableList(mpPage, genTableEntity); + } + + @Override + public List selectDbTableListByNames(String[] tableNames) { + return baseMapper.selectDbTableListByNames(tableNames); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void importGenTable(List tableList) { + if (CollectionUtil.isNotEmpty(tableList)) { + for (GenTableEntity table : tableList) { + String tableName = table.getTableName(); + GenUtils.initTable(table); + // 保存生成表数据 + int row = baseMapper.insert(table); + if (row > 0) { + // 查询数据库表列信息 + List genTableColumnEntities = genTableColumnMapper + .selectDbTableColumnsByName(tableName); + if (CollectionUtil.isNotEmpty(genTableColumnEntities)) { + for (GenTableColumnEntity column : genTableColumnEntities) { + GenUtils.initColumnField(column, table); + // 保存生成表字段数据 + genTableColumnMapper.insert(column); + } + } + } + } + } + } + + @Override + public IPage selectGenTableList(GenTableVo vo) { + return baseMapper.selectGenTableList(new Page<>(vo.getPageNum(), vo.getPageSize()), vo); + } + + @Override + public Map previewCode(Long tableId) { + Map dataMap = new LinkedHashMap<>(); + // 查询表信息 + GenTableEntity table = baseMapper.selectGenTableById(tableId); + // 设置主子表信息 + setSubTable(table); + // 设置主键列信息 + setPkColumn(table); + // 初始化 + VelocityInitializer.initVelocity(); + // 设置模板变量信息 + VelocityContext context = VelocityUtils.prepareContext(table); + // 获取模版列表 + List templates = VelocityUtils.getTemplateList(table.getTplCategory()); + for (String template : templates) { + // 渲染模板 + StringWriter sw = new StringWriter(); + Template tpl = Velocity.getTemplate(template, "UTF-8"); + tpl.merge(context, sw); + dataMap.put(template, sw.toString()); + } + return dataMap; + } + + @Override + public byte[] downloadCode(String tableName) { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + ZipOutputStream zip = new ZipOutputStream(outputStream); + generatorCode(tableName, zip); + IOUtils.closeQuietly(zip); + return outputStream.toByteArray(); + } + + @Override + public byte[] downloadCode(String[] tableNames) { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + ZipOutputStream zip = new ZipOutputStream(outputStream); + for (String tableName : tableNames) { + generatorCode(tableName, zip); + } + IOUtils.closeQuietly(zip); + return outputStream.toByteArray(); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteGenTableByIds(Long[] tableIds) { + baseMapper.deleteBatchIds(Arrays.asList(tableIds)); + List genTableColumnEntities = genTableColumnMapper + .selectList(new LambdaQueryWrapper().in(GenTableColumnEntity::getTableId, + Arrays.asList(tableIds))); + genTableColumnMapper.deleteBatchIds(genTableColumnEntities); + } + + private void generatorCode(String tableName, ZipOutputStream zip) { + // 查询表信息 + GenTableEntity table = baseMapper.selectGenTableByName(tableName); + // 设置主子表信息 + setSubTable(table); + // 设置主键列信息 + setPkColumn(table); + // 初始化 + VelocityInitializer.initVelocity(); + // 设置模板变量信息 + VelocityContext context = VelocityUtils.prepareContext(table); + // 获取模版列表 + List templates = VelocityUtils.getTemplateList(table.getTplCategory()); + for (String template : templates) { + // 渲染模板 + StringWriter sw = new StringWriter(); + Template tpl = Velocity.getTemplate(template, "UTF-8"); + tpl.merge(context, sw); + try { + // 添加到zip + zip.putNextEntry(new ZipEntry(VelocityUtils.getFileName(template, table))); + IOUtils.write(sw.toString(), zip, "UTF-8"); + IOUtils.closeQuietly(sw); + zip.flush(); + zip.closeEntry(); + } catch (IOException e) { + log.error("渲染模板失败,表名:" + table.getTableName(), e); + } + } + } + + public void setSubTable(GenTableEntity table) { + String subTableName = table.getSubTableName(); + if (StringUtils.isNotBlank(subTableName)) { + + } + } + + /** + * 设置主键列信息 + * + * @param table + * 业务表信息 + */ + public void setPkColumn(GenTableEntity table) { + for (GenTableColumnEntity column : table.getColumns()) { + if ("1".equals(column.getIsPk())) { + table.setPkColumn(column); + break; + } + if (StringUtils.isNull(table.getPkColumn())) { + table.setPkColumn(table.getColumns().get(0)); + } + if (GenConstants.TPL_SUB.equals(table.getTplCategory())) { + for (GenTableColumnEntity columnSub : table.getSubTable().getColumns()) { + if ("1".equals(columnSub.getIsPk())) { + table.getSubTable().setPkColumn(columnSub); + break; + } + if (StringUtils.isNull(table.getSubTable().getPkColumn())) { + table.getSubTable().setPkColumn(table.getSubTable().getColumns().get(0)); + } + } + } + } + } +} + + +--- File: play-generator/src/main/java/com/starry/generator/utils/GenUtils.java --- +package com.starry.generator.utils; + +import com.starry.generator.config.GenConfig; +import com.starry.generator.constant.GenConstants; +import com.starry.generator.entity.GenTableColumnEntity; +import com.starry.generator.entity.GenTableEntity; +import java.util.Arrays; +import org.apache.commons.lang3.StringUtils; + +/** + * @author admin 代码生成器 工具类 + * @since 2022/7/15 + */ +public class GenUtils { + + /** + * 初始化表信息 + */ + public static void initTable(GenTableEntity genTableEntity) { + genTableEntity.setClassName(convertClassName(genTableEntity.getTableName())); + genTableEntity.setPackageName(GenConfig.getPackageName()); + genTableEntity.setModuleName(getModuleName(GenConfig.getPackageName())); + genTableEntity.setBusinessName(getBusinessName(genTableEntity.getTableName())); + genTableEntity.setFunctionName(genTableEntity.getTableComment()); + genTableEntity.setFunctionAuthor(GenConfig.getAuthor()); + } + + /** + * 表名转换成Java类名 + * + * @param tableName + * 表名称 + * @return 类名 + */ + public static String convertClassName(String tableName) { + // 获取是否自动去除表前缀 + boolean autoRemovePre = GenConfig.getAutoRemovePre(); + // 获取表前缀 + String tablePrefix = GenConfig.getTablePrefix(); + if (autoRemovePre && StringUtils.isNotBlank(tablePrefix)) { + String[] searchList = StringUtils.split(tablePrefix, ","); + tableName = replaceFirst(tableName, searchList); + } + return convertToCamelCase(tableName); + } + + /** + * 批量替换前缀 + * + * @param replacement + * 替换值 + * @param searchList + * 替换列表 + * @return + */ + public static String replaceFirst(String replacement, String[] searchList) { + String text = replacement; + for (String searchString : searchList) { + if (replacement.startsWith(searchString)) { + text = replacement.replaceFirst(searchString, ""); + break; + } + } + return text; + } + + /** + * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD -> + * HelloWorld + * + * @param name + * 转换前的下划线大写方式命名的字符串 + * @return 转换后的驼峰式命名的字符串 + */ + public static String convertToCamelCase(String name) { + StringBuilder result = new StringBuilder(); + if (StringUtils.isBlank(name)) { + return ""; + } else if (!name.contains("_")) { + // 不含下划线,仅将首字母大写 + return name.substring(0, 1).toUpperCase() + name.substring(1); + } + String[] camels = name.split("_"); + for (String camel : camels) { + // 跳过原始字符串中开头、结尾的下换线或双重下划线 + if (camel.isEmpty()) { + continue; + } + // 首字母大写 + result.append(camel.substring(0, 1).toUpperCase()); + result.append(camel.substring(1).toLowerCase()); + } + return result.toString(); + } + + /** + * 获取模块名 + * + * @param packageName + * 包名 + * @return 模块名 + */ + public static String getModuleName(String packageName) { + int lastIndex = packageName.lastIndexOf("."); + int nameLength = packageName.length(); + return StringUtils.substring(packageName, lastIndex + 1, nameLength); + } + + /** + * 获取业务名 + * + * @param tableName + * 表名 + * @return 业务名 + */ + public static String getBusinessName(String tableName) { + int lastIndex = tableName.lastIndexOf("_"); + int nameLength = tableName.length(); + return StringUtils.substring(tableName, lastIndex + 1, nameLength); + } + + /** + * 初始化列属性字段 + */ + public static void initColumnField(GenTableColumnEntity column, GenTableEntity table) { + String dataType = getDbType(column.getColumnType()); + String columnName = column.getColumnName(); + column.setTableId(table.getTableId()); + // 设置java字段名 + column.setJavaField(toCamelCase(columnName)); + // 设置默认类型 + column.setJavaType(GenConstants.TYPE_STRING); + column.setQueryType(GenConstants.QUERY_EQ); + + if (arraysContains(GenConstants.COLUMN_TYPE_STR, dataType) + || arraysContains(GenConstants.COLUMN_TYPE_TEXT, dataType)) { + // 字符串长度超过500设置为文本域 + Integer columnLength = getColumnLength(column.getColumnType()); + String htmlType = columnLength >= 500 || arraysContains(GenConstants.COLUMN_TYPE_TEXT, dataType) + ? GenConstants.HTML_TEXTAREA + : GenConstants.HTML_INPUT; + column.setHtmlType(htmlType); + } else if (arraysContains(GenConstants.COLUMN_TYPE_TIME, dataType)) { + // 时间类型 + column.setJavaType(GenConstants.TYPE_DATE); + column.setHtmlType(GenConstants.HTML_DATETIME); + } else if (arraysContains(GenConstants.COLUMNTYPE_NUMBER, dataType)) { + // 数字类型 + column.setHtmlType(GenConstants.HTML_INPUT); + // 如果是浮点型 统一用BigDecimal + String[] str = StringUtils.split(StringUtils.substringBetween(column.getColumnType(), "(", ")"), ","); + if (str != null && str.length == 2 && Integer.parseInt(str[1]) > 0) { + column.setJavaType(GenConstants.TYPE_BIGDECIMAL); + } else if (str != null && str.length == 1 && Integer.parseInt(str[0]) <= 10) { + // 如果是整形 + column.setJavaType(GenConstants.TYPE_INTEGER); + } else { + // 长整形 + column.setJavaType(GenConstants.TYPE_LONG); + } + } + + // 插入字段(默认所有字段都需要插入) + column.setIsInsert(GenConstants.REQUIRE); + + // 编辑字段 + if (!arraysContains(GenConstants.COLUMN_NAME_NOT_EDIT, columnName) && !"1".equals(column.getIsPk())) { + column.setIsEdit(GenConstants.REQUIRE); + } + // 列表字段 + if (!arraysContains(GenConstants.COLUMN_NAME_NOT_LIST, columnName) && !"1".equals(column.getIsPk())) { + column.setIsList(GenConstants.REQUIRE); + } + // 查询字段 + if (!arraysContains(GenConstants.COLUMN_NAME_NOT_QUERY, columnName) && !"1".equals(column.getIsPk())) { + column.setIsQuery(GenConstants.REQUIRE); + } + + // 查询字段类型 + if (StringUtils.endsWithIgnoreCase(columnName, "name")) { + column.setQueryType(GenConstants.QUERY_LIKE); + } + // 状态字段设置单选框 + if (StringUtils.endsWithIgnoreCase(columnName, "status")) { + column.setHtmlType(GenConstants.HTML_RADIO); + } + // 类型&性别字段设置下拉框 + else if (StringUtils.endsWithIgnoreCase(columnName, "type") + || StringUtils.endsWithIgnoreCase(columnName, "sex")) { + column.setHtmlType(GenConstants.HTML_SELECT); + } + // 图片字段设置图片上传控件 + else if (StringUtils.endsWithIgnoreCase(columnName, "image")) { + column.setHtmlType(GenConstants.HTML_IMAGE_UPLOAD); + } + // 文件字段设置文件上传控件 + else if (StringUtils.endsWithIgnoreCase(columnName, "file")) { + column.setHtmlType(GenConstants.HTML_FILE_UPLOAD); + } + // 内容字段设置富文本控件 + else if (StringUtils.endsWithIgnoreCase(columnName, "content")) { + column.setHtmlType(GenConstants.HTML_EDITOR); + } + } + + /** + * 获取数据库类型字段 例如: bigint 、varchar(64) + * + * @param columnType + * 列类型 + * @return 截取后的列类型 + */ + public static String getDbType(String columnType) { + if (StringUtils.indexOf(columnType, "(") > 0) { + return StringUtils.substringBefore(columnType, "("); + } else { + return columnType; + } + } + + /** + * 获取字段长度 + * + * @param columnType + * 列类型 + * @return 截取后的列类型 + */ + public static Integer getColumnLength(String columnType) { + if (StringUtils.indexOf(columnType, "(") > 0) { + String length = StringUtils.substringBetween(columnType, "(", ")"); + return Integer.valueOf(length); + } else { + return 0; + } + } + + /** + * 驼峰式命名法 例如:user_name->userName + */ + public static String toCamelCase(String s) { + if (StringUtils.isNotBlank(s)) { + // 小写 + s = s.toLowerCase(); + StringBuilder sb = new StringBuilder(s.length()); + // 大写 + boolean upperCase = false; + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (c == '_') { + upperCase = true; + } else if (upperCase) { + sb.append(Character.toUpperCase(c)); + upperCase = false; + } else { + sb.append(c); + } + } + return sb.toString(); + } + return s; + } + + /** + * 校验数组是否包含指定值 + * + * @param arr + * 数组 + * @param targetValue + * 值 + * @return 是否包含 + */ + public static boolean arraysContains(String[] arr, String targetValue) { + return Arrays.asList(arr).contains(targetValue); + } +} + + +--- File: play-generator/src/main/java/com/starry/generator/utils/VelocityInitializer.java --- +package com.starry.generator.utils; + +import java.util.Properties; +import org.apache.velocity.app.Velocity; + +/** + * @author VelocityEngine工厂 + * @since 2022/7/19 + */ +public class VelocityInitializer { + + public static void initVelocity() { + Properties p = new Properties(); + // 加载classpath目录下的vm文件 + p.setProperty("resource.loader.file.class", + "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); + // 定义字符集 + p.setProperty(Velocity.INPUT_ENCODING, "UTF-8"); + // 初始化Velocity引擎,指定配置Properties + Velocity.init(p); + } +} + + +--- File: play-generator/src/main/java/com/starry/generator/utils/VelocityUtils.java --- +package com.starry.generator.utils; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; +import com.starry.common.utils.StringUtils; +import com.starry.generator.constant.GenConstants; +import com.starry.generator.entity.GenTableColumnEntity; +import com.starry.generator.entity.GenTableEntity; +import java.util.*; +import org.apache.velocity.VelocityContext; + +/** + * @author admin 模板处理工具类 + * @since 2022/7/19 + */ +public class VelocityUtils { + + /** + * 默认上级菜单,系统工具 + */ + private static final String DEFAULT_PARENT_MENU_ID = "3"; + + /** + * 项目空间路径 + */ + private static final String PROJECT_PATH = "main/java"; + /** + * mybatis空间路径 + */ + private static final String MYBATIS_PATH = "main/resources/mapper"; + + /** + * 设置模板变量信息 + * + * @return 模板列表 + */ + public static VelocityContext prepareContext(GenTableEntity genTableEntity) { + String moduleName = genTableEntity.getModuleName(); + String businessName = genTableEntity.getBusinessName(); + String packageName = genTableEntity.getPackageName(); + String tplCategory = genTableEntity.getTplCategory(); + String functionName = genTableEntity.getFunctionName(); + + VelocityContext velocityContext = new VelocityContext(); + velocityContext.put("tplCategory", genTableEntity.getTplCategory()); + velocityContext.put("tableName", genTableEntity.getTableName()); + velocityContext.put("functionName", StrUtil.isNotBlank(functionName) ? functionName : "【请填写功能名称】"); + velocityContext.put("ClassName", genTableEntity.getClassName()); + // 首字母小写 + velocityContext.put("className", StringUtils.uncapitalize(genTableEntity.getClassName())); + velocityContext.put("moduleName", genTableEntity.getModuleName()); + // 首字母大写 + velocityContext.put("BusinessName", StringUtils.capitalize(genTableEntity.getBusinessName())); + velocityContext.put("businessName", genTableEntity.getBusinessName()); + velocityContext.put("basePackage", getPackagePrefix(packageName)); + velocityContext.put("packageName", packageName); + velocityContext.put("author", genTableEntity.getFunctionAuthor()); + velocityContext.put("datetime", DateUtil.format(new Date(), "yyyy-MM-dd")); + velocityContext.put("pkColumn", genTableEntity.getPkColumn()); + velocityContext.put("importList", getImportList(genTableEntity)); + velocityContext.put("permissionPrefix", getPermissionPrefix(moduleName, businessName)); + velocityContext.put("columns", genTableEntity.getColumns()); + velocityContext.put("table", genTableEntity); + velocityContext.put("dicts", getDicts(genTableEntity)); + setMenuVelocityContext(velocityContext, genTableEntity); + if (GenConstants.TPL_TREE.equals(tplCategory)) { + setTreeVelocityContext(velocityContext, genTableEntity); + } + if (GenConstants.TPL_SUB.equals(tplCategory)) { + setSubVelocityContext(velocityContext, genTableEntity); + } + return velocityContext; + } + + /** + * 获取包前缀 + * + * @param packageName + * 包名称 + * @return 包前缀名称 + */ + public static String getPackagePrefix(String packageName) { + int lastIndex = packageName.lastIndexOf("."); + return StringUtils.substring(packageName, 0, lastIndex); + } + + /** + * 根据列类型获取导入包 + * + * @param genTableEntity + * 业务表对象 + * @return 返回需要导入的包列表 + */ + public static HashSet getImportList(GenTableEntity genTableEntity) { + List columns = genTableEntity.getColumns(); + GenTableEntity subGenTableEntity = genTableEntity.getSubTable(); + HashSet importList = new HashSet<>(); + if (StringUtils.isNotNull(subGenTableEntity)) { + importList.add("java.util.List"); + } + for (GenTableColumnEntity column : columns) { + // 不是基础字段 且是 时间类型 + if (!column.isSuperColumn() && GenConstants.TYPE_DATE.equals(column.getJavaType())) { + importList.add("java.util.Date"); + importList.add("com.fasterxml.jackson.annotation.JsonFormat"); + } else if (!column.isSuperColumn() && GenConstants.TYPE_BIGDECIMAL.equals(column.getJavaType())) { + importList.add("java.math.BigDecimal"); + } + } + return importList; + } + + /** + * 获取权限前缀 + * + * @param moduleName + * 模块名称 + * @param businessName + * 业务名称 + * @return 返回权限前缀 + */ + public static String getPermissionPrefix(String moduleName, String businessName) { + return StringUtils.format("{}:{}", moduleName, businessName); + } + + /** + * 根据列类型获取字典组 + * + * @param genTableEntity + * 业务表对象 + * @return 返回字典组 + */ + public static String getDicts(GenTableEntity genTableEntity) { + List columns = genTableEntity.getColumns(); + Set dicts = new HashSet<>(); + addDicts(dicts, columns); + if (StringUtils.isNotNull(genTableEntity.getSubTable())) { + List subColumns = genTableEntity.getSubTable().getColumns(); + addDicts(dicts, subColumns); + } + return StringUtils.join(dicts, ", "); + } + + /** + * 添加字典列表 + * + * @param dicts + * 字典列表 + * @param columns + * 列集合 + */ + public static void addDicts(Set dicts, List columns) { + for (GenTableColumnEntity column : columns) { + if (!column.isSuperColumn() && StrUtil.isNotBlank(column.getDictType()) && StringUtils.equalsAny( + column.getHtmlType(), + new String[]{GenConstants.HTML_SELECT, GenConstants.HTML_RADIO, GenConstants.HTML_CHECKBOX})) { + dicts.add("'" + column.getDictType() + "'"); + } + } + } + + public static void setMenuVelocityContext(VelocityContext context, GenTableEntity genTableEntity) { + String options = genTableEntity.getOptions(); + JSONObject paramsObj = JSON.parseObject(options); + String parentMenuId = getParentMenuId(paramsObj); + context.put("parentMenuId", parentMenuId); + } + + public static void setTreeVelocityContext(VelocityContext context, GenTableEntity genTableEntity) { + String options = genTableEntity.getOptions(); + JSONObject paramsObj = JSON.parseObject(options); + String treeCode = getTreeCode(paramsObj); + String treeParentCode = getTreeParentCode(paramsObj); + String treeName = getTreeName(paramsObj); + + context.put("treeCode", treeCode); + context.put("treeParentCode", treeParentCode); + context.put("treeName", treeName); + context.put("expandColumn", getExpandColumn(genTableEntity)); + if (paramsObj.containsKey(GenConstants.TREE_PARENT_CODE)) { + context.put("tree_parent_code", paramsObj.getString(GenConstants.TREE_PARENT_CODE)); + } + if (paramsObj.containsKey(GenConstants.TREE_NAME)) { + context.put("tree_name", paramsObj.getString(GenConstants.TREE_NAME)); + } + } + + public static void setSubVelocityContext(VelocityContext context, GenTableEntity genTableEntity) { + GenTableEntity subTable = genTableEntity.getSubTable(); + String subTableName = genTableEntity.getSubTableName(); + String subTableFkName = genTableEntity.getSubTableFkName(); + String subClassName = genTableEntity.getSubTable().getClassName(); + String subTableFkClassName = StringUtils.convertToCamelCase(subTableFkName); + + context.put("subTable", subTable); + context.put("subTableName", subTableName); + context.put("subTableFkName", subTableFkName); + context.put("subTableFkClassName", subTableFkClassName); + context.put("subTableFkclassName", StringUtils.uncapitalize(subTableFkClassName)); + context.put("subClassName", subClassName); + context.put("subclassName", StringUtils.uncapitalize(subClassName)); + context.put("subImportList", getImportList(genTableEntity.getSubTable())); + } + + /** + * 获取上级菜单ID字段 + * + * @param paramsObj + * 生成其他选项 + * @return 上级菜单ID字段 + */ + public static String getParentMenuId(JSONObject paramsObj) { + if (StringUtils.isNotEmpty(paramsObj) && paramsObj.containsKey(GenConstants.PARENT_MENU_ID) + && StrUtil.isNotBlank(paramsObj.getString(GenConstants.PARENT_MENU_ID))) { + return paramsObj.getString(GenConstants.PARENT_MENU_ID); + } + return DEFAULT_PARENT_MENU_ID; + } + + /** + * 获取树编码 + * + * @param paramsObj + * 生成其他选项 + * @return 树编码 + */ + public static String getTreeCode(JSONObject paramsObj) { + if (paramsObj.containsKey(GenConstants.TREE_CODE)) { + return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_CODE)); + } + return StringUtils.EMPTY; + } + + /** + * 获取树父编码 + * + * @param paramsObj + * 生成其他选项 + * @return 树父编码 + */ + public static String getTreeParentCode(JSONObject paramsObj) { + if (paramsObj.containsKey(GenConstants.TREE_PARENT_CODE)) { + return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_PARENT_CODE)); + } + return StringUtils.EMPTY; + } + + /** + * 获取树名称 + * + * @param paramsObj + * 生成其他选项 + * @return 树名称 + */ + public static String getTreeName(JSONObject paramsObj) { + if (paramsObj.containsKey(GenConstants.TREE_NAME)) { + return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_NAME)); + } + return StringUtils.EMPTY; + } + + public static int getExpandColumn(GenTableEntity genTableEntity) { + String options = genTableEntity.getOptions(); + JSONObject paramsObj = JSON.parseObject(options); + String treeName = paramsObj.getString(GenConstants.TREE_NAME); + int num = 0; + for (GenTableColumnEntity column : genTableEntity.getColumns()) { + if ("1".equals(column.getIsList())) { + num++; + String columnName = column.getColumnName(); + if (columnName.equals(treeName)) { + break; + } + } + } + return num; + } + + /** + * 获取模板信息 + * + * @return 模板列表 + */ + public static List getTemplateList(String tplCategory) { + List templates = new ArrayList<>(); + templates.add("vm/java/entity.java.vm"); + templates.add("vm/java/mapper.java.vm"); + templates.add("vm/java/service.java.vm"); + templates.add("vm/java/serviceImpl.java.vm"); + templates.add("vm/java/controller.java.vm"); + templates.add("vm/java/queryVo.java.vm"); + templates.add("vm/java/addVo.java.vm"); + templates.add("vm/xml/mapper.xml.vm"); + templates.add("vm/sql/sql.vm"); + templates.add("vm/js/api.js.vm"); + if (GenConstants.TPL_CRUD.equals(tplCategory)) { + templates.add("vm/vue/index.vue.vm"); + } else if (GenConstants.TPL_TREE.equals(tplCategory)) { + templates.add("vm/vue/index-tree.vue.vm"); + } else if (GenConstants.TPL_SUB.equals(tplCategory)) { + templates.add("vm/vue/index.vue.vm"); + templates.add("vm/java/sub-domain.java.vm"); + } + return templates; + } + + /** + * 获取文件名 + * + * @return 文件名称 + */ + public static String getFileName(String template, GenTableEntity genTableEntity) { + // 文件名称 + String fileName = ""; + // 包路径 + String packageName = genTableEntity.getPackageName(); + // 模块名 + String moduleName = genTableEntity.getModuleName(); + // 大写类名 + String className = genTableEntity.getClassName(); + // 业务名称 + String businessName = genTableEntity.getBusinessName(); + + // 相关生成文件目录 + String javaPath = PROJECT_PATH + "/" + StringUtils.replace(packageName, ".", "/"); + String mybatisPath = MYBATIS_PATH + "/" + moduleName; + String vuePath = "vue"; + + if (template.contains("entity.java.vm")) { + fileName = StringUtils.format("{}/module/entity/{}Entity.java", javaPath, className); + } else if (template.contains("sub-domain.java.vm") + && StringUtils.equals(GenConstants.TPL_SUB, genTableEntity.getTplCategory())) { + fileName = StringUtils.format("{}/domain/{}.java", javaPath, genTableEntity.getSubTable().getClassName()); + } else if (template.contains("mapper.java.vm")) { + fileName = StringUtils.format("{}/mapper/{}Mapper.java", javaPath, className); + } else if (template.contains("service.java.vm")) { + fileName = StringUtils.format("{}/service/I{}Service.java", javaPath, className); + } else if (template.contains("serviceImpl.java.vm")) { + fileName = StringUtils.format("{}/service/impl/{}ServiceImpl.java", javaPath, className); + } else if (template.contains("controller.java.vm")) { + fileName = StringUtils.format("{}/controller/{}Controller.java", javaPath, className); + } else if (template.contains("queryVo.java.vm")) { + fileName = StringUtils.format("{}/vo/{}QueryVo.java", javaPath, className); + } else if (template.contains("addVo.java.vm")) { + fileName = StringUtils.format("{}/vo/{}AddVo.java", javaPath, className); + } else if (template.contains("mapper.xml.vm")) { + fileName = StringUtils.format("{}/{}Mapper.xml", mybatisPath, className); + } else if (template.contains("sql.vm")) { + fileName = businessName + "Menu.sql"; + } else if (template.contains("api.js.vm")) { + fileName = StringUtils.format("{}/api/{}/{}.js", vuePath, moduleName, businessName); + } else if (template.contains("index.vue.vm")) { + fileName = StringUtils.format("{}/views/{}/{}/index.vue", vuePath, moduleName, businessName); + } else if (template.contains("index-tree.vue.vm")) { + fileName = StringUtils.format("{}/views/{}/{}/index.vue", vuePath, moduleName, businessName); + } + return fileName; + } +} + + +--- File: play-generator/src/main/resources/config.properties --- +# 数据库配置 +db.url=jdbc:mysql://122.51.20.105:3306/play-with?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai +db.driver=com.mysql.cj.jdbc.Driver +db.name=play-with +db.username=root +db.password=KdaKRZ2trpdhNePa + +# 代码生成配置 +gen.author=huchuansai +gen.packageName=com.starry.admin +gen.outputDir=./generated-code +gen.autoRemovePre=false +gen.tablePrefix=sys_ +gen.tplCategory=crud + +# 要生成的表名,多个表名用逗号分隔 +gen.tableNames=sys_role + +--- File: play-generator/src/main/resources/generator.properties --- +dataSource.url=jdbc:mysql://42.194.222.32:3306/admin?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai +dataSource.driverName=com.mysql.cj.jdbc.Driver +dataSource.username=root +dataSource.password=yx_admin +package.base=com.admin.modules + +--- File: play-generator/src/main/resources/generator.yml --- +# 代码生成 +gen: + # 作者 + author: admin + # 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool + packageName: com.starry.play + # 自动去除表前缀,默认是false + autoRemovePre: false + # 表前缀(生成类名不会包含表前缀,多个用逗号分隔) + tablePrefix: sys_ + +--- File: play-generator/src/main/resources/logback.xml --- + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + +--- File: play-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml --- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +--- File: play-generator/src/main/resources/mapper/generator/GenTableMapper.xml --- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select table_id, + table_name, + table_comment, + sub_table_name, + sub_table_fk_name, + class_name, + tpl_category, + package_name, + module_name, + business_name, + function_name, + function_author, + gen_type, + gen_path, + options, + created_by, + created_time, + updated_by, + updated_time + from gen_table + + + + + + + + + + + + + +--- File: play-generator/src/main/resources/vm/java/addVo.java.vm --- +package ${packageName}.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; +#foreach ($import in $importList) +import ${import}; +#end +import javax.validation.constraints.NotNull; +import javax.validation.constraints.NotBlank; +import java.time.LocalDateTime; + +/** + * ${functionName}添加参数VO + * + * @author ${author} + * @since ${datetime} + */ +@Data +@ApiModel(value = "${functionName}添加参数", description = "新增${functionName}信息的请求参数") +public class ${ClassName}AddVo { + +#foreach ($column in $columns) +#if(!$column.superColumn && !$column.pk) +#if($column.insert == "1") + /** + * $column.columnComment + */ +#if($column.javaType == 'Date') + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") +#if($column.isRequired == "1") + @NotNull(message = "${column.columnComment}不能为空") + @ApiModelProperty(value = "$column.columnComment", required = true, example = "2024-01-01 00:00:00", notes = "$column.columnComment") +#else + @ApiModelProperty(value = "$column.columnComment", example = "2024-01-01 00:00:00", notes = "$column.columnComment") +#end +#elseif($column.javaType == 'String') +#if($column.isRequired == "1") + @NotBlank(message = "${column.columnComment}不能为空") + @ApiModelProperty(value = "$column.columnComment", required = true, example = "示例${column.columnComment}", notes = "$column.columnComment") +#else + @ApiModelProperty(value = "$column.columnComment", example = "示例${column.columnComment}", notes = "$column.columnComment") +#end +#elseif($column.javaType == 'Integer') +#if($column.isRequired == "1") + @NotNull(message = "${column.columnComment}不能为空") + @ApiModelProperty(value = "$column.columnComment", required = true, example = "1", notes = "$column.columnComment") +#else + @ApiModelProperty(value = "$column.columnComment", example = "1", notes = "$column.columnComment") +#end +#elseif($column.javaType == 'Long') +#if($column.isRequired == "1") + @NotNull(message = "${column.columnComment}不能为空") + @ApiModelProperty(value = "$column.columnComment", required = true, example = "1", notes = "$column.columnComment") +#else + @ApiModelProperty(value = "$column.columnComment", example = "1", notes = "$column.columnComment") +#end +#else +#if($column.isRequired == "1") + @NotNull(message = "${column.columnComment}不能为空") + @ApiModelProperty(value = "$column.columnComment", required = true, notes = "$column.columnComment") +#else + @ApiModelProperty(value = "$column.columnComment", notes = "$column.columnComment") +#end +#end + private $column.javaType $column.javaField; + +#end +#end +#end +} + +--- File: play-generator/src/main/resources/vm/java/controller.java.vm --- +package ${packageName}.controller; + +import com.starry.common.enums.BusinessType; +import com.starry.common.result.R; +import com.starry.common.annotation.Log; +import ${packageName}.entity.${ClassName}Entity; +import ${packageName}.vo.${ClassName}QueryVo; +import ${packageName}.vo.${ClassName}AddVo; +import ${packageName}.service.I${ClassName}Service; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import com.baomidou.mybatisplus.core.metadata.IPage; + +/** + * ${functionName}Controller + * + * @author ${author} + * @since ${datetime} + */ +@Api(tags = "${functionName}管理", description = "${functionName}信息管理相关接口,包括查询、新增、修改、删除等操作") +@RestController +@RequestMapping("/${moduleName}/${businessName}") +public class ${ClassName}Controller { + @Resource + private I${ClassName}Service ${className}Service; + +/** + * 分页查询${functionName}列表 + */ +@ApiOperation(value = "分页查询${functionName}", notes = "分页查询${functionName}信息列表") +@ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = ${ClassName}Entity.class, responseContainer = "Page") +}) +@PreAuthorize("@customSs.hasPermission('${permissionPrefix}:list')") +@PostMapping("/listByPage") +#if($table.crud || $table.sub) +public R listByPage(@ApiParam(value = "查询条件", required = true) @Validated @RequestBody ${ClassName}QueryVo vo) { + return R.ok(${className}Service.selectByPage(vo)); +} +#elseif($table.tree) +public R listByPage(@ApiParam(value = "查询条件", required = true) @Validated @RequestBody ${ClassName}QueryVo vo) { + return R.ok(${className}Service.select${ClassName}List(vo)); +} +#end + +/** + * 查询所有${functionName}列表 + */ +@ApiOperation(value = "查询所有${functionName}", notes = "获取所有${functionName}信息列表") +@ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = ${ClassName}Entity.class, responseContainer = "List") +}) +@PreAuthorize("@customSs.hasPermission('${permissionPrefix}:list')") +@GetMapping("/listAll") +public R listAll() { + return R.ok(${className}Service.selectAll()); +} + + /** + * 获取${functionName}详细信息 + */ + @ApiOperation(value = "获取${functionName}详情", notes = "根据ID获取${functionName}详细信息") + @ApiImplicitParam(name = "${pkColumn.javaField}", value = "${functionName}ID", required = true, paramType = "path", dataType = "${pkColumn.javaType}", example = "1") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = ${ClassName}Entity.class) + }) + @PreAuthorize("@customSs.hasPermission('${permissionPrefix}:query')") + @GetMapping(value = "/{${pkColumn.javaField}}") + public R getInfo(@PathVariable("${pkColumn.javaField}") ${pkColumn.javaType} ${pkColumn.javaField}) { + return R.ok(${className}Service.select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaField})); + } + + /** + * 新增${functionName} + */ + @ApiOperation(value = "新增${functionName}", notes = "创建新的${functionName}信息") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功"), + @ApiResponse(code = 500, message = "添加失败") + }) + @PreAuthorize("@customSs.hasPermission('${permissionPrefix}:create')") + @Log(title = "${functionName}", businessType = BusinessType.INSERT) + @PostMapping("/create") + public R create(@ApiParam(value = "${functionName}信息", required = true) @Validated @RequestBody ${ClassName}AddVo vo) { + boolean success = ${className}Service.create(vo); + if (success) { + return R.ok(); + } + return R.error("添加失败"); + } + + /** + * 修改${functionName} + */ + @ApiOperation(value = "修改${functionName}", notes = "根据ID修改${functionName}信息") + @ApiImplicitParam(name = "${pkColumn.javaField}", value = "${functionName}ID", required = true, paramType = "path", dataType = "${pkColumn.javaType}", example = "1") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功"), + @ApiResponse(code = 500, message = "修改失败") + }) + @PreAuthorize("@customSs.hasPermission('${permissionPrefix}:edit')") + @Log(title = "${functionName}", businessType = BusinessType.UPDATE) + @PostMapping(value = "/update/{${pkColumn.javaField}}") + public R update(@PathVariable ${pkColumn.javaType} ${pkColumn.javaField}, @ApiParam(value = "${functionName}信息", required = true) @RequestBody ${ClassName}Entity ${className}) { + ${className}.set${pkColumn.capJavaField}(${pkColumn.javaField}); + boolean success = ${className}Service.update(${className}); + if (success) { + return R.ok(); + } + return R.error("修改失败"); + } + + /** + * 删除${functionName} + */ + @ApiOperation(value = "删除${functionName}", notes = "根据ID批量删除${functionName}信息") + @ApiImplicitParam(name = "${pkColumn.javaField}s", value = "${functionName}ID数组", required = true, paramType = "path", dataType = "${pkColumn.javaType}[]", example = "1,2,3") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = Integer.class) + }) + @PreAuthorize("@customSs.hasPermission('${permissionPrefix}:remove')") + @Log(title = "${functionName}", businessType = BusinessType.DELETE) + @DeleteMapping("/{${pkColumn.javaField}s}") + public R remove(@PathVariable ${pkColumn.javaType}[] ${pkColumn.javaField}s) { + return R.ok(${className}Service.delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaField}s)); + } +} + + +--- File: play-generator/src/main/resources/vm/java/entity.java.vm --- +package ${packageName}.entity; + +#foreach ($import in $importList) +import ${import}; +#end +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import cn.hutool.core.util.StrUtil; + +import java.util.Date; +#if($table.crud || $table.sub) +import com.starry.common.domain.BaseEntity; +#elseif($table.tree) +import com.starry.common.domain.TreeEntity; +#end + +/** + * ${functionName}对象 ${tableName} + * + * @author ${author} + * @since ${datetime} + */ + #if($table.crud || $table.sub) + #set($Entity="BaseEntity") + #elseif($table.tree) + #set($Entity="TreeEntity") + #end + @Data + @EqualsAndHashCode(callSuper = false) + @TableName("$table.tableName") + public class ${ClassName}Entity extends BaseEntity<${ClassName}Entity> { + + + + #foreach ($column in $columns) + #if(!$table.isSuperColumn($column.javaField)) + /** $column.columnComment */ + #if($column.list) + #set($parentheseIndex=$column.columnComment.indexOf("(")) + #if($parentheseIndex != -1) + #set($comment=$column.columnComment.substring(0, $parentheseIndex)) + #else + #set($comment=$column.columnComment) + #end + #if($parentheseIndex != -1) + @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()") + #elseif($column.javaType == 'Date') + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "${comment}", width = 30, dateFormat = "yyyy-MM-dd") + #else + @Excel(name = "${comment}") + #end + #end + private $column.javaType $column.javaField; + + #end + #end + #if($table.sub) + /** $table.subTable.functionName信息 */ + private List<${subClassName}> ${subclassName}List; + + #end + +} + + +--- File: play-generator/src/main/resources/vm/java/mapper.java.vm --- +package ${packageName}.mapper; + + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import ${packageName}.entity.${ClassName}; +#if($table.sub) +import ${packageName}.entity .${subClassName}; +#end + +/** + * ${functionName}Mapper接口 + * + * @author ${author} + * @since ${datetime} + */ +public interface ${ClassName}Mapper extends BaseMapper<${ClassName}Entity> { + + + #if($table.sub) + + /** + * 批量删除${subTable.functionName} + * @param ${pkColumn.javaField}s 需要删除的数据主键集合 + * @return 结果 + */ + int delete${subClassName}By${subTableFkClassName}s(${pkColumn.javaType}[] ${pkColumn.javaField}s); + + /** + * 批量新增${subTable.functionName} + * @param ${subclassName}List ${subTable.functionName}列表 + * @return 结果 + */ + int batch${subClassName}(List<${subClassName}> ${subclassName}List); + + + #end +} + + +--- File: play-generator/src/main/resources/vm/java/module.module.vo.java.vm --- +package ${packageName}.entity; + +#foreach ($import in $importList) +import ${import}; +#end +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.util.Date; +#if($table.crud || $table.sub) +import com.starry.common.domain.BaseEntity; +#elseif($table.tree) +import com.starry.common.domain.TreeEntity; +#end + +/** + * ${functionName}对象 ${tableName} + * + * @author ${author} + * @since ${datetime} + */ +#if($table.crud || $table.sub) + #set($Entity="BasePageEntity") +#elseif($table.tree) + #set($Entity="TreeEntity") +#end +@Data +@EqualsAndHashCode(callSuper = false) +public class ${ClassName} extends ${Entity}{ + +private static final long serialVersionUID = 1L; + + #foreach ($column in $columns) + #if(!$table.isSuperColumn($column.javaField)) + /** $column.columnComment */ + #if($column.list) + #set($parentheseIndex=$column.columnComment.indexOf("(")) + #if($parentheseIndex != -1) + #set($comment=$column.columnComment.substring(0, $parentheseIndex)) + #else + #set($comment=$column.columnComment) + #end + #if($parentheseIndex != -1) + @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()") + #elseif($column.javaType == 'Date') + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "${comment}", width = 30, dateFormat = "yyyy-MM-dd") + #else + @Excel(name = "${comment}") + #end + #end + private $column.javaType $column.javaField; + + #end + #end + #if($table.sub) + /** $table.subTable.functionName信息 */ + private List<${subClassName}> ${subclassName}List; + + #end + +} + + +--- File: play-generator/src/main/resources/vm/java/queryVo.java.vm --- +package ${packageName}.vo; + +import com.starry.common.domain.BasePageEntity; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +#foreach ($import in $importList) +import ${import}; +#end +#if($table.tree) +import java.util.List; +#end + +/** + * ${functionName}查询参数VO + * + * @author ${author} + * @since ${datetime} + */ +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel(value = "${functionName}查询参数", description = "查询${functionName}信息的条件参数") +public class ${ClassName}QueryVo extends BasePageEntity { + +#foreach ($column in $columns) +#if(!$column.superColumn) +#if($column.query) + /** + * $column.columnComment + */ +#if($column.javaType == 'Date') + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "$column.columnComment", example = "2024-01-01 00:00:00", notes = "$column.columnComment") +#elseif($column.javaType == 'String') + @ApiModelProperty(value = "$column.columnComment", example = "示例${column.columnComment}", notes = "$column.columnComment") +#elseif($column.javaType == 'Integer') + @ApiModelProperty(value = "$column.columnComment", example = "1", notes = "$column.columnComment") +#elseif($column.javaType == 'Long') + @ApiModelProperty(value = "$column.columnComment", example = "1", notes = "$column.columnComment") +#else + @ApiModelProperty(value = "$column.columnComment", notes = "$column.columnComment") +#end + private $column.javaType $column.javaField; + +#end +#end +#end +} + +--- File: play-generator/src/main/resources/vm/java/service.java.vm --- +package ${packageName}.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import ${packageName}.entity .${ClassName}; + +/** + * ${functionName}Service接口 + * + * @author ${author} + * @since ${datetime} + */ +public interface I${ClassName}Service extends IService<${ClassName}Entity> { + /** + * 查询${functionName} + * @param ${pkColumn.javaField} ${functionName}主键 + * @return ${functionName} + */ + ${ClassName}Entity select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField}); + + /** + * 查询${functionName}列表 + * @param ${className} ${functionName} + * @return ${functionName}集合 + */ + IPage<${ClassName}Entity> select${ClassName}ByPage(${ClassName}Entity ${className}); + + /** + * 新增${functionName} + * @param ${className} ${functionName} + * @return 结果 + */ + boolean create(${ClassName}Entity ${className}); + + /** + * 修改${functionName} + * @param ${className} ${functionName} + * @return 结果 + */ + boolean update(${ClassName}Entity ${className}); + + /** + * 批量删除${functionName} + * + * @param ${pkColumn.javaField}s 需要删除的${functionName}主键集合 + * @return 结果 + */ + int delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaType}[] ${pkColumn.javaField}s); + + /** + * 删除${functionName}信息 + * + * @param ${pkColumn.javaField} ${functionName}主键 + * @return 结果 + */ + int delete${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField}); +} + + +--- File: play-generator/src/main/resources/vm/java/serviceImpl.java.vm --- +package ${packageName}.service.impl; + +import java.util.Arrays; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.starry.common.utils.IdUtils; +import cn.hutool.core.util.StrUtil; + +import javax.annotation.Resource; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import org.springframework.stereotype.Service; + #if($table.sub) + import java.util.ArrayList; + + import com.starry.common.utils.StringUtils; + import org.springframework.transaction.annotation.Transactional; + import ${packageName}.entity.${subClassName}; + #end +import ${packageName}.mapper.${ClassName}Mapper; +import ${packageName}.entity.${ClassName}; +import ${packageName}.service.I${ClassName}Service; + +/** + * ${functionName}Service业务层处理 + * + * @author ${author} + * @since ${datetime} + */ +@Service +public class ${ClassName}ServiceImpl extends ServiceImpl<${ClassName}Mapper, ${ClassName}Entity> implements I${ClassName}Service { + @Resource + private ${ClassName}Mapper ${className}Mapper; + + /** + * 查询${functionName} + * @param ${pkColumn.javaField} ${functionName}主键 + * @return ${functionName} + */ + @Override + public ${ClassName}Entity select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField}) { + return this.baseMapper.selectById(id); + } + + /** + * 查询${functionName}列表 + * @param ${className} ${functionName} + * @return ${functionName} + */ + @Override + public IPage<${ClassName}Entity> select${ClassName}ByPage(${ClassName}Entity ${className}) { + Page<${ClassName}Entity> page = new Page<>(1, 10); + return this.baseMapper.selectPage(page, new LambdaQueryWrapper<${ClassName}Entity>()); + } + + /** + * 新增${functionName} + * @param ${className} ${functionName} + * @return 结果 + */ + #if($table.sub) + @Transactional(rollbackFor = Exception.class) + #end + @Override + public boolean create(${ClassName}Entity ${className}) { + #if($table.sub) + int rows = ${className}Mapper.insert${ClassName}(${className}); + insert${subClassName}(${className}); + return rows; + #else + if (StrUtil.isBlankIfStr(${className}.getId())){ + ${className}.setId(IdUtils.getUuid()); + } + return save(${className}); + #end + } + + /** + * 修改${functionName} + * @param ${className} ${functionName} + * @return 结果 + */ + #if($table.sub) + @Transactional(rollbackFor = Exception.class) + #end + @Override + public boolean update(${ClassName}Entity ${className}) { + #if($table.sub) + ${className}Mapper.delete${subClassName}By${subTableFkClassName}(${className}.get${pkColumn.capJavaField}()) + ; + insert${subClassName}(${className}); + #end + return updateById(${className}); + } + + /** + * 批量删除${functionName} + * @param ${pkColumn.javaField}s 需要删除的${functionName}主键 + * @return 结果 + */ + #if($table.sub) + @Transactional(rollbackFor = Exception.class) + #end + @Override + public int delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaType}[] ${pkColumn.javaField}s) { + #if($table.sub) + ${className}Mapper.delete${subClassName}By${subTableFkClassName}s(${pkColumn.javaField}s); + #end + return ${className}Mapper.deleteBatchIds(Arrays.asList(${pkColumn.javaField}s)); + } + + /** + * 删除${functionName}信息 + * @param ${pkColumn.javaField} ${functionName}主键 + * @return 结果 + */ + #if($table.sub) + @Transactional(rollbackFor = Exception.class) + #end + @Override + public int delete${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField}) { + #if($table.sub) + ${className}Mapper.delete${subClassName}By${subTableFkClassName}(${pkColumn.javaField}); + #end + return ${className}Mapper.deleteById(${pkColumn.javaField}); + } + #if($table.sub) + + /** + * 新增${subTable.functionName}信息 + * @param ${className} ${functionName}对象 + */ + public void insert${subClassName}(${ClassName}Entity ${className}) { + List<${subClassName}> ${subclassName}List = ${className}.get${subClassName}List(); + ${pkColumn.javaType} ${pkColumn.javaField} = ${className}.get${pkColumn.capJavaField}(); + if (StringUtils.isNotNull(${subclassName}List)) { + List<${subClassName}> list = new ArrayList<${subClassName}>(); + for (${subClassName} ${subclassName} :${subclassName}List) + { + ${subclassName}.set${subTableFkClassName}(${pkColumn.javaField}); + list.add(${subclassName}); + } + if (!list.isEmpty()) { + ${className}Mapper.batch${subClassName}(list); + } + } + } + #end +} + + +--- File: play-generator/src/main/resources/vm/js/api.js.vm --- +import request from '@/utils/request' + +// 查询${functionName}列表 +export function list${BusinessName}(query) { + return request({ + url: '/${moduleName}/${businessName}/list', + method: 'get', + params: query + }) +} + +// 查询${functionName}详细 +export function get${BusinessName}(${pkColumn.javaField}) { + return request({ + url: '/${moduleName}/${businessName}/' + ${pkColumn.javaField}, + method: 'get' + }) +} + +// 新增${functionName} +export function add${BusinessName}(data) { + return request({ + url: '/${moduleName}/${businessName}/create', + method: 'post', + data: data + }) +} + +// 修改${functionName} +export function update${BusinessName}(${pkColumn.javaField}, data) { + return request({ + url: '/${moduleName}/${businessName}/update/' + ${pkColumn.javaField}, + method: 'post', + data: data + }) +} + +// 删除${functionName} +export function del${BusinessName}(${pkColumn.javaField}) { + return request({ + url: '/${moduleName}/${businessName}/' + ${pkColumn.javaField}, + method: 'delete' + }) +} + + +--- File: play-generator/src/main/resources/vm/sql/sql.vm --- +-- 菜单 SQL +insert into sys_menu (menu_name, parent_id, sort, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, created_by, created_time, updated_by, updated_time) +values('${functionName}', '${parentMenuId}', '1', '${businessName}', '${moduleName}/${businessName}/index', 1, 0, 'C', '0', '0', '${permissionPrefix}:list', '#', 'admin', sysdate(), '', null); + +-- 按钮父菜单ID +SELECT @parentId := LAST_INSERT_ID(); + +-- 按钮 SQL +insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, created_by, created_time, updated_by, updated_time) +values('${functionName}查询', @parentId, '1', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:query', '#', 'admin', sysdate(), '', null); + +insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, created_by, created_time, updated_by, updated_time) +values('${functionName}新增', @parentId, '2', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:create', '#', 'admin', sysdate(), '', null); + +insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, created_by, created_time, updated_by, updated_time) +values('${functionName}修改', @parentId, '3', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:edit', '#', 'admin', sysdate(), '', null); + +insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, created_by, created_time, updated_by, updated_time) +values('${functionName}删除', @parentId, '4', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:remove', '#', 'admin', sysdate(), '', null); + +insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, created_by, created_time, updated_by, updated_time) +values('${functionName}导出', @parentId, '5', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:export', '#', 'admin', sysdate(), '', null); + +--- File: play-generator/src/main/resources/vm/vue/index-tree.vue.vm --- + + + + + +--- File: play-generator/src/main/resources/vm/vue/index.vue.vm --- + + + + + +--- File: play-generator/src/main/resources/vm/xml/mapper.xml.vm --- + + + + + + #foreach ($column in $columns) + + #end + + #if($table.sub) + + + + + + + #foreach ($column in $subTable.columns) + + #end + + #end + + + select#foreach($column in $columns) $column.columnName#if($foreach.count != $columns.size()),#end#end + from ${tableName} + + + + + + + + #if($table.sub) + + + delete from ${subTableName} where ${subTableFkName} in + + #{${subTableFkclassName}} + + + + + delete + from ${subTableName} where ${subTableFkName} = #{${subTableFkclassName}} + + + + insert into ${subTableName} + (#foreach($column in $subTable.columns) $column.columnName#if($foreach.count != $subTable.columns.size()) + ,#end#end) values + + (#foreach($column in $subTable.columns) #{item.$column.javaField + }#if($foreach.count != $subTable.columns.size()),#end#end) + + + #end + + +--- File: pom.xml --- + + + 4.0.0 + + + org.springframework.boot + spring-boot-starter-parent + 2.5.4 + + + + com.starry + play-with + 1.0 + pom + + + play-admin + play-common + play-generator + + + + + 11 + + 3.5.3.2 + 1.4.10 + + 2.0.7 + + 0.9.0 + + 2.14.5 + + 5.8.26 + + 1.2.21 + + 2.15.1 + + 2.0.47 + + 2.1 + + 6.5.0 + + 2.2.11 + + 4.6.0 + 3.1.1 + + 1.18.30 + + 7.15.0 + + + 5.6.205 + + 3.17.4 + + 3.1.1 + + 2.10.1 + 3.24.3 + 2.2.5 + + + + + + + + com.baomidou + mybatis-plus-boot-starter + ${mybatis-plus.version} + + + com.github.yulichang + mybatis-plus-join-boot-starter + ${mybatis-plus-join.version} + + + + + cn.hutool + hutool-all + ${hutool.version} + + + + com.alibaba + druid-spring-boot-starter + ${druid-version} + + + + com.github.xiaoymin + knife4j-spring-boot-starter + ${swagger.version} + + + + io.jsonwebtoken + jjwt + ${jwt.version} + + + + com.alibaba + transmittable-thread-local + ${transmittable-thread-local.version} + + + + commons-io + commons-io + ${commom-io.version} + + + + com.alibaba.fastjson2 + fastjson2 + ${fastjson2-version} + + + + org.apache.velocity + velocity-engine-core + ${velocity-version} + + + + com.github.oshi + oshi-core + ${oshi-version} + + + + com.alibaba + easyexcel + ${easyexcel.version} + + + + com.google.code.gson + gson + ${gson-version} + + + + com.github.gavlyukovskiy + p6spy-spring-boot-starter + 1.9.1 + + + + + + com.starry + play-common + 1.0 + + + + com.starry + play-generator + 1.0 + + + + com.starry + play-admin + 1.0 + + + com.aliyun.oss + aliyun-sdk-oss + ${aliyun-oss.version} + + + + + + com.github.binarywang + wx-java-mp-spring-boot-starter + ${weixin-java.version} + + + + com.github.wxpay + wxpay-sdk + 0.0.3 + + + + + org.redisson + redisson-spring-boot-starter + ${redisson.version} + + + + com.baomidou + lock4j-redisson-spring-boot-starter + ${lock4j.version} + + + + org.springframework.boot + spring-boot-maven-plugin + 2.7.9 + + + + ws.schild + jave-core + ${ws-schild.version} + + + + ws.schild + jave-nativebin-linux64 + ${ws-schild.version} + + + com.squareup.okio + okio + 3.4.0 + + + + + org.lionsoul + ip2region + 1.7.2 + + + + + org.flywaydb + flyway-core + ${flyway.version} + + + + + + + + + + com.diffplug.spotless + spotless-maven-plugin + 2.43.0 + + + + + + + true + 4 + + + + + + src/main/java/**/*.java + src/test/java/**/*.java + + + + + + + check + + validate + + + + + + + + + + +--- File: todo.md --- + + + +[] DB migration +[] Domain migration + diff --git a/play-admin/src/main/java/com/starry/admin/modules/weichat/controller/WxClerkController.java b/play-admin/src/main/java/com/starry/admin/modules/weichat/controller/WxClerkController.java index b99e1dc..bddf2a4 100644 --- a/play-admin/src/main/java/com/starry/admin/modules/weichat/controller/WxClerkController.java +++ b/play-admin/src/main/java/com/starry/admin/modules/weichat/controller/WxClerkController.java @@ -114,7 +114,7 @@ public class WxClerkController { * 店员获取个人业绩信息 */ @ApiOperation(value = "查询店员业绩", notes = "店员获取个人业绩信息") - @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @ApiResponses({ @ApiResponse(code = 200, message = "操作成功") }) @ClerkUserLogin @PostMapping("/user/queryPerformanceInfo") public R queryPerformanceInfo( @@ -133,7 +133,7 @@ public class WxClerkController { * 店员获取个人等级信息 */ @ApiOperation(value = "查询店员等级", notes = "店员获取个人等级信息") - @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = PlayClerkLevelInfoReturnVo.class)}) + @ApiResponses({ @ApiResponse(code = 200, message = "操作成功", response = PlayClerkLevelInfoReturnVo.class) }) @ClerkUserLogin @GetMapping("/user/queryLevelInfo") public R queryLevelInfo() { @@ -158,8 +158,8 @@ public class WxClerkController { * 店员获取个人信息 */ @ApiOperation(value = "查询店员信息", notes = "店员获取个人详细信息") - @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = PlayClerkUserInfoResultVo.class), - @ApiResponse(code = 500, message = "用户不存在")}) + @ApiResponses({ @ApiResponse(code = 200, message = "操作成功", response = PlayClerkUserInfoResultVo.class), + @ApiResponse(code = 500, message = "用户不存在") }) @ClerkUserLogin @GetMapping("/user/queryById") public R queryById() { @@ -172,7 +172,7 @@ public class WxClerkController { } @ApiOperation(value = "发送验证码", notes = "店员绑定手机号发送验证码") - @ApiResponses({@ApiResponse(code = 200, message = "操作成功", response = String.class)}) + @ApiResponses({ @ApiResponse(code = 200, message = "操作成功", response = String.class) }) @ClerkUserLogin @PostMapping("/user/sendCode") public R sendCode( @@ -186,7 +186,7 @@ public class WxClerkController { } @ApiOperation(value = "绑定手机号", notes = "店员绑定手机号") - @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "验证码错误")}) + @ApiResponses({ @ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "验证码错误") }) @ClerkUserLogin @PostMapping("/user/bindCode") public R bindCode( @@ -210,8 +210,8 @@ public class WxClerkController { } @ApiOperation(value = "店员申请", notes = "用户申请成为店员") - @ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "系统错误,用户不存在"), - @ApiResponse(code = 500, message = "当前用户已经是店员"), @ApiResponse(code = 500, message = "已有申请未审核")}) + @ApiResponses({ @ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "系统错误,用户不存在"), + @ApiResponse(code = 500, message = "当前用户已经是店员"), @ApiResponse(code = 500, message = "已有申请未审核") }) @ClerkUserLogin @PostMapping("/user/add") @Transactional(rollbackFor = Exception.class) @@ -240,7 +240,7 @@ public class WxClerkController { } @ApiOperation(value = "更新头像", notes = "店员更新头像") - @ApiResponses({@ApiResponse(code = 200, message = "操作成功")}) + @ApiResponses({ @ApiResponse(code = 200, message = "操作成功") }) @ClerkUserLogin @PostMapping("/user/updateAvatar") public R updateAvatar(@ApiParam(value = "头像信息", required = true) @Validated @RequestBody PlayClerkUserAvatarVo vo) { @@ -340,13 +340,34 @@ public class WxClerkController { * 分页获取店员列表 * * @param vo - * PlayClerkUserInfoQueryVo + * PlayClerkUserInfoQueryVo * @return 店员列表 */ @PostMapping("/user/queryByPage") public R queryByPage(@RequestBody PlayClerkUserInfoQueryVo vo) { IPage page = playClerkUserInfoService.selectByPage(vo, customUserService.getLoginUserId()); + // 对记录进行排序,优先显示在线店员 + if (page.getRecords() != null && !page.getRecords().isEmpty()) { + page.getRecords().sort((clerk1, clerk2) -> { + // 在线状态优先级:"1"(在线)排在"0"(离线)之前 + String onlineState1 = clerk1.getOnlineState(); + String onlineState2 = clerk2.getOnlineState(); + // 如果两者在线状态相同,保持原有顺序 + if (onlineState1 != null && onlineState2 != null) { + // 反向比较,使"1"排在"0"之前 + return onlineState2.compareTo(onlineState1); + } + // 处理空值情况:将null视为离线状态("0") + if (onlineState1 == null && onlineState2 == null) + return 0; + if (onlineState1 == null) + return 1; // null视为离线,排在在线之后 + if (onlineState2 == null) + return -1; // null视为离线,排在在线之后 + return onlineState2.compareTo(onlineState1); + }); + } return R.ok(page); } @@ -369,7 +390,7 @@ public class WxClerkController { * 获取店员礼物信息 * * @param id - * 店员ID + * 店员ID * @return 店员礼物 */ @@ -405,7 +426,7 @@ public class WxClerkController { * 获取店员价格 * * @param id - * 店员ID + * 店员ID * @return 店员价格 */ @GetMapping("/user/queryPriceById") @@ -417,7 +438,7 @@ public class WxClerkController { * 店员分页查询本人订单列表 * * @param vo - * 订单列表分页查询对象 + * 订单列表分页查询对象 * @return com.starry.common.result.R * @author admin * @since 2024/5/8 15:57 @@ -434,7 +455,7 @@ public class WxClerkController { * 店员查询本人订单详情 * * @param id - * 订单ID + * 订单ID * @return com.starry.common.result.R * @author admin * @since 2024/5/8 15:57 @@ -451,7 +472,7 @@ public class WxClerkController { * 店员-接单 * * @param id - * 订单ID + * 订单ID * @return com.starry.common.result.R * @author admin * @since 2024/5/8 15:57 @@ -468,7 +489,7 @@ public class WxClerkController { * 店员-开始订单 * * @param id - * 订单ID + * 订单ID * @return com.starry.common.result.R * @author admin * @since 2024/5/8 15:57 @@ -484,7 +505,7 @@ public class WxClerkController { * 店员-取消订单 * * @param vo - * 取消订单传参 + * 取消订单传参 * @return com.starry.common.result.R * @author admin * @since 2024/5/8 15:57 @@ -501,7 +522,7 @@ public class WxClerkController { * 分页获取店员评价(订单评价) * * @param vo - * 店员评价查询对象 + * 店员评价查询对象 * @return 店员评价 */ @PostMapping("/user/queryEvaluateByPage")