功能完成

main
王宇航 2023-11-27 09:51:57 +08:00
parent 2ed2056775
commit 4d7432786d
183 changed files with 11979 additions and 34 deletions

147
.gitignore vendored Normal file
View File

@ -0,0 +1,147 @@
# Created by .ignore support plugin (hsz.mobi)
### Maven template
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
.mvn/wrapper/maven-wrapper.jar
.idea
.editorconfig
.sdkmanrc
### Java template
# 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*
### Example user template template
### Example user template
# IntelliJ project files
.idea
*.iml
out
gen
### macOS template
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 hb730
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,34 +0,0 @@
# Boot-Admin V5
基于Java17,SpringBoot3,Spring security6,Mysql8,MybatisPlus的前后端分离的后台管理系统
| | | |
|---------------------------------------------------------------------------------|--------------------------------------------------------------------------------|--------------------------------------------------------------------------------|
| ![](https://github.com/hb0730/boot-admin/raw/v5/doc/asset/boot-admin_v5_1.png) | ![](https://github.com/hb0730/boot-admin/raw/v5/doc/asset/boot-admin_v5_2.png) | ![](https://github.com/hb0730/boot-admin/raw/v5/doc/asset/boot-admin_v5_2.png) |
| ![](https://github.com/hb0730/boot-admin/raw/v5/doc/asset/boot-admin_v5_3.png) | ![](https://github.com/hb0730/boot-admin/raw/v5/doc/asset/boot-admin_v5_5.png) | ![](https://github.com/hb0730/boot-admin/raw/v5/doc/asset/boot-admin_v5_6.png) |
## 开源地址
| | 后端 | 前端 |
|--------|--------------------------------------|------------------------------------------|
| Github | https://github.com/hb0730/boot-admin | https://github.com/hb0730/boot-admin-ui |
| Gitee | https://gitee.com/hb0730/boot-admin/ | https://gitee.com/hb0730/boot-admin-ui |
## 特征
* 前端采用vue-pure-admin (Vue3,Element-Plus,Vite)
* 支持动态菜单与路由
* 自定义权限认证与Security的结合使用
## 在线预览
https://boot.hb0730.com/next
**admin/123456 能不能访问凭运气,Java Server: HK,Redis Server: HK,Mysql Server:HK**
## SQL 所在地
> doc/sql/boot-admin.sql
## question
* 为什么实时请求routes
>1. 首先我们后端已经缓存了当前用户路由
>2. 我们采用EventListener,当管理者更改了用户权限能够实时响应,
>3. 如果要前端缓存,可以开启前端配置: `CachingAsyncRoutes`

19
docker/Dockerfile Normal file
View File

@ -0,0 +1,19 @@
FROM eclipse-temurin:17-jre as builder
WORKDIR application
ARG JAR_FILE=*.jar
COPY ${JAR_FILE} application.jar
RUN java -Djarmode=layertools -jar application.jar extract
FROM eclipse-temurin:17-jre
WORKDIR application
COPY --from=builder application/dependencies/ ./
COPY --from=builder application/spring-boot-loader/ ./
COPY --from=builder application/snapshot-dependencies/ ./
COPY --from=builder application/application/ ./
ENV JAVA_OPTS="-server -Xms2048m -Xmx2048m -Xmn512m -XX:MaxMetaspaceSize=512m" \
TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
ENTRYPOINT java $JAVA_OPTS org.springframework.boot.loader.JarLauncher

View File

@ -0,0 +1,25 @@
version: '3'
services:
mysql8_server:
image: mysql:8
container_name: boot_admin_mysql8_server
ports:
- 3306:3306
volumes:
- ./data/mysql:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: 1234
MYSQL_DATABASE: boot-admin
TZ: Asia/Shanghai
redis_server:
image: redis:alpine
container_name: boot_admin_redis_server
ports:
- 6379:6379
volumes:
# redis配置
- ./conf/redis:/usr/local/etc/redis
# redis 数据挂载
- ./data/redis:/data
command: redis-server /usr/local/etc/redis/redis.conf

12
docker/docker-compose.yml Normal file
View File

@ -0,0 +1,12 @@
version: '3'
services:
next_boot-admin:
image: boot-admin:v5
container_name: next_boot-admin
ports:
- '8089:8088'
environment:
JAVA_OPTS: '-server -Dspring.profiles.active=prod -Dspring.config.additional-location=/application/conf/'
TZ: "Asia/Shanghai"
volumes:
- ./conf:/application/conf

192
pom.xml Normal file
View File

@ -0,0 +1,192 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.hb0730</groupId>
<artifactId>boot-admin</artifactId>
<version>5.0.0-SNAPSHOT</version>
<name>boot-admin</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<hutool.version>5.8.11</hutool.version>
<bouncycastle.version>1.72</bouncycastle.version>
<!-- <lombok.version>1.18.24</lombok.version>-->
<mybatis-plus.version>3.5.3.1</mybatis-plus.version>
<hb0730-jsons.version>1.0.3</hb0730-jsons.version>
<knife4j.version>4.1.0</knife4j.version>
<jwt.version>4.2.2</jwt.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</dependency>
<!--jwt-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>${jwt.version}</version>
</dependency>
<!--hutool-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
<version>${hutool.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-extra</artifactId>
<version>${hutool.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-crypto</artifactId>
<version>${hutool.version}</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15to18</artifactId>
<version>${bouncycastle.version}</version>
</dependency>
<!--jsons-->
<dependency>
<groupId>com.hb0730</groupId>
<artifactId>jsons</artifactId>
<version>${hb0730-jsons.version}</version>
</dependency>
<!--swagger-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
<version>${knife4j.version}</version>
</dependency>
<!--test-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
<version>4.3.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.10.2</version>
</dependency>
<dependency>
<groupId>cn.mrzin</groupId>
<artifactId>tool-wx</artifactId>
<version>1.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.7</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>14</source>
<target>14</target>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${project.parent.version}</version>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.json</include>
<include>**/*.ftl</include>
</includes>
</resource>
</resources>
</build>
</project>

View File

@ -0,0 +1,24 @@
package com.hb0730.boot.admin;
import cn.hutool.extra.spring.EnableSpringUtil;
import com.hb0730.boot.admin.base.BootAdminApp;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
/**
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/1/11
*/
@SpringBootApplication
@EnableSpringUtil
@EnableAsync
public class BootAdminApplication extends BootAdminApp {
public static void main(String[] args) {
bootstrap(BootAdminApplication.class, args);
}
@Override
protected void doSomethingAfterBooted() {
}
}

View File

@ -0,0 +1,62 @@
package com.hb0730.boot.admin.base;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.env.Environment;
/**
* SPRING 启动器
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/1/11
*/
@Slf4j
public class BootAdminApp implements ApplicationContextAware, ApplicationRunner {
private ApplicationContext context;
public static void bootstrap(Class<?> clazz, String... args) {
log.debug("{} 启动开始 ...", clazz.getCanonicalName());
SpringApplication application = new SpringApplication(clazz);
application.setBannerMode(Banner.Mode.CONSOLE);
application.run(args);
log.debug("{} 启动完成 ...", clazz.getCanonicalName());
}
@Override
public void run(ApplicationArguments args) throws Exception {
//启动后做点啥
doSomethingAfterBooted();
//输出启动完成信息
doShowBootedInfs();
}
/**
* 启动后做点啥
*/
protected void doSomethingAfterBooted() {
}
/**
* 输出启动完成信息
*/
protected void doShowBootedInfs() {
Environment env = context.getEnvironment();
log.info("启动完成 -> {}:{}",
env.getProperty("server.servlet.context-path"),
env.getProperty("server.port")
);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
}

View File

@ -0,0 +1,17 @@
package com.hb0730.boot.admin.base;
/**
* 常量池
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/1/30
*/
public interface BootAdminConst {
String CHARSET_NAME_UTF8 = "utf-8";
/**
* 访问令牌头
*/
String X_ACCESS_TOKEN = "X-Access-Token";
}

View File

@ -0,0 +1,37 @@
package com.hb0730.boot.admin.base;
import cn.hutool.extra.spring.SpringUtil;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.lang.annotation.Annotation;
import java.util.Map;
/**
* Spring ApplicationContext
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/1/11
*/
@Component
public class BootAdminContext extends SpringUtil {
/**
* 获取HttpServletRequest
*/
public static HttpServletRequest getHttpServletRequest() {
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
}
/**
* 根据BEAN注解获取BEAN
*
* @param annotationType BEAN注解
* @return BEANS
*/
public static Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) {
return getApplicationContext().getBeansWithAnnotation(annotationType);
}
}

View File

@ -0,0 +1,239 @@
package com.hb0730.boot.admin.base;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
/**
* 接口返回数据格式
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/1/11
*/
@Data
@EqualsAndHashCode
public class R<T> implements Serializable {
public static final Integer OK_200 = 200;
public static final Integer SERVER_ERROR_500 = 500;
/**
* 默认失败 状态码
*/
public static final Integer SUC_0 = 0;
/**
* 成功状态码
*/
public static final Integer SUC_1 = 1;
/**
* 成功标志
*/
@Schema(description = "成功标识")
private boolean success = true;
/**
* 返回处理消息
*/
@Schema(description = "返回处理消息")
private String message = "操作成功!";
/**
* 返回代码
*/
@Schema(description = "返回代码")
private Integer code = 0;
/**
* 返回数据对象 data
*/
@Schema(description = "返回数据对象")
private T result;
/**
* 时间戳
*/
@Schema(description = "时间戳")
private long timestamp = System.currentTimeMillis();
public R() {
}
public R(T result) {
this.code = SUC_1;
this.result = result;
}
public R(boolean success, String message) {
this.success = success;
this.message = message;
if (success) {
this.code = SUC_1;
} else {
this.code = SUC_0;
}
}
/**
* 接口返回数据:成功
*
* @param message 消息
* @return 接口返回数据:成功
*/
public R<T> success(String message) {
this.message = message;
this.code = OK_200;
this.success = true;
return this;
}
/**
* 接口返回数据:失败,code: 500
*
* @param message 消息
* @return 接口返回数据:失败
*/
public R<T> error(String message) {
return error(SERVER_ERROR_500, message);
}
/**
* 接口返回数据:失败
*
* @param code 代码
* @param message 消息
* @param <T> .
* @return 接口返回数据:失败
*/
public static <T> R<T> error(int code, String message) {
R<T> r = new R<>();
r.setCode(code);
r.setMessage(message);
r.setSuccess(false);
return r;
}
/**
* 接口返回数据:成功
*
* @param <T> .
* @return 接口返回数据:成功
*/
public static <T> R<T> OK() {
return OK("成功!", null);
}
/**
* 接口返回数据:成功
*
* @param data 数据
* @param <T> .
* @return 接口返回数据:成功
*/
public static <T> R<T> OK(T data) {
return OK("成功", data);
}
/**
* 接口返回数据:成功
*
* @param code 代码
* @param message 消息
* @param <T> .
* @return 接口返回数据:成功
*/
public static <T> R<T> OK(int code, String message) {
return OK(code, message, null);
}
/**
* 接口返回数据:成功
*
* @param message 消息
* @param <T> .
* @return 接口返回数据:成功
*/
public static <T> R<T> OK(String message) {
return OK(OK_200, message, null);
}
/**
* 接口返回数据:成功
*
* @param message 消息
* @param data 数据
* @param <T> .
* @return 接口返回数据:成功
*/
public static <T> R<T> OK(String message, T data) {
return OK(OK_200, message, data);
}
/**
* 接口返回数据:成功
*
* @param code 代码
* @param message 消息
* @param data 数据
* @param <T> .
* @return 接口返回数据:成功
*/
public static <T> R<T> OK(int code, String message, T data) {
R<T> r = new R<>();
r.setSuccess(true);
r.setCode(code);
r.setMessage(message);
r.setResult(data);
return r;
}
/**
* 接口返回数据:失败
*
* @param message 消息
* @param <T> .
* @return 接口返回数据:失败
*/
public static <T> R<T> NG(String message) {
return NG(message, null);
}
/**
* 接口返回数据:失败
*
* @param message 消息
* @param data 数据
* @param <T> .
* @return 接口返回数据:失败
*/
public static <T> R<T> NG(String message, T data) {
return NG(SERVER_ERROR_500, message, data);
}
/**
* 接口返回数据:失败
*
* @param code 代码
* @param message 消息
* @param <T> .
* @return 接口返回数据:失败
*/
public static <T> R<T> NG(int code, String message) {
return NG(code, message, null);
}
/**
* 接口返回数据:失败
*
* @param code 代码
* @param message 消息
* @param data 数据
* @param <T> .
* @return 接口返回数据:失败
*/
public static <T> R<T> NG(int code, String message, T data) {
R<T> r = new R<>();
r.setSuccess(false);
r.setCode(code);
r.setMessage(message);
r.setResult(data);
return r;
}
}

View File

@ -0,0 +1,29 @@
package com.hb0730.boot.admin.base.exception;
/**
* 系统异常
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/1/30
*/
public class BootAdminException extends RuntimeException {
public BootAdminException() {
super();
}
public BootAdminException(String message) {
super(message);
}
public BootAdminException(String message, Throwable cause) {
super(message, cause);
}
public BootAdminException(Throwable cause) {
super(cause);
}
protected BootAdminException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}

View File

@ -0,0 +1,74 @@
package com.hb0730.boot.admin.base.util;
import cn.hutool.crypto.Mode;
import cn.hutool.crypto.Padding;
import cn.hutool.crypto.symmetric.AES;
import jakarta.annotation.Nonnull;
import lombok.Data;
import java.nio.charset.StandardCharsets;
/**
* AES 加密
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/1/30
*/
public class AesEncryptUtil {
@Data
public static class SecKey {
public static String key = "1234567890adbcde"; // 长度为16个字符
public static String iv = "1234567890hjlkew"; // 长度为16个字符
}
/**
* 加密方法,使用默认的密钥与偏移向量
*
* @param data 要加密的数据
* @return 加密的结果
*/
public static String encrypt(String data) {
return encrypt(data, SecKey.key, SecKey.iv);
}
/**
* 加密方式
*
* @param data 要加密的数据
* @param key 密钥
* @param iv 偏移向量,加盐
* @return 加密的结果
*/
public static String encrypt(String data, @Nonnull String key, @Nonnull String iv) {
AES aes = new AES(Mode.CBC, Padding.PKCS5Padding, key.getBytes(StandardCharsets.UTF_8),
iv.getBytes(StandardCharsets.UTF_8));
return aes.encryptHex(data);
}
/**
* 解密方法
*
* @param data 要解密的数据
* @return 解密的结果
*/
public static String desEncrypt(String data) {
return desEncrypt(data, SecKey.key, SecKey.iv);
}
/**
* 解密方法
*
* @param data 要解密的数据
* @param key 密钥
* @param iv 偏移向量,加盐
* @return 解密的结果
*/
public static String desEncrypt(String data, @Nonnull String key, @Nonnull String iv) {
AES aes = new AES(Mode.CBC, Padding.PKCS5Padding, key.getBytes(StandardCharsets.UTF_8),
iv.getBytes(StandardCharsets.UTF_8));
return aes.decryptStr(data);
}
}

View File

@ -0,0 +1,33 @@
package com.hb0730.boot.admin.base.util;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.hb0730.jsons.support.jackson.JacksonImpl;
/**
* json util
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/1/11
*/
public class JsonUtil extends JacksonImpl {
public static JsonUtil DEFAULT = new JsonUtil();
public JsonUtil() {
ObjectMapper mapper = new ObjectMapper() {
{
//序列化时候,只序列化非空字段
//this.setSerializationInclusion(Inclusion.NON_NULL);
//or this.setSerializationConfig(this.getSerializationConfig().withSerializationInclusion(Inclusion.NON_NULL));
// 设置输入时忽略在JSON字符串中存在但Java对象实际没有的属性
this.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
this.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
//this.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));
}
};
setClient(mapper);
}
}

View File

@ -0,0 +1,110 @@
package com.hb0730.boot.admin.base.util;
import cn.hutool.core.util.StrUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.hb0730.boot.admin.base.BootAdminConst;
import com.hb0730.boot.admin.base.exception.BootAdminException;
import jakarta.annotation.Nullable;
import jakarta.servlet.http.HttpServletRequest;
import java.util.Date;
/**
* JWT util
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/1/30
*/
public class JwtUtil {
/**
* 过期时间(毫秒):Token过期时间30分钟(用户登录过期时间是此时间的两倍,以token在reids缓存时间为准)
*/
public static final long EXPIRE_TIME = 30 * 60 * 1000;
/**
* 获取 request 里传递的 token
*
* @param request .
* @return jwt_token
*/
public static String getTokenByRequest(HttpServletRequest request) {
String token = request.getParameter("token");
if (token == null) {
token = request.getHeader(BootAdminConst.X_ACCESS_TOKEN);
}
return token;
}
/**
* 根据request中的token获取用户账号
*
* @param request 请求
* @return 用户名
*/
@Nullable
public static String getUserNameByToken(HttpServletRequest request) throws BootAdminException {
String accessToken = request.getHeader(BootAdminConst.X_ACCESS_TOKEN);
if (StrUtil.isBlank(accessToken)) {
return null;
}
String username = getUsername(accessToken);
if (StrUtil.isBlank(username)) {
throw new BootAdminException("未获取到用户");
}
return username;
}
/**
* 获得token中的信息无需secret解密也能获得
*
* @return token中包含的用户名
*/
public static String getUsername(String token) {
try {
DecodedJWT jwt = JWT.decode(token);
return jwt.getClaim("username").asString();
} catch (JWTDecodeException e) {
return null;
}
}
/**
* 生成签名,EXPIRE_TIME后过期
*
* @param username 用户名
* @param secret 用户的密码
* @return 加密的token
*/
public static String sign(String username, String secret) {
Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
Algorithm algorithm = Algorithm.HMAC256(secret);
// 附带username信息
return JWT.create().withClaim("username", username).withExpiresAt(date).sign(algorithm);
}
/**
* 校验token是否正确
*
* @param token 密钥
* @param secret 用户的密码
* @return 是否正确
*/
public static boolean verify(String token, String username, String secret) {
try {
// 根据密码生成JWT效验器
Algorithm algorithm = Algorithm.HMAC256(secret);
JWTVerifier verifier = JWT.require(algorithm).withClaim("username", username).build();
// 效验TOKEN
DecodedJWT jwt = verifier.verify(token);
return true;
} catch (Exception exception) {
return false;
}
}
}

View File

@ -0,0 +1,68 @@
package com.hb0730.boot.admin.base.util;
import jakarta.annotation.Nonnull;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
/**
* 提供对密码的加密与匹对
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/2/3
*/
public class PasswordUtil {
/**
* 将原始密码进行编码,使用默认编码器{@link #defaultPasswordEncoder()}
*
* @param rawPassword 原密码
* @return 编码后的密码
*/
public static String encoder(String rawPassword) {
return encoder(rawPassword, defaultPasswordEncoder());
}
/**
* 将原始密码进行编码
*
* @param rawPassword 原密码
* @param passwordEncoder 编码器
* @return 编码后的密码
*/
public static String encoder(String rawPassword, @Nonnull PasswordEncoder passwordEncoder) {
return passwordEncoder.encode(rawPassword);
}
/**
* 校验原始密码与编码后的密码是否为同一个密码,使用默认编码器{@link #defaultPasswordEncoder()}
*
* @param rawPassword 原密码
* @param encodedPassword 编码后的密码
* @return 是否一致
*/
public static boolean matches(String rawPassword, String encodedPassword) {
return matches(rawPassword, encodedPassword, defaultPasswordEncoder());
}
/**
* 校验原始密码与编码后的密码是否为同一个密码
*
* @param rawPassword 原密码
* @param encodedPassword 编码后的密码
* @param passwordEncoder 编码器
* @return 是否一致
*/
public static boolean matches(String rawPassword, String encodedPassword,
@Nonnull PasswordEncoder passwordEncoder) {
return passwordEncoder.matches(rawPassword, encodedPassword);
}
/**
* 默认使用 {@link BCryptPasswordEncoder} 密码编码器
*
* @return {@link BCryptPasswordEncoder}
*/
public static PasswordEncoder defaultPasswordEncoder() {
return new BCryptPasswordEncoder();
}
}

View File

@ -0,0 +1,106 @@
package com.hb0730.boot.admin.base.util;
import cn.hutool.core.codec.Base64;
import cn.hutool.crypto.KeyUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.UtilityClass;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
/**
* ras util
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/2/5
*/
@UtilityClass
public class RsaUtil {
/**
* 公钥加密,私钥解密
*
* @param text 待加密的信息
* @param publicKeyBase64 公钥
* @return base64后的结果
*/
public String encryptByPublicKey(String text, String publicKeyBase64) {
RSA rsa = new RSA();
PublicKey publicKey = KeyUtil.generateRSAPublicKey(Base64.decode(publicKeyBase64));
rsa.setPublicKey(publicKey);
return rsa.encryptBase64(text, KeyType.PublicKey);
}
/**
* 私钥解密
*
* @param text 待解密的信息,base64
* @param privateKeyBase64 私钥
* @return 解密后的结果
*/
public String decryptByPrivateKey(String text, String privateKeyBase64) {
RSA rsa = new RSA();
PrivateKey privateKey = KeyUtil.generateRSAPrivateKey(Base64.decode(privateKeyBase64));
rsa.setPrivateKey(privateKey);
return rsa.decryptStr(text, KeyType.PrivateKey);
}
/**
* 私钥解密,公钥解密
*
* @param text 待解密信息
* @param privateKeyBase64 私钥
* @return 加密后的结果, base64类型
*/
public String encryptByPrivateKey(String text, String privateKeyBase64) {
RSA rsa = new RSA();
PrivateKey privateKey = KeyUtil.generateRSAPrivateKey(Base64.decode(privateKeyBase64));
rsa.setPrivateKey(privateKey);
return rsa.encryptBase64(text, KeyType.PrivateKey);
}
/**
* 公钥解密
*
* @param text 待解密信息,base64
* @param publicKeyBase64 公钥
* @return 解密后的结果
*/
public String decryptByPublicKey(String text, String publicKeyBase64) {
RSA rsa = new RSA();
PublicKey publicKey = KeyUtil.generateRSAPublicKey(Base64.decode(publicKeyBase64));
rsa.setPublicKey(publicKey);
return rsa.decryptStr(text, KeyType.PublicKey);
}
/**
* 构建RSA密钥对
*
* @return .
*/
public RsaKeyPair generateKey() {
KeyPair keyPair = KeyUtil.generateKeyPair("RSA", 1024);
String publicBase64Key = KeyUtil.toBase64(keyPair.getPublic());
String privateBase64Key = KeyUtil.toBase64(keyPair.getPrivate());
return new RsaKeyPair(publicBase64Key, privateBase64Key);
}
/**
* RSA密钥对对象
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class RsaKeyPair {
private String publicKeyBase64;
private String privateKeyBase64;
}
}

View File

@ -0,0 +1,260 @@
package com.hb0730.boot.admin.config.cache;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import jakarta.annotation.Nonnull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* 缓存
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/1/11
*/
@Component
@RequiredArgsConstructor
@Slf4j
public class BootAdminCache {
private final BootAdminProperties cacheProperties;
private final StringRedisTemplate redisTemplate;
/**
* 正规化缓存KEY,按照<code>:</code>进行拼接
*
* @param key key
* @return <code>"prefix:key"</code>
*/
public String normaliz(String key) {
if (StrUtil.isBlank(key)) {
return null;
}
return cacheProperties.getCache().getPrefix() + ":" + key;
}
/**
* 是否存在
*
* @param key .
* @return .
*/
public boolean hasKey(String key) {
return Boolean.TRUE.equals(redisTemplate.hasKey(normaliz(key)));
}
/**
* 获取所有keys
*
* @param key .
* @return .
*/
public Set<String> getKeys(String key) {
String normalizKey = normaliz(key);
return Optional.ofNullable(redisTemplate.keys(normalizKey))
.orElse(CollUtil.newHashSet());
}
/**
* 设置过期时间,单位 秒/s
*
* @param key key: prefix+key
* @param timeout timeout 单位 秒/s
* @return .
*/
public boolean expire(final String key, long timeout) {
return expire(key, timeout, TimeUnit.SECONDS);
}
/**
* 设置过期时间
*
* @param key key,自动追加前缀{@link #normaliz(String)}
* @param timeout timeout
* @param unit time unit
* @return .
*/
public boolean expire(final String key, long timeout, TimeUnit unit) {
String _key = normaliz(key);
Boolean _res = this.redisTemplate.expire(_key, timeout, unit);
return Boolean.TRUE.equals(_res);
}
/**
* 获取过期时间,单位 秒/s
*
* @param key key,自动追加前缀{@link #normaliz(String)}
* @return timeout
*/
public long getExpire(final String key) {
return getExpire(key, TimeUnit.SECONDS);
}
/**
* 获取剩下过期时间
*
* @param key key,自动追加前缀{@link #normaliz(String)}
* @param unit time unit
* @return timeout
*/
public long getExpire(final String key, TimeUnit unit) {
String _key = normaliz(key);
return Optional.ofNullable(this.redisTemplate.getExpire(_key, unit)).orElse(0L);
}
/**
* 设置永久缓存
*
* @param key key,自动追加前缀{@link #normaliz(String)}
* @param value .
* @return .
*/
public boolean set(final String key, String value) {
return set(key, value, -1);
}
/**
* 设置缓存,单位时间/秒
*
* @param key key,自动追加前缀{@link #normaliz(String)}
* @param value .
* @param timeout timeout,如果为-l,则永久缓存
* @return .
*/
public boolean set(final String key, String value, long timeout) {
return set(key, value, timeout, TimeUnit.SECONDS);
}
/**
* 设置缓存
*
* @param key key,自动追加前缀{@link #normaliz(String)}
* @param value .
* @param timeout timeout,如果为-l,则永久缓存
* @param unit time unit
* @return .
*/
public boolean set(final String key, String value, long timeout, TimeUnit unit) {
if (StrUtil.isBlank(key)) {
log.warn("【boot-admin-cache】 set cache value warn, key missing");
return false;
}
String _key = normaliz(key);
log.debug("【boot-admin-cache】set cache value : key: {}, value: {},timeout: {}", _key, value, timeout);
if (timeout == -1) {
this.redisTemplate.opsForValue().set(_key, value);
} else {
this.redisTemplate.opsForValue().set(_key, value, timeout, unit);
}
return Boolean.TRUE;
}
/**
* 获取缓存
*
* @param key,自动追加前缀{@link #normaliz(String)}
* @return .
*/
@Nonnull
public Optional<String> getStr(final String key) {
String _key = normaliz(key);
return Optional.ofNullable(this.redisTemplate.opsForValue().get(_key));
}
/**
* 获取缓存
*
* @param key key
* @return .
*/
public Optional<String> defaultGet(final String key) {
return Optional.ofNullable(this.redisTemplate.opsForValue().get(key));
}
/**
* 获取hashKey对应的所有键值
*
* @param key 键
* @return 对应的多个键值
*/
@Nonnull
public Optional<Map<String, String>> hmget(final String key) {
String _key = normaliz(key);
Map<Object, Object> entries = this.redisTemplate.opsForHash().entries(_key);
return Optional.of(entries).map(Map::entrySet).map(entries1 -> {
Map<String, String> map = new HashMap<>(entries1.size());
entries1.forEach(entry -> map.put(entry.getKey().toString(), entry.getValue().toString()));
return map;
});
}
/**
* 获取hashKey对应的所有键值
*
* @param key .
* @return .
*/
@Nonnull
public Optional<Set<String>> sGet(final String key) {
String _key = normaliz(key);
return Optional.ofNullable(this.redisTemplate.opsForSet().members(_key));
}
/**
* 获取list缓存的内容,默认 0 到 -1
*
* @param key .
* @return .
*/
@Nonnull
public Optional<List<String>> lGet(final String key) {
return lGet(key, 0, -1);
}
/**
* 获取list缓存的内容, 0 到 -1代表所有值
*
* @param key .
* @param start 开始
* @param end 结束
* @return .
*/
public Optional<List<String>> lGet(final String key, long start, long end) {
String _key = normaliz(key);
return Optional.ofNullable(this.redisTemplate.opsForList().range(_key, start, end));
}
/**
* 批量删除
*
* @param keys .
* @return .
*/
public boolean del(Collection<String> keys) {
if (CollUtil.isEmpty(keys)) {
return Boolean.FALSE;
}
keys.forEach(this::del);
return Boolean.TRUE;
}
/**
* 删除缓存
*
* @param key,自动追加前缀{@link #normaliz(String)}
* @return .
*/
public boolean del(final String key) {
String _key = normaliz(key);
return Boolean.TRUE.equals(this.redisTemplate.delete(_key));
}
}

View File

@ -0,0 +1,35 @@
package com.hb0730.boot.admin.config.cache;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/1/11
*/
@Configuration
@ConfigurationProperties(prefix = "boot.admin")
@Data
public class BootAdminProperties {
/**
* 缓存
*/
private CacheProperties cache = new CacheProperties();
/**
* 是否刷新路由,默认不刷新
* <p>
* 一般用于用户权限发生变化时,刷新路由,如果用户量过多,不建议启用
* </p>
*/
public Boolean refreshRoutes = false;
@Data
public static class CacheProperties {
/**
* 前缀
*/
private String prefix = "boot:admin:cache";
}
}

View File

@ -0,0 +1,37 @@
package com.hb0730.boot.admin.config.cache;
import java.util.Arrays;
import java.util.stream.Collectors;
/**
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/1/30
*/
public interface CacheUtil {
/**
* 缓存关键字连接符号:冒号
*/
String CACHE_SPLICE_COLON = ":";
/**
* 缓存KEY组装器
*
* @param kv 缓存枚举
* @param keys 缓存key拼接字符
*/
default String getCacheKey(KeyValue kv, Object... keys) {
return buildKeys(kv, keys);
}
static String buildKeys(KeyValue kv, Object... keys) {
if (keys.length == 0) {
return kv.getPrefix();
}
return kv.getPrefix() + CACHE_SPLICE_COLON + concatKeys(keys);
}
static String concatKeys(Object... keys) {
return Arrays.stream(keys).map(String::valueOf).collect(Collectors.joining(CACHE_SPLICE_COLON));
}
}

View File

@ -0,0 +1,96 @@
package com.hb0730.boot.admin.config.cache;
/**
* 非系统级别的缓存定义
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/6/6
*/
public enum DefaultKeyValue implements KeyValue {
/**
* 【系统配置项】
* --------------------------------------------------------------------------------
* <p>系统配置表【sys_config】缓存</p>
* --------------------------------------------------------------------------------
*/
SYS_CONFIG("SYS",
EXPIRE_TIME_DEFAULT,
CacheType.STRING,
String.class,
"系统配置",
"SYS:key --> (String)value"),
;
/**
* KEY前缀
*/
private final String prefix;
/**
* 过期时间(秒)
*/
private final long expire;
/**
* 缓存对象
*/
private final Class<?> clazz;
/**
* 缓存名称
*/
private final String name;
/**
* 缓存说明
*/
private final String desc;
/**
* 缓存的数据类型 {涉及JimDB缓存的 get、set 方法使用}
*/
private CacheType type;
DefaultKeyValue(String prefix, long expire, CacheType type, Class<?> clazz, String name, String desc) {
this.prefix = prefix;
this.expire = expire;
this.clazz = clazz;
this.name = name;
this.desc = desc;
this.type = type;
}
@Override
public String getPrefix() {
return prefix;
}
@Override
public long getExpire() {
return expire;
}
@Override
public Class<?> getClazz() {
return clazz;
}
@Override
public String getName() {
return name;
}
@Override
public String getDesc() {
return desc;
}
public CacheType getType() {
return type;
}
/**
* JimDB缓存的数据类型
* <p> 涉及如何 set、get </p>
*/
public enum CacheType {
STRING, OBJECT, HASHMAP, SET, LIST
}
}

View File

@ -0,0 +1,65 @@
package com.hb0730.boot.admin.config.cache;
/**
* 缓存定义
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/1/30
*/
public interface KeyValue {
/**
* 缓存key的失效时间
* <p> 不设置失效时间 == 永久有效 ;
* XXX: setObject方法设为-1时,经封装后代表永久有效
* <p> 单位:秒
*/
long EXPIRE_TIME_DEFAULT = -1;
/**
* 工单号在缓存存储时间 90天
*/
long ORDER_TIME_OUT_LIMIT = 60 * 60 * 24 * 30;
/**
* KEY前缀
*
* @return 前缀
*/
default String getPrefix() {
return "";
}
/**
* 过期时间(秒)
*
* @return 过期时间
*/
default long getExpire() {
return 0L;
}
/**
* 缓存对象
*
* @return 缓存对象
*/
default Class<?> getClazz() {
return null;
}
/**
* 缓存名称
*
* @return 缓存名称
*/
default String getName() {
return "";
}
/**
* 缓存说明
*/
default String getDesc() {
return "";
}
}

View File

@ -0,0 +1,28 @@
package com.hb0730.boot.admin.config.cors;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
/**
* 跨域
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/1/11
*/
@Configuration
public class CorsConfiguration {
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
org.springframework.web.cors.CorsConfiguration config = new org.springframework.web.cors.CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOriginPattern("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}

View File

@ -0,0 +1,34 @@
package com.hb0730.boot.admin.config.handler;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hb0730.boot.admin.modules.api.buiness.model.PictureEntity;
import java.util.List;
/**
* JSON转对象
* @author jianpòlan
* @version 1.0
**/
public class JsonHandler extends JacksonTypeHandler {
private final Class<Object> type;
public JsonHandler(Class<Object> type) {
super(type);
this.type = type;
}
@Override
protected Object parse(String json) {
try {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readValue(json, new TypeReference<List<PictureEntity>>() { });
}catch (Exception e){
e.printStackTrace();
return null;
}
}
}

View File

@ -0,0 +1,68 @@
package com.hb0730.boot.admin.config.jackson;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.TimeZone;
/**
* jackson 序列化与反序列化
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/2/12
*/
@Configuration
public class JacksonConfig {
private static final String DEFAULT_DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
private static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
private static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";
@Bean
public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
return builder -> {
// 这一部分也可以在 yaml 中配置
builder
// 序列化时,对象为 null,是否抛异常
.failOnEmptyBeans(false)
// 反序列化时,json 中包含 pojo 不存在属性时,是否抛异常
.failOnUnknownProperties(false)
// 禁止将 java.util.Date, Calendar 序列化为数字(时间戳)
.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
// 设置 java.util.Date, Calendar 序列化、反序列化的格式
.dateFormat(new SimpleDateFormat(DEFAULT_DATETIME_PATTERN))
// 设置 java.util.Date、Calendar 序列化、反序列化的时区
.timeZone(TimeZone.getTimeZone("GMT+8"))
;
// Jackson 序列化 long类型为String,解决后端返回的Long类型在前端精度丢失的问题
builder.serializerByType(BigInteger.class, ToStringSerializer.instance);
builder.serializerByType(Long.class, ToStringSerializer.instance);
builder.serializerByType(Long.TYPE, ToStringSerializer.instance);
// 配置 Jackson 反序列化 LocalDateTime、LocalDate、LocalTime 时使用的格式
builder.deserializerByType(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATETIME_PATTERN)));
builder.deserializerByType(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)));
builder.deserializerByType(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));
// 配置 Jackson 序列化 LocalDateTime、LocalDate、LocalTime 时使用的格式
builder.serializers(new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATETIME_PATTERN)));
builder.serializers(new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)));
builder.serializers(new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));
};
}
}

View File

@ -0,0 +1,29 @@
package com.hb0730.boot.admin.config.mybatis;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/1/11
*/
@Configuration
@MapperScan(basePackages = "com.hb0730.boot.admin.**.mapper")
public class MybatisConfiguration {
/**
* 插件
*
* @return .
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
return interceptor;
}
}

View File

@ -0,0 +1,54 @@
package com.hb0730.boot.admin.config.springdoc;
import com.hb0730.boot.admin.base.BootAdminConst;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/1/12
*/
@Configuration
public class SpringdocConfiguration {
@Bean
public OpenAPI openAPI() {
return new OpenAPI()
.info(getInfo()
).addSecurityItem(
new io.swagger.v3.oas.models.security.SecurityRequirement()
.addList(BootAdminConst.X_ACCESS_TOKEN)
).schemaRequirement(
BootAdminConst.X_ACCESS_TOKEN,
securityScheme()
).components(
new Components()
.addSecuritySchemes(BootAdminConst.X_ACCESS_TOKEN, securityScheme())
);
}
private Info getInfo() {
return new Info()
.title("boot-admin系统API")
.contact(
new Contact()
.name("hb0730")
.url("https://blog.hb0730.me")
.email("huangbing0730@gmail.com")
)
.version("v5.0.0")
;
}
private SecurityScheme securityScheme() {
SecurityScheme securityScheme = new SecurityScheme();
securityScheme.setType(SecurityScheme.Type.APIKEY);
securityScheme.setName(BootAdminConst.X_ACCESS_TOKEN);
securityScheme.setIn(SecurityScheme.In.HEADER);
return securityScheme;
}
}

View File

@ -0,0 +1,17 @@
package com.hb0730.boot.admin.core.service;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
/**
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/2/4
*/
@Slf4j
public class BaseServiceImpl<
M extends BaseMapper<T>,
T
> extends ServiceImpl<M, T> implements IService<T> {
}

View File

@ -0,0 +1,52 @@
package com.hb0730.boot.admin.data.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/2/4
*/
@Data
@EqualsAndHashCode
@ToString
public class BaseEntity implements Serializable {
/**
* ID
*/
@TableId(type = IdType.ASSIGN_ID)
@Schema(description = "id")
protected String id;
/**
* 创建人
*/
@Schema(description = "创建人")
protected String createdBy;
/**
* 创建时间
*/
@Schema(description = "创建时间")
protected LocalDateTime created;
/**
* 更新人
*/
@Schema(description = "更新人")
protected String modifiedBy;
/**
* 更新时间
*/
@Schema(description = "更新时间")
protected LocalDateTime modified;
}

View File

@ -0,0 +1,84 @@
package com.hb0730.boot.admin.data.domain;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.io.Serializable;
import java.util.Collections;
import java.util.List;
/**
* 分页基类
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/2/28
*/
@Data
@EqualsAndHashCode
@ToString
public class BasePage<T> implements Serializable {
/**
* 数据集合
*/
@Schema(description = "数据集合")
private List<T> records;
/**
* 数据总数
*/
@Schema(description = "数据总数")
private long total;
/**
* 分页size
*/
@Schema(description = "分页size")
private long size;
/**
* 当前页码
*/
@Schema(description = "当前页码")
private long current;
public BasePage() {
this.records = Collections.emptyList();
this.total = 0L;
this.size = 0L;
this.current = 0L;
}
public BasePage(long current, long size) {
this(current, size, 0L);
}
public BasePage(long current, long size, long total) {
this(current, size, total, null);
}
public BasePage(long current, long size, long total, List<T> records) {
this.setCurrent(current)
.setSize(size)
.setTotal(total)
.setRecords(records);
}
public BasePage<T> setCurrent(long current) {
this.current = current;
return this;
}
public BasePage<T> setSize(long size) {
this.size = size;
return this;
}
public BasePage<T> setTotal(long total) {
this.total = total;
return this;
}
public BasePage<T> setRecords(List<T> records) {
this.records = records;
return this;
}
}

View File

@ -0,0 +1,27 @@
package com.hb0730.boot.admin.data.domain;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.io.Serializable;
/**
* 分页查询基类
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/1/12
*/
@Data
@EqualsAndHashCode
@ToString
public class BasePageQuery implements Serializable {
@Parameter(description = "分页size")
@Schema(description = "分页size")
private long size;
@Parameter(description = "当前页数")
@Schema(description = "当前页数")
private long current;
}

View File

@ -0,0 +1,42 @@
package com.hb0730.boot.admin.data.domain;
import java.io.Serializable;
import java.util.List;
/**
* 数据结构的数据
*
* @param <T> .
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/1/12
*/
public interface TreeData<T extends TreeData<T>> extends Serializable {
/**
* id
*
* @return .
*/
String getId();
/**
* parent id
*
* @return .
*/
String getParentId();
/**
* children
*
* @return .
*/
List<T> getChildren();
/**
* set children
*
* @param data .
* @return .
*/
TreeData<T> setChildren(List<T> data);
}

View File

@ -0,0 +1,29 @@
package com.hb0730.boot.admin.data.enums;
/**
* 配置类型
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/6/12
*/
public enum ConfigTypeEnums implements ValueEnum<Integer> {
CONFIG_TYPE01(1, "系统配置"),
CONFIG_TYPE02(2, "业务配置"),
;
private final Integer value;
private final String name;
ConfigTypeEnums(Integer value, String name) {
this.value = value;
this.name = name;
}
@Override
public Integer getValue() {
return value;
}
public String getName() {
return name;
}
}

View File

@ -0,0 +1,38 @@
package com.hb0730.boot.admin.data.enums;
/**
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/1/11
*/
public enum EnabledEnums implements ValueEnum<Integer> {
/**
* 启用:1
*/
enabled("启用", "", 1),
/**
* 禁用:0
*/
un_enabled("禁用", "", 0);
private final String name;
private final String alias;
private final Integer value;
EnabledEnums(String name, String alias, Integer value) {
this.name = name;
this.alias = alias;
this.value = value;
}
public String getName() {
return name;
}
public String getAlias() {
return alias;
}
@Override
public Integer getValue() {
return value;
}
}

View File

@ -0,0 +1,45 @@
package com.hb0730.boot.admin.data.enums;
/**
* 性别
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/1/11
*/
public enum GenderEnums implements ValueEnum<Integer> {
/**
* 未知
*/
unknown("未知", "保密", -1),
/**
* 男性
*/
man("男", "先生", 0),
/**
* 女性
*/
woman("女", "女士", 1),
;
private final String name;
private final String alias;
private final Integer value;
GenderEnums(String name, String alias, Integer value) {
this.name = name;
this.alias = alias;
this.value = value;
}
public String getName() {
return name;
}
public String getAlias() {
return alias;
}
@Override
public Integer getValue() {
return value;
}
}

View File

@ -0,0 +1,30 @@
package com.hb0730.boot.admin.data.enums;
/**
* 菜单类型
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/1/12
*/
public enum MenuTypeEnums implements ValueEnum<Integer> {
dir("目录", 0),
menu("菜单", 1),
permission("权限", 2),
;
private final String name;
private final Integer value;
MenuTypeEnums(String name, Integer value) {
this.name = name;
this.value = value;
}
public String getName() {
return name;
}
@Override
public Integer getValue() {
return value;
}
}

View File

@ -0,0 +1,52 @@
package com.hb0730.boot.admin.data.enums;
/**
* 操作
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/1/12
*/
public enum OperateEnums implements ValueEnum<Integer> {
operate_null("", 0),
/**
* 查询
*/
operate_query("查询", 1),
/**
* 添加
*/
operate_add("添加", 2),
/**
* 更新
*/
operate_edit("更新", 3),
/**
* 删除
*/
operate_delete("删除", 4),
/**
* 导出
*/
operate_export("导出", 5),
/**
* 导入
*/
operate_import("导入", 6),
;
private final String name;
private final Integer value;
OperateEnums(String name, Integer value) {
this.name = name;
this.value = value;
}
public String getName() {
return name;
}
@Override
public Integer getValue() {
return value;
}
}

View File

@ -0,0 +1,62 @@
package com.hb0730.boot.admin.data.enums;
import java.util.stream.Stream;
/**
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/1/11
*/
public interface ValueEnum<T> {
/**
* Gets enum value.
*
* @return enum value
*/
T getValue();
/**
* Converts value to corresponding enum.
*
* @param enumType 枚举类型,不为空
* @param value 值
* @param <V> 值类型
* @param <E> 枚举类型
* @return corresponding enum
*/
static <V, E extends Enum<E> & ValueEnum<V>> E valueToEnum(Class<E> enumType, V value) {
return Stream.of(enumType.getEnumConstants())
.filter(item -> item.getValue().equals(value))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("unknown database value: " + value));
}
/**
* Converts value to corresponding enum.
*
* @param enumType 枚举类型,不为空
* @param value 值
* @param defaultValue 默认值
* @param <V> 值类型
* @param <E> 枚举类型
* @return corresponding enum
*/
static <V, E extends Enum<E> & ValueEnum<V>> E valueToEnum(Class<E> enumType, V value, E defaultValue) {
return Stream.of(enumType.getEnumConstants())
.filter(item -> item.getValue().equals(value))
.findFirst()
.orElse(defaultValue);
}
/**
* 是否存在当前值
*
* @param enumType 枚举类型
* @param value 值
* @param <V> 值类型
* @param <E> 枚举类型
* @return 是否存在
*/
static <V, E extends Enum<E> & ValueEnum<V>> boolean hash(Class<E> enumType, V value) {
return Stream.of(enumType.getEnumConstants()).anyMatch(item -> item.getValue().equals(value));
}
}

View File

@ -0,0 +1,17 @@
package com.hb0730.boot.admin.job;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/6/13
*/
@Component
@Slf4j
public class MyTestJobService {
public void start(String params) {
log.info("MyTestJobService start {}", params);
}
}

View File

@ -0,0 +1,45 @@
package com.hb0730.boot.admin.job;
import jakarta.annotation.Resource;
import jakarta.validation.constraints.NotNull;
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.scheduling.quartz.QuartzJobBean;
/**
* 依赖注入
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/6/12
* @see <a href="https://docs.spring.io/spring-boot/docs/current/reference/html/io.html#io.quartz">quartz</a
*/
@Slf4j
public class SampleInjectBeanJob extends QuartzJobBean {
private MyTestJobService myTestJobService;
/**
* 依赖注入
* <p>
* 为什么需要@Resource或者@Autowired
*
* @param myTestJobService .
* @see org.springframework.scheduling.quartz.SpringBeanJobFactory#createJobInstance(TriggerFiredBundle)
* getAutowireCapableBeanFactory
* </p>
*/
@Resource
public void setMyTestJobService(MyTestJobService myTestJobService) {
this.myTestJobService = myTestJobService;
}
@Override
protected void executeInternal(@NotNull JobExecutionContext context) throws JobExecutionException {
log.info("普通定时任务 SampleInjectBeanJob ! 时间: {}", myTestJobService);
JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
String parameter = jobDataMap.getString("parameter");
myTestJobService.start(parameter);
}
}

View File

@ -0,0 +1,21 @@
package com.hb0730.boot.admin.job;
import cn.hutool.core.date.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
/**
* 示例不带参定时任务
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/6/12
*/
@Slf4j
public class SampleJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
log.info("普通定时任务 SampleJob ! 时间: {}", DateUtil.now());
}
}

View File

@ -0,0 +1,38 @@
package com.hb0730.boot.admin.job;
import cn.hutool.core.date.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
/**
* 带参数的JOB
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/6/12
*/
@Slf4j
public class SampleParamJob implements Job {
/**
* 任务参数
*/
private String parameter;
/**
* 设置任务参数
*
* @param parameter 任务参数
*/
public void setParameter(String parameter) {
this.parameter = parameter;
}
//------------------------------------------------------------------------------------------------
@Override
public void execute(JobExecutionContext jobExecutionContext) {
log.info("welcome {}! 带参数定时任务 SampleParamJob ! 时间 :{}", this.parameter, DateUtil.now());
}
}

View File

@ -0,0 +1,34 @@
package com.hb0730.boot.admin.modules.api.buiness.controller;
import com.hb0730.boot.admin.base.R;
import com.hb0730.boot.admin.modules.api.buiness.service.OssService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
@Tag(name = "系统:阿里云:上传")
@RestController
@RequestMapping("buiness/oss")
public class OssController {
@Autowired
OssService ossService;
//1、上传文件到oss: 接收客户端上传的文件流和文件名称 上传到oss之后 返回上传成功的文件路径
@PostMapping("upload")
@Operation(summary = "上传文件")
public R uploadFile(@RequestBody MultipartFile file
) {
return ossService.uploadFile(file);
}
//2、删除oss中的文件
@DeleteMapping("delete")
@Operation(summary = "删除文件")
public R deleteFile(@RequestParam("path") String path
) {
return ossService.deleteFile(path);
}
}

View File

@ -0,0 +1,101 @@
package com.hb0730.boot.admin.modules.api.buiness.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hb0730.boot.admin.base.R;
import com.hb0730.boot.admin.data.domain.BasePage;
import com.hb0730.boot.admin.modules.api.buiness.model.SysBox;
import com.hb0730.boot.admin.modules.api.buiness.model.SysShop;
import com.hb0730.boot.admin.modules.api.buiness.model.query.BoxQuery;
import com.hb0730.boot.admin.modules.api.buiness.model.query.ShopQuery;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.BoxVO;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.ShopVO;
import com.hb0730.boot.admin.modules.api.buiness.service.SysBoxService;
import com.hb0730.boot.admin.modules.api.buiness.service.SysShopService;
import com.hb0730.boot.admin.security.util.SecurityUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.beans.BeanUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.util.List;
/**
* 包厢管理
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/2/4
*/
@RestController
@RequestMapping("/buiness/box")
@Tag(name = "系统:包厢管理")
@RequiredArgsConstructor
public class SysBoxController {
private final SysBoxService sysBoxService;
@GetMapping("/query/page")
@Operation(summary = "分页查询")
public R<BasePage<BoxVO>> queryPage(HttpServletRequest request, @ParameterObject BoxQuery query) {
BasePage<BoxVO> res = this.sysBoxService.queryPage(query);
return R.OK(res);
}
// @GetMapping("/query/list")
// @Operation(summary = "列表查询")
// public R<List<UserVO>> queryList(HttpServletRequest request, @ParameterObject UserQuery query) {
// List<UserVO> res = this.sysShopService.queryList(query);
// return R.OK(res);
// }
//
// @GetMapping("/check/username")
// @Operation(summary = "检查用户名是否存在")
// public R<Boolean> checkUsername(HttpServletRequest request, @RequestParam String username) {
// return this.sysBoxService.hashUsername(username);
// }
////
@GetMapping("/")
@Operation(summary = "详情")
public R<BoxVO> detail(HttpServletRequest request, @Parameter(name = "id", description = "包厢ID",
required = true) @RequestParam String id) {
return this.sysBoxService.detail(id);
}
@PostMapping("/save")
@Operation(summary = "保存")
public R<BoxVO> save(HttpServletRequest request, @Validated @RequestBody BoxVO boxVO) {
return this.sysBoxService.saveShop(boxVO);
}
@PutMapping("/update/{id}")
@Operation(summary = "修改")
public R<BoxVO> update(HttpServletRequest request,@PathVariable String id,
@Validated @RequestBody BoxVO boxVO) {
SysBox byId = sysBoxService.getById(boxVO.getId());
boxVO.setModified(LocalDateTime.now());
boxVO.setModifiedBy(SecurityUtil.getCurrentUsername());
BeanUtils.copyProperties(boxVO,byId);
this.sysBoxService.updateById(byId);
return R.OK(boxVO);
}
@GetMapping("/delete")
@Operation(summary = "删除")
public R delete(HttpServletRequest request , @RequestParam String id) {
QueryWrapper<SysBox> wrapper = new QueryWrapper<>();
wrapper.eq(
"id",id
);
return R.OK(this.sysBoxService.remove(wrapper));
}
}

View File

@ -0,0 +1,102 @@
package com.hb0730.boot.admin.modules.api.buiness.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hb0730.boot.admin.base.R;
import com.hb0730.boot.admin.data.domain.BasePage;
import com.hb0730.boot.admin.modules.api.buiness.model.SysBox;
import com.hb0730.boot.admin.modules.api.buiness.model.SysCoupon;
import com.hb0730.boot.admin.modules.api.buiness.model.SysCouponLog;
import com.hb0730.boot.admin.modules.api.buiness.model.query.BoxQuery;
import com.hb0730.boot.admin.modules.api.buiness.model.query.CouponQuery;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.BoxVO;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.CouponVO;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.GetCouponLogVO;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.ShopVO;
import com.hb0730.boot.admin.modules.api.buiness.service.SysBoxService;
import com.hb0730.boot.admin.modules.api.buiness.service.SysCouponService;
import com.hb0730.boot.admin.security.util.SecurityUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.util.List;
/**
* 包厢管理
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/2/4
*/
@RestController
@RequestMapping("/buiness/coupon")
@Tag(name = "系统:优惠券管理")
@RequiredArgsConstructor
public class SysCouponController {
private final SysCouponService sysCouponService;
@GetMapping("/query/page")
@Operation(summary = "分页查询")
public R<BasePage<CouponVO>> queryPage(HttpServletRequest request, @ParameterObject CouponQuery query) {
BasePage<CouponVO> res = this.sysCouponService.queryPage(query);
return R.OK(res);
}
@GetMapping()
@Operation(summary = "详情")
public R<CouponVO> detail(HttpServletRequest request, @Parameter(name = "id", description = "优惠券ID",
required = true) @RequestParam String id) {
return this.sysCouponService.detail(id);
}
@PostMapping("/save")
@Operation(summary = "保存")
public R<CouponVO> save(HttpServletRequest request, @Validated @RequestBody CouponVO couponVO) {
return this.sysCouponService.saveShop(couponVO);
}
@PutMapping("/update/{id}")
@Operation(summary = "修改")
public R<CouponVO> update(HttpServletRequest request, @PathVariable String id,
@Validated @RequestBody CouponVO couponVO) {
couponVO.setModified(LocalDateTime.now());
couponVO.setModifiedBy(SecurityUtil.getCurrentUsername());
return this.sysCouponService.updateById(id, couponVO);
}
@GetMapping("/delete")
@Operation(summary = "删除")
public R delete(HttpServletRequest request , @RequestParam String id) {
QueryWrapper<SysCoupon> wrapper = new QueryWrapper<>();
wrapper.eq(
"id",id
);
return R.OK(this.sysCouponService.remove(wrapper));
}
@GetMapping("/getCoupon")
@Operation(summary = "领取取优惠券")
public R<GetCouponLogVO> getCoupon(HttpServletRequest request , @RequestParam("id") String id , @RequestParam String openId) {
return this.sysCouponService.getCoupon(id,openId);
}
@GetMapping("/verification")
@Operation(summary = "核销优惠券")
public R<String> verification(HttpServletRequest request ,@Parameter(name = "id", description = "领取记录表ID",
required = true) @RequestParam String id ,
@Parameter(name = "checkCode", description = "核销码",
required = true)@RequestParam String checkCode) {
return this.sysCouponService.verification(id,checkCode);
}
}

View File

@ -0,0 +1,82 @@
package com.hb0730.boot.admin.modules.api.buiness.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hb0730.boot.admin.base.R;
import com.hb0730.boot.admin.data.domain.BasePage;
import com.hb0730.boot.admin.modules.api.buiness.model.SysCoupon;
import com.hb0730.boot.admin.modules.api.buiness.model.SysCouponLog;
import com.hb0730.boot.admin.modules.api.buiness.model.query.CouponQuery;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.CouponLogVO;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.CouponVO;
import com.hb0730.boot.admin.modules.api.buiness.service.SysCouponLogService;
import com.hb0730.boot.admin.modules.api.buiness.service.SysCouponService;
import com.hb0730.boot.admin.security.util.SecurityUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
/**
* 包厢管理
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/2/4
*/
@RestController
@RequestMapping("/buiness/couponLog")
@Tag(name = "系统:优惠券领取记录管理")
@RequiredArgsConstructor
public class SysCouponLogController {
private final SysCouponLogService sysCouponLogService;
@GetMapping("/query/page")
@Operation(summary = "分页查询")
public R<BasePage<CouponLogVO>> queryPage(HttpServletRequest request, @ParameterObject CouponQuery query) {
BasePage<CouponLogVO> res = this.sysCouponLogService.queryPage(query);
return R.OK(res);
}
@GetMapping()
@Operation(summary = "详情")
public R<CouponLogVO> detail(HttpServletRequest request, @Parameter(name = "id", description = "优惠券ID",
required = true) @RequestParam String id) {
return this.sysCouponLogService.detail(id);
}
@PostMapping("/save")
@Operation(summary = "保存")
public R<CouponLogVO> save(HttpServletRequest request, @Validated @RequestBody CouponLogVO couponlogVO) {
return this.sysCouponLogService.saveShop(couponlogVO);
}
@PutMapping("/update/{id}")
@Operation(summary = "修改")
public R<CouponLogVO> update(HttpServletRequest request, @PathVariable String id,
@Validated @RequestBody CouponLogVO couponVO) {
couponVO.setModified(LocalDateTime.now());
couponVO.setModifiedBy(SecurityUtil.getCurrentUsername());
return this.sysCouponLogService.updateById(id, couponVO);
}
@GetMapping("/delete")
@Operation(summary = "删除")
public R delete(HttpServletRequest request , @RequestParam String id) {
QueryWrapper<SysCouponLog> wrapper = new QueryWrapper<>();
wrapper.eq(
"id",id
);
return R.OK(this.sysCouponLogService.remove(wrapper));
}
}

View File

@ -0,0 +1,103 @@
package com.hb0730.boot.admin.modules.api.buiness.controller;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hb0730.boot.admin.base.R;
import com.hb0730.boot.admin.data.domain.BasePage;
import com.hb0730.boot.admin.modules.api.buiness.model.SysShop;
import com.hb0730.boot.admin.modules.api.buiness.model.query.ShopQuery;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.HourVO;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.SeasonVO;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.ShopVO;
import com.hb0730.boot.admin.modules.api.buiness.service.SysShopService;
import com.hb0730.boot.admin.modules.sys.system.model.query.UserQuery;
import com.hb0730.boot.admin.modules.sys.system.model.vo.RestPasswdVO;
import com.hb0730.boot.admin.modules.sys.system.model.vo.UserVO;
import com.hb0730.boot.admin.modules.sys.system.service.SysUserService;
import com.hb0730.boot.admin.security.util.SecurityUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
/**
* 店铺管理
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/2/4
*/
@RestController
@RequestMapping("/buiness/shop")
@Tag(name = "系统:店铺管理")
@RequiredArgsConstructor
public class SysShopController {
private final SysShopService sysShopService;
@GetMapping("/query/page")
@Operation(summary = "分页查询")
public R<BasePage<ShopVO>> queryPage(HttpServletRequest request, @ParameterObject ShopQuery query) {
BasePage<ShopVO> res = this.sysShopService.queryPage(query);
return R.OK(res);
}
@GetMapping
@Operation(summary = "详情")
public R<ShopVO> detail(HttpServletRequest request, @Parameter(name = "id", description = "店铺ID",
required = true) @RequestParam String id) {
return this.sysShopService.detail(id);
}
@PostMapping("/save")
@Operation(summary = "保存")
public R<ShopVO> save(HttpServletRequest request, @Validated @RequestBody ShopVO shopVO) {
return this.sysShopService.saveShop(shopVO);
}
//
//
@PutMapping("/update/{id}")
@Operation(summary = "修改")
public R<ShopVO> update(HttpServletRequest request, @PathVariable String id,
@Validated @RequestBody ShopVO shopVO) {
shopVO.setModified(LocalDateTime.now());
shopVO.setModifiedBy(SecurityUtil.getCurrentUsername());
return this.sysShopService.updateById(id, shopVO);
}
@GetMapping("/delete")
@Operation(summary = "删除")
public R delete(HttpServletRequest request , @RequestParam String id) {
QueryWrapper<SysShop> wrapper = new QueryWrapper<>();
wrapper.eq(
"id",id
);
return R.OK(this.sysShopService.remove(wrapper));
}
@GetMapping("/getSeason")
@Operation(summary = "获取季节菜品")
public R<List<SeasonVO>> getSeason(HttpServletRequest request) {
return R.OK(this.sysShopService.getSeason());
}
@GetMapping("/getHour")
@Operation(summary = "获取小时菜品")
public R<List<HourVO>> getHour(HttpServletRequest request) {
return R.OK(this.sysShopService.getHour());
}
}

View File

@ -0,0 +1,19 @@
package com.hb0730.boot.admin.modules.api.buiness.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hb0730.boot.admin.modules.api.buiness.model.SysBox;
import com.hb0730.boot.admin.modules.api.buiness.model.SysShop;
import com.hb0730.boot.admin.modules.api.buiness.model.query.BoxQuery;
import com.hb0730.boot.admin.modules.api.buiness.model.query.ShopQuery;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.BoxVO;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.ShopVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface SysBoxMapper extends BaseMapper<SysBox> {
List<SysBox> queryPage(Page<BoxVO> page, @Param("query") BoxQuery query);
}

View File

@ -0,0 +1,18 @@
package com.hb0730.boot.admin.modules.api.buiness.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hb0730.boot.admin.modules.api.buiness.model.SysCoupon;
import com.hb0730.boot.admin.modules.api.buiness.model.SysCouponLog;
import com.hb0730.boot.admin.modules.api.buiness.model.query.CouponQuery;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.CouponLogVO;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.CouponVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface SysCouponLogMapper extends BaseMapper<SysCouponLog> {
List<SysCouponLog> queryPage(Page<CouponLogVO> page, @Param("query") CouponQuery query);
}

View File

@ -0,0 +1,21 @@
package com.hb0730.boot.admin.modules.api.buiness.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hb0730.boot.admin.modules.api.buiness.model.SysBox;
import com.hb0730.boot.admin.modules.api.buiness.model.SysCoupon;
import com.hb0730.boot.admin.modules.api.buiness.model.query.BoxQuery;
import com.hb0730.boot.admin.modules.api.buiness.model.query.CouponQuery;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.BoxVO;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.CouponVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface SysCouponMapper extends BaseMapper<SysCoupon> {
List<SysCoupon> queryPage(Page<CouponVO> page, @Param("query") CouponQuery query);
void updateNums(@Param("id")String id);
}

View File

@ -0,0 +1,22 @@
package com.hb0730.boot.admin.modules.api.buiness.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hb0730.boot.admin.modules.api.buiness.model.SysShop;
import com.hb0730.boot.admin.modules.api.buiness.model.query.ShopQuery;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.HourVO;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.SeasonVO;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.ShopVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface SysShopMapper extends BaseMapper<SysShop> {
List<SysShop> queryPage(Page<ShopVO> page, @Param("query") ShopQuery query);
List<SeasonVO> getSeason();
List<HourVO> getHour();
}

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hb0730.boot.admin.modules.api.buiness.mapper.SysBoxMapper">
<sql id="Base_sql">
t.id,
t.created_by,
t.created,
t.modified_by,
t.modified,
t.name,
t.min,
t.max,
t.images_url,
t.shop_id,
t.nums
</sql>
<select id="queryPage" resultType="com.hb0730.boot.admin.modules.api.buiness.model.SysBox">
SELECT
<include refid="Base_sql"/>,t.name as name
FROM `sys_box` t
WHERE 1=1
<if test="query.shopId!=null and query.shopId!=''">
AND t.shop_id = #{query.shopId}
</if>
</select>
</mapper>

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hb0730.boot.admin.modules.api.buiness.mapper.SysCouponLogMapper">
<sql id="Base_sql">
t.id,
t.created_by,
t.created,
t.modified_by,
t.modified,
t.user_id,
t.coupon_id,
t.open_id,
t.check_code,
t.user_name,
t.gift_name
</sql>
<select id="queryPage" resultType="com.hb0730.boot.admin.modules.api.buiness.model.SysCouponLog">
SELECT
<include refid="Base_sql"/>
FROM `sys_coupon_log` t
where t.coupon_id = #{query.id}
ORDER BY t.modified ASC
</select>
</mapper>

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hb0730.boot.admin.modules.api.buiness.mapper.SysCouponMapper">
<sql id="Base_sql">
t.id,
t.created_by,
t.created,
t.modified_by,
t.modified,
t.coupon_name,
t.nums,
t.title,
t.receive_date,
t.receive_time,
t.activity_rules,
t.activity_dec,
t.gift_name,
t.gift_image,
t.open_id,
t.tag_img
</sql>
<select id="queryPage" resultType="com.hb0730.boot.admin.modules.api.buiness.model.SysCoupon">
SELECT
<include refid="Base_sql"/>,t.coupon_name
FROM `sys_coupon` t
</select>
<update id="updateNums">
UPDATE sys_coupon SET nums = nums - 1 WHERE id = #{id};
</update>
</mapper>

View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hb0730.boot.admin.modules.api.buiness.mapper.SysShopMapper">
<sql id="Base_sql">
t.id,
t.created_by,
t.created,
t.modified_by,
t.modified,
t.name,
t.intro_chi as introChi,
t.intro_eng as introEng,
t.intro_jap as introJap,
t.phone,
t.start_time,
t.end_time,
t.tag_url,
t.logo_url,
t.picture_url,
t.floor,
t.vagetable_url,
t.is_enable as isEnable,
t.name_picture,
t.title,
t.season,
t.hour,
t.sort
</sql>
<select id="queryPage" resultType="com.hb0730.boot.admin.modules.api.buiness.model.SysShop">
SELECT
<include refid="Base_sql"/>,t.name as name
FROM `sys_shop` t
WHERE 1=1
<if test="query.name!=null and query.name!=''">
AND t.name LIKE CONCAT('%',#{query.name},'%')
</if>
ORDER BY t.sort Asc
</select>
<select id="getSeason" resultType="com.hb0730.boot.admin.modules.api.buiness.model.vo.SeasonVO">
select id , season , `sort` , modified from sys_shop ORDER BY sort Asc
</select>
<select id="getHour" resultType="com.hb0730.boot.admin.modules.api.buiness.model.vo.HourVO">
select id, `hour` , `sort` , modified from sys_shop ORDER BY sort Asc
</select>
</mapper>

View File

@ -0,0 +1,10 @@
package com.hb0730.boot.admin.modules.api.buiness.model;
import lombok.Data;
@Data
public class PictureEntity {
public String name;
public String url;
}

View File

@ -0,0 +1,45 @@
package com.hb0730.boot.admin.modules.api.buiness.model;
import com.baomidou.mybatisplus.annotation.TableName;
import com.hb0730.boot.admin.data.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/**
* 包厢表
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/2/4
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ToString
@TableName
public class SysBox extends BaseEntity {
/**
* 包厢名称
*/
private String name;
/**
* 包厢最小人数
*/
private Integer min;
/**
* 包厢最大人数
*/
private Integer max;
/**
* 包厢图片路径
*/
private String imagesUrl;
/**
* 所属店铺id
*/
private String shopId;
/**
* 包厢数量
*/
private Integer nums;
}

View File

@ -0,0 +1,51 @@
package com.hb0730.boot.admin.modules.api.buiness.model;
import com.baomidou.mybatisplus.annotation.TableName;
import com.hb0730.boot.admin.data.domain.BaseEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/**
* 优惠券表
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/2/4
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ToString
@TableName(value = "sys_coupon",autoResultMap = true)
public class SysCoupon extends BaseEntity {
/**
*优惠券名称
*/
private String couponName;
/**
* 优惠券数量
*/
private Integer nums;
private String userId;
private String title;
private String receiveDate;
private String receiveTime;
private String activityRules;
private String activityDec;
private String giftName;
private String giftImage;
private String openId;
private String tagImg;
}

View File

@ -0,0 +1,37 @@
package com.hb0730.boot.admin.modules.api.buiness.model;
import com.baomidou.mybatisplus.annotation.TableName;
import com.hb0730.boot.admin.data.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/**
* 优惠券表
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/2/4
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ToString
@TableName(value = "sys_coupon_log")
public class SysCouponLog extends BaseEntity {
/**
*优惠券名称
*/
private String title;
private String userId;
private String couponId;
private String openId;
private String checkCode;
private String userName;
private String giftName;
}

View File

@ -0,0 +1,100 @@
package com.hb0730.boot.admin.modules.api.buiness.model;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.hb0730.boot.admin.config.handler.JsonHandler;
import com.hb0730.boot.admin.data.domain.BaseEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.List;
/**
* 店铺表
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/2/4
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ToString
@TableName(value = "sys_shop",autoResultMap = true)
public class SysShop extends BaseEntity {
/**
* 店铺名称
*/
private String name;
/**
* 店铺介绍(中文)
*/
private String introChi;
/**
* 店铺介绍(英文)
*/
private String introEng;
/**
* 店铺介绍(日文)
*/
private String introJap;
/**
* 预约电话
*/
private String phone;
/**
* 营业时间(开始时间)
*/
private String startTime;
/**
* 营业时间(结束时间)
*/
private String endTime;
/**
* 标签图片url
*/
private String tagUrl;
/**
* logo url
*/
private String logoUrl;
/**
* 名字url
*/
private String namePicture;
/**
* 轮播图url
*/
@TableField(value = "picture_url")
private String pictureUrl;
@TableField(value = "vagetable_url")
private String vagetableUrl;
/**
* 店铺楼层
*/
private Integer floor;
/**
* 是否启用,true:启用,false:禁用
*/
@TableField(value = "is_enable" )
private Boolean isEnable= false;
@TableField(value = "season" )
private String season;
@TableField(value = "title")
private String title;
@TableField(value = "hour")
private String hour;
@Schema(description = "排序")
@TableField(value = "sort")
private Integer sort;
}

View File

@ -0,0 +1,25 @@
package com.hb0730.boot.admin.modules.api.buiness.model.query;
import com.hb0730.boot.admin.data.domain.BasePageQuery;
import io.swagger.v3.oas.annotations.Parameter;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/**
* 用户查询参数
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/6/8
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ToString
public class BoxQuery extends BasePageQuery {
/**
* 店铺id
*/
@Parameter(description = "店铺id")
private String shopId;
}

View File

@ -0,0 +1,22 @@
package com.hb0730.boot.admin.modules.api.buiness.model.query;
import com.hb0730.boot.admin.data.domain.BasePageQuery;
import io.swagger.v3.oas.annotations.Parameter;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/**
* 用户查询参数
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/6/8
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ToString
public class CouponQuery extends BasePageQuery {
private String id;
}

View File

@ -0,0 +1,25 @@
package com.hb0730.boot.admin.modules.api.buiness.model.query;
import com.hb0730.boot.admin.data.domain.BasePageQuery;
import io.swagger.v3.oas.annotations.Parameter;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/**
* 用户查询参数
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/6/8
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ToString
public class ShopQuery extends BasePageQuery {
/**
* 店铺名称
*/
@Parameter(description = "店铺名称")
private String name;
}

View File

@ -0,0 +1,80 @@
package com.hb0730.boot.admin.modules.api.buiness.model.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 用户信息
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/6/8
*/
@Data
@EqualsAndHashCode
@ToString
public class BoxVO implements Serializable {
/**
* ID
*/
@Schema(description = "id")
protected String id;
/**
* 创建人
*/
@Schema(description = "创建人")
protected String createdBy;
/**
* 创建时间
*/
@Schema(description = "创建时间")
protected LocalDateTime created;
/**
* 更新人
*/
@Schema(description = "更新人")
protected String modifiedBy;
/**
* 更新时间
*/
@Schema(description = "更新时间")
protected LocalDateTime modified;
/**
* 所属店铺id
*/
@Schema(description = "更新时间")
private String shopId;
/**
* 包厢名称
*/
@Schema(description = "包厢名称")
private String name;
/**
* 包厢最小人数
*/
@Schema(description = "包厢最小人数")
private Integer min;
/**
* 包厢最大人数
*/
@Schema(description = "包厢最大人数")
private Integer max;
/**
* 包厢图片路径
*/
@Schema(description = "包厢图片路径")
private String imagesUrl;
@Schema(description = "包厢数量")
private Integer nums;
}

View File

@ -0,0 +1,98 @@
package com.hb0730.boot.admin.modules.api.buiness.model.vo;
import com.baomidou.mybatisplus.annotation.TableName;
import com.hb0730.boot.admin.data.domain.BaseEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.time.LocalDateTime;
/**
* 包厢表
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/2/4
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ToString
@TableName
public class CouponLogVO extends BaseEntity {
/**
* ID
*/
@Schema(description = "id")
protected String id;
/**
* 创建人
*/
@Schema(description = "创建人")
protected String createdBy;
/**
* 创建时间
*/
@Schema(description = "创建时间")
protected LocalDateTime created;
/**
* 更新人
*/
@Schema(description = "更新人")
protected String modifiedBy;
/**
* 更新时间
*/
@Schema(description = "更新时间")
protected LocalDateTime modified;
/**
* 优惠券名称
*/
@Schema(description = "优惠券名称")
private String couponName;
/**
* 用户id
*/
@Schema(description = "用户id")
private String userId;
@Schema(description = "openId")
private String openId;
/**
* 优惠券数量
*/
@Schema(description = "优惠券数量")
private Integer nums;
@Schema(description = "优惠券标题")
private String title;
@Schema(description = "优惠券领取日期")
private String receiveDate;
@Schema(description = "优惠券领取时间")
private String receiveTime;
@Schema(description = "活动规则")
private String activityRules;
@Schema(description = "活动说明")
private String activityDec;
@Schema(description = "礼品名称")
private String giftName;
@Schema(description = "礼品图片")
private String giftImage;
@Schema(description = "优惠券ID")
private String couponId;
private String checkCode;
}

View File

@ -0,0 +1,96 @@
package com.hb0730.boot.admin.modules.api.buiness.model.vo;
import com.baomidou.mybatisplus.annotation.TableName;
import com.hb0730.boot.admin.data.domain.BaseEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.time.LocalDateTime;
/**
* 包厢表
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/2/4
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ToString
@TableName
public class CouponVO extends BaseEntity {
/**
* ID
*/
@Schema(description = "id")
protected String id;
/**
* 创建人
*/
@Schema(description = "创建人")
protected String createdBy;
/**
* 创建时间
*/
@Schema(description = "创建时间")
protected LocalDateTime created;
/**
* 更新人
*/
@Schema(description = "更新人")
protected String modifiedBy;
/**
* 更新时间
*/
@Schema(description = "更新时间")
protected LocalDateTime modified;
/**
* 优惠券名称
*/
@Schema(description = "优惠券名称")
private String couponName;
/**
* 用户id
*/
@Schema(description = "用户id")
private String userId;
@Schema(description = "openId")
private String openId;
/**
* 优惠券数量
*/
@Schema(description = "优惠券数量")
private Integer nums;
@Schema(description = "优惠券标题")
private String title;
@Schema(description = "优惠券领取日期")
private String receiveDate;
@Schema(description = "优惠券领取时间")
private String receiveTime;
@Schema(description = "活动规则")
private String activityRules;
@Schema(description = "活动说明")
private String activityDec;
@Schema(description = "礼品名称")
private String giftName;
@Schema(description = "礼品图片")
private String giftImage;
@Schema(description = "标签图片")
private String tagImg;
}

View File

@ -0,0 +1,99 @@
package com.hb0730.boot.admin.modules.api.buiness.model.vo;
import com.baomidou.mybatisplus.annotation.TableName;
import com.hb0730.boot.admin.data.domain.BaseEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.time.LocalDateTime;
/**
* 包厢表
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/2/4
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ToString
@TableName
public class GetCouponLogVO extends BaseEntity {
/**
* ID
*/
@Schema(description = "id")
protected String id;
/**
* 创建人
*/
@Schema(description = "创建人")
protected String createdBy;
/**
* 创建时间
*/
@Schema(description = "创建时间")
protected LocalDateTime created;
/**
* 更新人
*/
@Schema(description = "更新人")
protected String modifiedBy;
/**
* 更新时间
*/
@Schema(description = "更新时间")
protected LocalDateTime modified;
/**
* 优惠券名称
*/
@Schema(description = "优惠券名称")
private String couponName;
/**
* 用户id
*/
@Schema(description = "用户id")
private String userId;
@Schema(description = "openId")
private String openId;
/**
* 优惠券数量
*/
@Schema(description = "优惠券数量")
private Integer nums;
@Schema(description = "优惠券标题")
private String title;
@Schema(description = "优惠券领取日期")
private String receiveDate;
@Schema(description = "优惠券领取时间")
private String receiveTime;
@Schema(description = "活动规则")
private String activityRules;
@Schema(description = "活动说明")
private String activityDec;
@Schema(description = "礼品名称")
private String giftName;
@Schema(description = "礼品图片")
private String giftImage;
@Schema(description = "优惠券ID")
private String couponId;
@Schema(description = "用户名称")
private String userName;
}

View File

@ -0,0 +1,12 @@
package com.hb0730.boot.admin.modules.api.buiness.model.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class HourVO {
@Schema(description = "id")
private String id;
@Schema(description = "小时菜品url")
private String hour;
}

View File

@ -0,0 +1,13 @@
package com.hb0730.boot.admin.modules.api.buiness.model.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class SeasonVO {
@Schema(description = "id")
private String id;
@Schema(description = "季节菜品url")
private String season;
}

View File

@ -0,0 +1,141 @@
package com.hb0730.boot.admin.modules.api.buiness.model.vo;
import cn.hutool.core.util.StrUtil;
import com.hb0730.boot.admin.base.util.AesEncryptUtil;
import com.hb0730.boot.admin.modules.api.buiness.model.PictureEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;
/**
* 用户信息
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/6/8
*/
@Data
@EqualsAndHashCode
@ToString
public class ShopVO implements Serializable {
/**
* ID
*/
@Schema(description = "id")
protected String id;
/**
* 创建人
*/
@Schema(description = "创建人")
protected String createdBy;
/**
* 创建时间
*/
@Schema(description = "创建时间")
protected LocalDateTime created;
/**
* 更新人
*/
@Schema(description = "更新人")
protected String modifiedBy;
/**
* 更新时间
*/
@Schema(description = "更新时间")
protected LocalDateTime modified;
/**
* 店铺名称
*/
@Schema(description = "店铺名称")
private String name;
/**
* 店铺介绍(中文)
*/
@Schema(description = "店铺介绍(中文)")
private String introChi;
/**
* 店铺介绍(英文)
*/
@Schema(description = "店铺介绍(英文)")
private String introEng;
/**
* 店铺介绍(日文)
*/
@Schema(description = "店铺介绍(日文")
private String introJap;
/**
* 预约电话
*/
@Schema(description = "预约电话")
private String phone;
/**
* 营业时间(开始时间)
*/
@Schema(description = "营业时间(开始时间)")
private String startTime;
/**
* 营业时间(结束时间)
*/
@Schema(description = "营业时间(结束时间)")
private String endTime;
/**
* 标签图片url
*/
@Schema(description = "标签图片url")
private String tagUrl;
/**
* logo url
*/
@Schema(description = "logo url")
private String logoUrl;
/**
* 轮播图url
*/
@Schema(description = "轮播图url")
private String pictureUrl;
/**
* 店铺楼层
*/
@Schema(description = "店铺楼层")
private Integer floor;
/**
* 是否启用,true:启用,false:禁用
*/
@Schema(description = "是否启用,true:启用,false:禁用")
private Boolean isEnable;
/**
* 名字url
*/
@Schema(description = "名字url")
private String namePicture;
@Schema(description = "菜品url")
private String vagetableUrl;
@Schema(description = "季节菜品url")
private String season;
@Schema(description = "名字边上标题")
private String title;
@Schema(description = "小时菜品")
private String hour;
@Schema(description = "排序")
private Integer sort;
}

View File

@ -0,0 +1,12 @@
package com.hb0730.boot.admin.modules.api.buiness.service;
import com.hb0730.boot.admin.base.R;
import org.springframework.web.multipart.MultipartFile;
public interface OssService {
R uploadFile(MultipartFile file);
R deleteFile(String path);
}

View File

@ -0,0 +1,23 @@
package com.hb0730.boot.admin.modules.api.buiness.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.hb0730.boot.admin.base.R;
import com.hb0730.boot.admin.data.domain.BasePage;
import com.hb0730.boot.admin.modules.api.buiness.model.SysBox;
import com.hb0730.boot.admin.modules.api.buiness.model.SysShop;
import com.hb0730.boot.admin.modules.api.buiness.model.query.BoxQuery;
import com.hb0730.boot.admin.modules.api.buiness.model.query.ShopQuery;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.BoxVO;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.ShopVO;
import java.util.List;
public interface SysBoxService extends IService<SysBox> {
BasePage<BoxVO> queryPage(BoxQuery query);
R<BoxVO>detail(String id);
R<BoxVO> saveShop(BoxVO boxVO);
R<BoxVO> updateById(String id, BoxVO boxVO);
}

View File

@ -0,0 +1,21 @@
package com.hb0730.boot.admin.modules.api.buiness.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.hb0730.boot.admin.base.R;
import com.hb0730.boot.admin.data.domain.BasePage;
import com.hb0730.boot.admin.modules.api.buiness.model.SysCoupon;
import com.hb0730.boot.admin.modules.api.buiness.model.SysCouponLog;
import com.hb0730.boot.admin.modules.api.buiness.model.query.CouponQuery;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.CouponLogVO;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.CouponVO;
public interface SysCouponLogService extends IService<SysCouponLog> {
BasePage<CouponLogVO> queryPage(CouponQuery query);
R<CouponLogVO> detail(String id);
R<CouponLogVO> saveShop(CouponLogVO couponlogVO);
R<CouponLogVO> updateById(String id, CouponLogVO couponVO);
}

View File

@ -0,0 +1,29 @@
package com.hb0730.boot.admin.modules.api.buiness.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.hb0730.boot.admin.base.R;
import com.hb0730.boot.admin.data.domain.BasePage;
import com.hb0730.boot.admin.modules.api.buiness.model.SysBox;
import com.hb0730.boot.admin.modules.api.buiness.model.SysCoupon;
import com.hb0730.boot.admin.modules.api.buiness.model.SysCouponLog;
import com.hb0730.boot.admin.modules.api.buiness.model.query.BoxQuery;
import com.hb0730.boot.admin.modules.api.buiness.model.query.CouponQuery;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.BoxVO;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.CouponVO;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.GetCouponLogVO;
import java.util.List;
public interface SysCouponService extends IService<SysCoupon> {
BasePage<CouponVO> queryPage(CouponQuery query);
R<CouponVO>detail(String id);
R<CouponVO> saveShop(CouponVO couponVO);
//
R<CouponVO> updateById(String id, CouponVO couponVO);
R<GetCouponLogVO> getCoupon(String id , String openId);
R<String> verification(String id, String checkCode);
}

View File

@ -0,0 +1,35 @@
package com.hb0730.boot.admin.modules.api.buiness.service;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.IService;
import com.hb0730.boot.admin.base.R;
import com.hb0730.boot.admin.base.util.AesEncryptUtil;
import com.hb0730.boot.admin.data.domain.BasePage;
import com.hb0730.boot.admin.modules.api.buiness.model.SysShop;
import com.hb0730.boot.admin.modules.api.buiness.model.query.ShopQuery;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.HourVO;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.SeasonVO;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.ShopVO;
import com.hb0730.boot.admin.modules.sys.system.model.entity.SysUser;
import com.hb0730.boot.admin.modules.sys.system.model.vo.UserVO;
import java.util.HashSet;
import java.util.List;
public interface SysShopService extends IService<SysShop> {
BasePage<ShopVO> queryPage(ShopQuery query);
R<ShopVO> detail(String id);
R<ShopVO> updateById(String id, ShopVO vo);
R<ShopVO> saveShop(ShopVO shopVO);
List<SeasonVO> getSeason();
List<HourVO> getHour();
}

View File

@ -0,0 +1,59 @@
package com.hb0730.boot.admin.modules.api.buiness.service.impl;
import cn.hutool.core.date.DateTime;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.hb0730.boot.admin.base.R;
import com.hb0730.boot.admin.modules.api.buiness.service.OssService;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;
@Service("ossService")
public class OssServiceImpl implements OssService {
private static final String schema= "https://";
private static final String endpoint= "oss-cn-shanghai.aliyuncs.com";
private static final String accessKeyId= "LTAI5tMhBNyfJH7voue1VdD9";
private static final String accessKeySecret= "tdlSGtauAy154Yx1qX5peuZgpQVzWh";
private static final String bucketName= "huanqiuzhongxin";//huanqiuzhongxin
@Override
public R uploadFile(MultipartFile file) {
try {
//4、 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(schema + endpoint, accessKeyId, accessKeySecret);
String fileName = file.getOriginalFilename();//获取上传文件的名称
InputStream inputStream = file.getInputStream();
// 通过ossClient上传文件: 参数1:桶名, 参数2:上传后的文件路径+文件名 ,参数3:要上传的文件流
String objectName = new DateTime().toString("yyyy/MM/dd/") +
UUID.randomUUID().toString().replace("-", "").substring(0, 16) +
"_" + fileName;//使用UUID+源文件名称后缀拼接生成objectName
ossClient.putObject(bucketName, objectName, inputStream);
// 关闭OSSClient。
ossClient.shutdown();
String path = schema + bucketName + "." + endpoint + "/" + objectName;//手动拼接上传成功的图片地址
System.out.println("path ======================================" + path);
return R.OK(path);
} catch (IOException e) {
throw new RuntimeException("图片上传失败");
}
}
@Override
public R deleteFile(String path) {
String host = schema + bucketName + "." + endpoint +"/";
String objectName = path.replace(host,"");
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
ossClient.deleteObject(bucketName, objectName.trim());
ossClient.shutdown();
return R.OK("删除成功");
}
}

View File

@ -0,0 +1,95 @@
package com.hb0730.boot.admin.modules.api.buiness.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
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.hb0730.boot.admin.base.R;
import com.hb0730.boot.admin.data.domain.BasePage;
import com.hb0730.boot.admin.modules.api.buiness.mapper.SysBoxMapper;
import com.hb0730.boot.admin.modules.api.buiness.mapper.SysShopMapper;
import com.hb0730.boot.admin.modules.api.buiness.model.SysBox;
import com.hb0730.boot.admin.modules.api.buiness.model.SysShop;
import com.hb0730.boot.admin.modules.api.buiness.model.query.BoxQuery;
import com.hb0730.boot.admin.modules.api.buiness.model.query.ShopQuery;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.BoxVO;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.ShopVO;
import com.hb0730.boot.admin.modules.api.buiness.service.SysBoxService;
import com.hb0730.boot.admin.modules.api.buiness.service.SysShopService;
import com.hb0730.boot.admin.security.util.SecurityUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;
@Service
@Slf4j
public class SysBoxServiceImpl extends ServiceImpl<SysBoxMapper, SysBox> implements SysBoxService {
@Autowired
private SysShopMapper sysShopMapper;
@Override
public BasePage<BoxVO> queryPage(BoxQuery query) {
Page<BoxVO> page = new Page<>();
if ( query.getSize() == 0 || query.getCurrent() == 0) {
page = new Page<>(0, Integer.MAX_VALUE);
}else {
page = new Page<>(query.getCurrent(), query.getSize());
}
List<SysBox> boxes = baseMapper.queryPage(page, query);
List<BoxVO> collect = boxes.stream().map(box -> {
BoxVO boxVO = new BoxVO();
BeanUtils.copyProperties(box, boxVO);
return boxVO;
}).collect(Collectors.toList());
return new BasePage<>(page.getCurrent(), page.getSize(), page.getTotal(), collect);
}
@Override
public R<BoxVO> detail(String id) {
LambdaQueryWrapper<SysBox> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SysBox::getId, id);
SysBox box = this.baseMapper.selectOne(wrapper);
BoxVO boxVO = new BoxVO();
BeanUtil.copyProperties(box, boxVO);
return R.OK(boxVO);
}
@Override
public R<BoxVO> saveShop(BoxVO boxVO) {
SysBox box = new SysBox();
BeanUtils.copyProperties(boxVO,box);
box.setCreated(LocalDateTime.now());
box.setCreatedBy(SecurityUtil.getCurrentUsername());
box.setModified(LocalDateTime.now());
box.setModifiedBy(SecurityUtil.getCurrentUsername());
this.baseMapper.insert(box);
return R.OK(boxVO);
}
@Override
public R<BoxVO> updateById(String id, BoxVO boxVO) {
SysBox box = baseMapper.selectById(id);
if (null == box) {
return R.NG("包厢不存在");
}
BeanUtil.copyProperties(boxVO, box);
baseMapper.updateById(box);
return R.OK(boxVO);
}
}

View File

@ -0,0 +1,104 @@
package com.hb0730.boot.admin.modules.api.buiness.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hb0730.boot.admin.base.R;
import com.hb0730.boot.admin.data.domain.BasePage;
import com.hb0730.boot.admin.modules.api.buiness.mapper.SysCouponLogMapper;
import com.hb0730.boot.admin.modules.api.buiness.mapper.SysCouponMapper;
import com.hb0730.boot.admin.modules.api.buiness.model.SysCoupon;
import com.hb0730.boot.admin.modules.api.buiness.model.SysCouponLog;
import com.hb0730.boot.admin.modules.api.buiness.model.query.CouponQuery;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.CouponLogVO;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.CouponVO;
import com.hb0730.boot.admin.modules.api.buiness.service.SysCouponLogService;
import com.hb0730.boot.admin.modules.api.buiness.service.SysCouponService;
import com.hb0730.boot.admin.modules.sys.system.mapper.SysUserMapper;
import com.hb0730.boot.admin.modules.sys.system.model.entity.SysUser;
import com.hb0730.boot.admin.security.util.SecurityUtil;
import lombok.Synchronized;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;
@Service
@Slf4j
public class SysCouponLogServiceImpl extends ServiceImpl<SysCouponLogMapper, SysCouponLog> implements SysCouponLogService {
@Autowired
private SysCouponLogMapper sysCouponLogMapper;
@Autowired
private SysUserMapper sysUserMapper;
@Override
public BasePage<CouponLogVO> queryPage(CouponQuery query) {
Page<CouponLogVO> page = new Page<>();
if ( query.getSize() == 0 || query.getCurrent() == 0) {
page = new Page<>(0, Integer.MAX_VALUE);
}else {
page = new Page<>(query.getCurrent(), query.getSize());
}
List<SysCouponLog> coupons = sysCouponLogMapper.queryPage(page, query);
List<CouponLogVO> collect = coupons.stream().map(coupon -> {
CouponLogVO couponLogVO = new CouponLogVO();
BeanUtils.copyProperties(coupon, couponLogVO);
return couponLogVO;
}).collect(Collectors.toList());
return new BasePage<>(page.getCurrent(), page.getSize(), page.getTotal(), collect);
}
@Override
public R<CouponLogVO> detail(String id) {
LambdaQueryWrapper<SysCouponLog> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SysCouponLog::getId, id);
SysCouponLog sysCouponLog = this.baseMapper.selectOne(wrapper);
CouponLogVO couponVO = new CouponLogVO();
BeanUtil.copyProperties(sysCouponLog, couponVO);
return R.OK(couponVO);
}
@Override
public R<CouponLogVO> saveShop(CouponLogVO couponLogVO) {
SysCouponLog coupon = new SysCouponLog();
BeanUtils.copyProperties(couponLogVO,coupon);
coupon.setCreated(LocalDateTime.now());
coupon.setCreatedBy(SecurityUtil.getCurrentUsername());
coupon.setModified(LocalDateTime.now());
coupon.setModifiedBy(SecurityUtil.getCurrentUsername());
this.baseMapper.insert(coupon);
return R.OK(couponLogVO);
}
//
@Override
public R<CouponLogVO> updateById(String id, CouponLogVO couponVO) {
SysCouponLog coupon = getById(id);
if (null == coupon) {
return R.NG("优惠券不存在");
}
BeanUtil.copyProperties(couponVO, coupon);
baseMapper.updateById(coupon);
return R.OK(couponVO);
}
}

View File

@ -0,0 +1,174 @@
package com.hb0730.boot.admin.modules.api.buiness.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hb0730.boot.admin.base.R;
import com.hb0730.boot.admin.data.domain.BasePage;
import com.hb0730.boot.admin.modules.api.buiness.mapper.SysBoxMapper;
import com.hb0730.boot.admin.modules.api.buiness.mapper.SysCouponLogMapper;
import com.hb0730.boot.admin.modules.api.buiness.mapper.SysCouponMapper;
import com.hb0730.boot.admin.modules.api.buiness.mapper.SysShopMapper;
import com.hb0730.boot.admin.modules.api.buiness.model.SysBox;
import com.hb0730.boot.admin.modules.api.buiness.model.SysCoupon;
import com.hb0730.boot.admin.modules.api.buiness.model.SysCouponLog;
import com.hb0730.boot.admin.modules.api.buiness.model.SysShop;
import com.hb0730.boot.admin.modules.api.buiness.model.query.BoxQuery;
import com.hb0730.boot.admin.modules.api.buiness.model.query.CouponQuery;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.BoxVO;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.CouponVO;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.GetCouponLogVO;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.ShopVO;
import com.hb0730.boot.admin.modules.api.buiness.service.SysBoxService;
import com.hb0730.boot.admin.modules.api.buiness.service.SysCouponLogService;
import com.hb0730.boot.admin.modules.api.buiness.service.SysCouponService;
import com.hb0730.boot.admin.modules.sys.system.mapper.SysUserMapper;
import com.hb0730.boot.admin.modules.sys.system.model.entity.SysUser;
import com.hb0730.boot.admin.security.util.SecurityUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.util.Formatter;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@Service
@Slf4j
public class SysCouponServiceImpl extends ServiceImpl<SysCouponMapper, SysCoupon> implements SysCouponService {
@Autowired
private SysUserMapper sysUserMapper;
@Autowired
private SysCouponLogMapper sysCouponLogMapper;
@Override
public BasePage<CouponVO> queryPage(CouponQuery query) {
Page<CouponVO> page = new Page<>();
if ( query.getSize() == 0 || query.getCurrent() == 0) {
page = new Page<>(0, Integer.MAX_VALUE);
}else {
page = new Page<>(query.getCurrent(), query.getSize());
}
List<SysCoupon> coupons = baseMapper.queryPage(page, query);
List<CouponVO> collect = coupons.stream().map(coupon -> {
CouponVO couponVO = new CouponVO();
BeanUtils.copyProperties(coupon, couponVO);
return couponVO;
}).collect(Collectors.toList());
return new BasePage<>(page.getCurrent(), page.getSize(), page.getTotal(), collect);
}
@Override
public R<CouponVO> detail(String id) {
LambdaQueryWrapper<SysCoupon> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SysCoupon::getId, id);
SysCoupon box = this.baseMapper.selectOne(wrapper);
CouponVO couponVO = new CouponVO();
BeanUtil.copyProperties(box, couponVO);
return R.OK(couponVO);
}
@Override
public R<CouponVO> saveShop(CouponVO couponVO) {
SysCoupon coupon = new SysCoupon();
BeanUtils.copyProperties(couponVO,coupon);
coupon.setCreated(LocalDateTime.now());
coupon.setCreatedBy(SecurityUtil.getCurrentUsername());
coupon.setModified(LocalDateTime.now());
coupon.setModifiedBy(SecurityUtil.getCurrentUsername());
this.baseMapper.insert(coupon);
return R.OK(couponVO);
}
//
@Override
public R<CouponVO> updateById(String id, CouponVO couponVO) {
SysCoupon coupon = getById(id);
if (null == coupon) {
return R.NG("优惠券不存在");
}
BeanUtil.copyProperties(couponVO, coupon);
baseMapper.updateById(coupon);
return R.OK(couponVO);
}
@Override
public R<GetCouponLogVO> getCoupon(String id,String openid) {
LambdaQueryWrapper<SysCouponLog> logs = new LambdaQueryWrapper<>();
SysCoupon coupon = this.baseMapper.selectById(id);
LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
SysUser user = sysUserMapper.selectOne(wrapper.eq(SysUser::getOpenId, openid));
long l = System.currentTimeMillis();
String s = Long.toString(l, 36);
SysCouponLog sysCouponLog = new SysCouponLog();
if(Objects.nonNull(user)){
sysCouponLog.setUserId(user.getId());
if (StringUtils.isNotEmpty(user.getUsername())) {
sysCouponLog.setUserName(user.getUsername());
}
sysCouponLog.setOpenId(user.getOpenId());
}
sysCouponLog.setCouponId(coupon.getId());
sysCouponLog.setTitle(coupon.getTitle());
sysCouponLog.setGiftName(coupon.getGiftName());
sysCouponLog.setCreated(LocalDateTime.now());
sysCouponLog.setCheckCode(s);
sysCouponLogMapper.insert(sysCouponLog);
baseMapper.updateNums(id);
GetCouponLogVO getCouponLogVO = new GetCouponLogVO();
BeanUtils.copyProperties(sysCouponLog,getCouponLogVO);
return R.OK(getCouponLogVO);
}
@Override
public R<String> verification(String id, String checkCode) {
LambdaQueryWrapper<SysCouponLog> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SysCouponLog::getCheckCode, checkCode);
wrapper.eq(SysCouponLog::getId, id);
SysCouponLog sysCouponLog = sysCouponLogMapper.selectOne(wrapper);
if(Objects.nonNull(sysCouponLog)){
UpdateWrapper<SysCouponLog> updateWrapper = new UpdateWrapper();
updateWrapper.set("modified", LocalDateTime.now());
updateWrapper.eq("id", id);
sysCouponLogMapper.update(sysCouponLog,updateWrapper);
return R.OK("验证通过!!!");
}else {
return R.error(201,"验证失败!!!!");
}
}
}

View File

@ -0,0 +1,111 @@
package com.hb0730.boot.admin.modules.api.buiness.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hb0730.boot.admin.base.R;
import com.hb0730.boot.admin.data.domain.BasePage;
import com.hb0730.boot.admin.modules.api.buiness.mapper.SysShopMapper;
import com.hb0730.boot.admin.modules.api.buiness.model.SysShop;
import com.hb0730.boot.admin.modules.api.buiness.model.query.ShopQuery;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.HourVO;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.SeasonVO;
import com.hb0730.boot.admin.modules.api.buiness.model.vo.ShopVO;
import com.hb0730.boot.admin.modules.api.buiness.service.SysShopService;
import com.hb0730.boot.admin.security.util.SecurityUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;
@Service
@Slf4j
public class SysShopServiceImpl extends ServiceImpl<SysShopMapper, SysShop> implements SysShopService {
@Autowired
private SysShopMapper sysShopMapper;
@Override
public BasePage<ShopVO> queryPage(ShopQuery query) {
Page<ShopVO> page = new Page<>();
if ( query.getSize() == 0 || query.getCurrent() == 0) {
page = new Page<>(0, Integer.MAX_VALUE);
}else {
page = new Page<>(query.getCurrent(), query.getSize());
}
List<SysShop> shops = this.sysShopMapper.queryPage(page, query);
List<ShopVO> collect = shops.stream().map(shop -> {
ShopVO shopVO = new ShopVO();
BeanUtils.copyProperties(shop, shopVO);
return shopVO;
}).collect(Collectors.toList());
System.out.println(collect);
return new BasePage<>(page.getCurrent(), page.getSize(), page.getTotal(), collect);
}
@Override
public R<ShopVO> detail(String id)
{
SysShop shop = this.baseMapper.selectById(id);
ShopVO shopVO = new ShopVO();
BeanUtil.copyProperties(shop, shopVO);
return R.OK(shopVO);
}
@Override
public R<ShopVO> updateById(String id, ShopVO vo) {
SysShop shop = getById(id);
if (null == shop) {
return R.NG("店铺不存在");
}
BeanUtil.copyProperties(vo, shop);
baseMapper.updateById(shop);
return R.OK(vo);
}
@Override
public R<ShopVO> saveShop(ShopVO shopVO) {
SysShop sysShop = new SysShop();
BeanUtils.copyProperties(shopVO,sysShop);
sysShop.setCreated(LocalDateTime.now());
sysShop.setCreatedBy(SecurityUtil.getCurrentUsername());
sysShop.setModified(LocalDateTime.now());
sysShop.setModifiedBy(SecurityUtil.getCurrentUsername());
// sysShop.setPictureUrl(shopVO.getPictureUrl().toString());
this.baseMapper.insert(sysShop);
return R.OK(shopVO);
}
@Override
public List<SeasonVO> getSeason() {
List<SeasonVO> season = this.baseMapper.getSeason();
return season;
}
@Override
public List<HourVO> getHour() {
List<HourVO> hour = this.baseMapper.getHour();
return hour;
}
}

View File

@ -0,0 +1,98 @@
package com.hb0730.boot.admin.modules.sys.auth.controller;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.crypto.SecureUtil;
import com.hb0730.boot.admin.base.R;
import com.hb0730.boot.admin.base.util.JwtUtil;
import com.hb0730.boot.admin.base.util.RsaUtil;
import com.hb0730.boot.admin.modules.sys.auth.event.LogoutEvent;
import com.hb0730.boot.admin.modules.sys.auth.model.LoginRequest;
import com.hb0730.boot.admin.modules.sys.auth.model.LoginResponse;
import com.hb0730.boot.admin.security.config.LoginProperties;
import com.hb0730.boot.admin.security.model.UserInfo;
import com.hb0730.boot.admin.security.token.TokenProvider;
import com.hb0730.boot.admin.security.util.SecurityUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationContext;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
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;
/**
* 授权、根据token获取用户详细信息
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/1/12
*/
@RestController
@RequestMapping("/auth")
@Tag(name = "系统: 授权接口")
@RequiredArgsConstructor
public class AuthorizationController {
private final AuthenticationManager authenticationManager;
private final TokenProvider jwtTokenRedisCacheProvider;
private final LoginProperties loginProperties;
private final ApplicationContext applicationContext;
@Operation(summary = "登录授权")
@PostMapping("/login")
public R<LoginResponse> login(HttpServletRequest request, @RequestBody @Valid LoginRequest login) throws Exception {
SecureUtil.disableBouncyCastle();
String password = login.getPassword();
// 解密
password = RsaUtil.decryptByPrivateKey(login.getPassword(), loginProperties.getRsaPrivateKey());
//
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(login.getUsername(), password);
Authentication authenticate = null;
try {
// 会调用UserDetailsService#loadUserByUsername(String username)
authenticate = authenticationManager.authenticate(authenticationToken);
} catch (AuthenticationException e) {
if (e instanceof UsernameNotFoundException) {
return R.NG("用户名不存在");
} else {
return R.NG(e.getMessage());
}
}
assert authenticate != null;
UserInfo userInfo = (UserInfo) authenticate.getPrincipal();
String jwtToken = jwtTokenRedisCacheProvider.createToken(userInfo, request);
LoginResponse response = BeanUtil.toBean(userInfo, LoginResponse.class);
response.setToken(jwtToken);
return R.OK(response);
}
@Operation(summary = "用户信息")
@GetMapping("/info")
public R<Object> getUserInfo() {
return null;
}
@Operation(summary = "退出登录")
@PostMapping("/logout")
public R<String> logout(HttpServletRequest request) {
String _jwtToken = JwtUtil.getTokenByRequest(request);
try {
// 如果超时,则获取失败
UserInfo userInfo = SecurityUtil.getCurrentUser();
applicationContext.publishEvent(new LogoutEvent(this, _jwtToken, userInfo.getUsername(), userInfo.getUserid()));
} catch (Exception ignored) {
}
jwtTokenRedisCacheProvider.removeToken(_jwtToken);
return R.OK("成功");
}
}

View File

@ -0,0 +1,73 @@
package com.hb0730.boot.admin.modules.sys.auth.controller;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class WeChatJSSDKSignature {
public static void main(String[] args) {
// 替换成你的公众号AppID和AppSecret
String appId = "wxbad2e8a91c62a734";
String appSecret = "e1b7fc425ca9cca05dd83609a6dc9c00";
// 替换成当前页面的URL
String url = "CURRENT_PAGE_URL";
String nonceStr = createNonceStr();
String timestamp = createTimestamp();
String jsapiTicket = getJsApiTicket(appId, appSecret);
String signature = generateSignature(jsapiTicket, nonceStr, timestamp, url);
System.out.println("nonceStr: " + nonceStr);
System.out.println("timestamp: " + timestamp);
System.out.println("signature: " + signature);
}
private static String createNonceStr() {
return UUID.randomUUID().toString().replaceAll("-", "");
}
private static String createTimestamp() {
return Long.toString(System.currentTimeMillis() / 1000);
}
private static String getJsApiTicket(String appId, String appSecret) {
// 调用微信API获取jsapi_ticket的逻辑,这里省略实现
// 返回有效的jsapi_ticket
return "YOUR_JSAPI_TICKET";
}
private static String generateSignature(String jsapiTicket, String nonceStr, String timestamp, String url) {
Map<String, String> paramMap = new HashMap<>();
paramMap.put("noncestr", nonceStr);
paramMap.put("jsapi_ticket", jsapiTicket);
paramMap.put("timestamp", timestamp);
paramMap.put("url", url);
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, String> entry : paramMap.entrySet()) {
sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
}
sb.deleteCharAt(sb.length() - 1);
try {
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(sb.toString().getBytes("UTF-8"));
byte[] digest = crypt.digest();
Formatter formatter = new Formatter();
for (byte b : digest) {
formatter.format("%02x", b);
}
String signature = formatter.toString();
formatter.close();
return signature;
} catch (NoSuchAlgorithmException | java.io.UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
}
}

View File

@ -0,0 +1,197 @@
package com.hb0730.boot.admin.modules.sys.auth.controller;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.mrzin.tool.http.HttpTool;
import cn.mrzin.tool.lang.StringUtils;
import cn.mrzin.wx.login.WxCommonUtil;
import cn.mrzin.wx.login.WxH5LoginUtil;
import cn.mrzin.wx.login.enums.AccessTokenGrantType;
import cn.mrzin.wx.login.model.WxSecretInfo;
import cn.mrzin.wx.login.response.AccessTokenInfo;
import cn.mrzin.wx.login.response.WxH5LoginResponse;
import cn.mrzin.wx.login.response.WxLoginResponse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.hb0730.boot.admin.base.R;
import com.hb0730.boot.admin.modules.sys.auth.model.*;
import com.hb0730.boot.admin.modules.sys.auth.model.dto.LoginDto;
import com.hb0730.boot.admin.modules.sys.system.model.entity.SysUser;
import com.hb0730.boot.admin.modules.sys.system.service.SysUserService;
import com.hb0730.boot.admin.security.model.UserInfo;
import com.hb0730.boot.admin.security.token.TokenProvider;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
/**
* 授权、根据token获取用户详细信息
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/1/12
*/
@RestController
@RequestMapping("/wx")
@Tag(name = "系统: h5授权接口")
@RequiredArgsConstructor
public class WxLoginController {
private static final RestTemplate REST_TEMPLATE = new RestTemplate();
@Autowired
private SysUserService sysUserService;
/**
* AppID:wx292995002b9476f3
* AppSecret:896202811f43b146123f8d3f9ad3c153
*/
/**
* 微信小程序AppID
*/
private final static String AppID = "wxbad2e8a91c62a734";
/**
* 微信小程序AppSecret
*/
private final static String AppSecret = "e1b7fc425ca9cca05dd83609a6dc9c00";
@Operation(summary = "微信登录")
@GetMapping("/wxlogin")
public R getWechatLoginInfo(@RequestParam String code) {
String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=wxbad2e8a91c62a734&secret=e1b7fc425ca9cca05dd83609a6dc9c00&code=" + code + "&grant_type=authorization_code";
String H5 = HttpTool.get(url, String.class);
Gson gson = new Gson();
H5LoginResponse h5LoginResponse = gson.fromJson(H5, H5LoginResponse.class);
System.out.println("h5LoginResponse = " + h5LoginResponse);
String useUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=" + h5LoginResponse.getAccessToken() + "&openid=" + h5LoginResponse.getOpenId() + "&lang=zh_CN";
String user = HttpTool.get(useUrl, String.class);
System.out.println("user = " + user);
UserResponse userResponse = gson.fromJson(user, UserResponse.class);
String opeId = userResponse.getOpenId();
SysUser sysUser = sysUserService.getByOpenId(opeId);
if(sysUser == null){
sysUser = new SysUser();
sysUser.setUsername(userResponse.getNicName());
sysUser.setOpenId(userResponse.getOpenId());
sysUser.setUnionId(userResponse.getOpenId());
sysUser.setPassword("123456");
sysUserService.save(sysUser);
}
JSH5LoginResponse jsh5LoginResponse = new JSH5LoginResponse();
BeanUtils.copyProperties(h5LoginResponse, jsh5LoginResponse);
jsh5LoginResponse.setUser(user);
return R.OK(jsh5LoginResponse);
}
@Operation(summary = "获取签名")
@GetMapping("/access")
public R access(String url){
Gson gson = new Gson();
Map<String,Object> map = new HashMap<>();
map.put("appid","wxbad2e8a91c62a734");
map.put("secret", "e1b7fc425ca9cca05dd83609a6dc9c00");
map.put("grant_type","client_credential");
String tokenUrl = "https://api.weixin.qq.com/cgi-bin/stable_token";
String access = REST_TEMPLATE.postForObject(tokenUrl, map, String.class);
// String access = HttpTool.pos(tokenUrl, map, String.class);
System.out.println("access = " + access);
AccessTokenResponse accessTokenResponse = gson.fromJson(access, AccessTokenResponse.class);
String jsUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+accessTokenResponse.getAccessToken()+"&type=jsapi";
String js = HttpTool.get(jsUrl, String.class);
JsResponse jsResponse = gson.fromJson(js, JsResponse.class);
System.out.println(js);
SignatureResponse signatureResponse = new SignatureResponse();
// 替换成你的公众号AppID和AppSecret
String appId = "wxbad2e8a91c62a734";
String appSecret = "e1b7fc425ca9cca05dd83609a6dc9c00";
String nonceStr = createNonceStr();
String timestamp = createTimestamp();
String jsapiTicket = jsResponse.getTicket();
String signature = generateSignature(jsapiTicket, nonceStr, timestamp, url);
signatureResponse.setSignature(signature);
signatureResponse.setTimestamp(timestamp);
signatureResponse.setJsapiTicket(jsapiTicket);
signatureResponse.setNonceStr(nonceStr);
System.out.println("signature = " + signature);
System.out.println(url);
return R.OK(signatureResponse);
}
private static String createNonceStr() {
return UUID.randomUUID().toString().replaceAll("-", "");
}
private static String createTimestamp() {
return Long.toString(System.currentTimeMillis() / 1000);
}
private static String getJsApiTicket(String appId, String appSecret) {
// 调用微信API获取jsapi_ticket的逻辑,这里省略实现
// 返回有效的jsapi_ticket
return "YOUR_JSAPI_TICKET";
}
private static String generateSignature(String jsapiTicket, String nonceStr, String timestamp, String url) {
String sb = "jsapi_ticket=" + jsapiTicket + "&noncestr=" + nonceStr + "&timestamp=" + timestamp + "&url=" + url;
try {
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(sb.toString().getBytes("UTF-8"));
byte[] digest = crypt.digest();
Formatter formatter = new Formatter();
for (byte b : digest) {
formatter.format("%02x", b);
}
String signature = formatter.toString();
formatter.close();
return signature;
} catch (NoSuchAlgorithmException | java.io.UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
}
public static void main(String[] args) {
String json = "{\"openid\":\"o2r-U6sN-BMZEQlzEZIuVbRzeqPk\",\"nickname\":\"王文龙\",\"sex\":0,\"language\":\"\",\"city\":\"\",\"province\":\"\",\"country\":\"\",\"headimgurl\":\"https:\\/\\/thirdwx.qlogo.cn\\/mmopen\\/vi_32\\/PiajxSqBRaEJyptEMOSZmJ1480uG0gH5SpgxxXYtqIf6XKUn0fm9X6lxkT8aMRpX0sVBkTia5C9KtqsD70w8Q6VA\\/132\",\"privilege\":[]}";
Gson gson = new Gson();
UserResponse user = gson.fromJson(json, UserResponse.class);
System.out.println(user.getNicName());
System.out.println(user.getPrivilege());
}
}

View File

@ -0,0 +1,43 @@
package com.hb0730.boot.admin.modules.sys.auth.event;
import org.springframework.context.ApplicationEvent;
/**
* logout event
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/2/5
*/
public class LogoutEvent extends ApplicationEvent {
/**
* 访问token
*/
private final String token;
/**
* 用户名
*/
private final String username;
/**
* 用户ID
*/
private final String userid;
public LogoutEvent(Object source, String token, String username, String userid) {
super(source);
this.token = token;
this.username = username;
this.userid = userid;
}
public String getToken() {
return token;
}
public String getUsername() {
return username;
}
public String getUserid() {
return userid;
}
}

View File

@ -0,0 +1,32 @@
package com.hb0730.boot.admin.modules.sys.auth.event;
import com.hb0730.boot.admin.modules.sys.system.cache.RouteCache;
import com.hb0730.boot.admin.security.token.UserCacheProvider;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
/**
* 登出事件
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/2/5
*/
@Component
@RequiredArgsConstructor
@Slf4j
public class LogoutListener implements ApplicationListener<LogoutEvent> {
private final UserCacheProvider userCacheProvider;
private final RouteCache routeCache;
@Override
public void onApplicationEvent(LogoutEvent event) {
log.info("【用户注销事件】用户注销清理缓存信息>>>>>>>>>>>开始");
String username = event.getUsername();
userCacheProvider.clearUser(username);
log.info("【用户注销事件】成功清理缓存登录用户信息");
routeCache.removeCache(event.getUserid());
log.info("【用户注销事件】成功清理缓存用户路由信息");
}
}

View File

@ -0,0 +1,33 @@
package com.hb0730.boot.admin.modules.sys.auth.model;
import com.google.gson.annotations.SerializedName;
public class AccessTokenResponse {
@SerializedName("access_token")
private String accessToken;
@SerializedName("expires_in")
private Long expires_in;
public AccessTokenResponse() {
}
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public Long getExpires_in() {
return expires_in;
}
public void setExpires_in(Long expires_in) {
this.expires_in = expires_in;
}
}

View File

@ -0,0 +1,99 @@
package com.hb0730.boot.admin.modules.sys.auth.model;
import com.google.gson.annotations.SerializedName;
public class H5LoginResponse {
@SerializedName("access_token")
private String accessToken;
@SerializedName("refresh_token")
private String refreshToken;
@SerializedName("expiresIn")
private Long expires_in;
@SerializedName("unionid")
private String unionId;
@SerializedName("is_snapshotuser")
private Integer isSnapshotUser;
@SerializedName("openid")
private String openId;
@SerializedName("scope")
private String scope;
@SerializedName("errcode")
private Long errCode = 0L;
@SerializedName("errmsg")
private String errMsg;
public H5LoginResponse() {
}
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public String getRefreshToken() {
return refreshToken;
}
public void setRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
}
public Long getExpires_in() {
return expires_in;
}
public void setExpires_in(Long expires_in) {
this.expires_in = expires_in;
}
public String getUnionId() {
return unionId;
}
public void setUnionId(String unionId) {
this.unionId = unionId;
}
public Integer getIsSnapshotUser() {
return isSnapshotUser;
}
public void setIsSnapshotUser(Integer isSnapshotUser) {
this.isSnapshotUser = isSnapshotUser;
}
public String getOpenId() {
return openId;
}
public void setOpenId(String openId) {
this.openId = openId;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
public Long getErrCode() {
return errCode;
}
public void setErrCode(Long errCode) {
this.errCode = errCode;
}
public String getErrMsg() {
return errMsg;
}
public void setErrMsg(String errMsg) {
this.errMsg = errMsg;
}
}

View File

@ -0,0 +1,121 @@
package com.hb0730.boot.admin.modules.sys.auth.model;
import com.google.gson.annotations.SerializedName;
public class JSH5LoginResponse {
@SerializedName("access_token")
private String accessToken;
@SerializedName("refresh_token")
private String refreshToken;
@SerializedName("expiresIn")
private Long expires_in;
@SerializedName("unionid")
private String unionId;
@SerializedName("is_snapshotuser")
private Integer isSnapshotUser;
@SerializedName("openid")
private String openId;
@SerializedName("scope")
private String scope;
@SerializedName("errcode")
private Long errCode = 0L;
@SerializedName("errmsg")
private String errMsg;
@SerializedName("ticket")
private String ticket;
private String user;
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getTicket() {
return ticket;
}
public void setTicket(String ticket) {
this.ticket = ticket;
}
public JSH5LoginResponse() {
}
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public String getRefreshToken() {
return refreshToken;
}
public void setRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
}
public Long getExpires_in() {
return expires_in;
}
public void setExpires_in(Long expires_in) {
this.expires_in = expires_in;
}
public String getUnionId() {
return unionId;
}
public void setUnionId(String unionId) {
this.unionId = unionId;
}
public Integer getIsSnapshotUser() {
return isSnapshotUser;
}
public void setIsSnapshotUser(Integer isSnapshotUser) {
this.isSnapshotUser = isSnapshotUser;
}
public String getOpenId() {
return openId;
}
public void setOpenId(String openId) {
this.openId = openId;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
public Long getErrCode() {
return errCode;
}
public void setErrCode(Long errCode) {
this.errCode = errCode;
}
public String getErrMsg() {
return errMsg;
}
public void setErrMsg(String errMsg) {
this.errMsg = errMsg;
}
}

View File

@ -0,0 +1,49 @@
package com.hb0730.boot.admin.modules.sys.auth.model;
import com.google.gson.annotations.SerializedName;
public class JsResponse {
@SerializedName("ticket")
private String ticket;
@SerializedName("expiresIn")
private Long expires_in;
@SerializedName("errcode")
private Long errCode = 0L;
@SerializedName("errmsg")
private String errMsg;
public String getTicket() {
return ticket;
}
public void setTicket(String ticket) {
this.ticket = ticket;
}
public Long getExpires_in() {
return expires_in;
}
public void setExpires_in(Long expires_in) {
this.expires_in = expires_in;
}
public Long getErrCode() {
return errCode;
}
public void setErrCode(Long errCode) {
this.errCode = errCode;
}
public String getErrMsg() {
return errMsg;
}
public void setErrMsg(String errMsg) {
this.errMsg = errMsg;
}
}

View File

@ -0,0 +1,27 @@
package com.hb0730.boot.admin.modules.sys.auth.model;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.io.Serializable;
/**
* login request body
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/1/30
*/
@Data
@EqualsAndHashCode
@ToString
public class LoginRequest implements Serializable {
@Schema(description = "用户名", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "用户名为空")
private String username;
@Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "密码为空")
private String password;
}

View File

@ -0,0 +1,27 @@
package com.hb0730.boot.admin.modules.sys.auth.model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.io.Serializable;
import java.util.List;
/**
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/2/5
*/
@Data
@EqualsAndHashCode
@ToString
public class LoginResponse implements Serializable {
@Schema(description = "用户名")
private String username;
@Schema(description = "用户昵称")
private String nickname;
@Schema(description = "权限")
private List<String> permissions;
@Schema(description = "访问token")
private String token;
}

View File

@ -0,0 +1,15 @@
package com.hb0730.boot.admin.modules.sys.auth.model;
import lombok.Data;
@Data
public class SignatureResponse {
private String signature;
private String timestamp;
private String nonceStr;
private String jsapiTicket;
}

View File

@ -0,0 +1,105 @@
package com.hb0730.boot.admin.modules.sys.auth.model;
import com.google.gson.annotations.SerializedName;
import java.util.List;
public class UserResponse {
@SerializedName("openid")
private String openId;
@SerializedName("unionid")
private String unionId;
@SerializedName("nickname")
private String nicName;
@SerializedName("sex")
private String sex;
@SerializedName("province")
private String province;
@SerializedName("city")
private String city;
@SerializedName("headimgurl")
private String headImgurl;
@SerializedName("privilege")
private List<String> privilege;
@SerializedName("country")
private String country;
public List<String> getPrivilege() {
return privilege;
}
public void setPrivilege(List<String> privilege) {
this.privilege = privilege;
}
public UserResponse() {
}
public String getOpenId() {
return openId;
}
public void setOpenId(String openId) {
this.openId = openId;
}
public String getUnionId() {
return unionId;
}
public void setUnionId(String unionId) {
this.unionId = unionId;
}
public String getNicName() {
return nicName;
}
public void setNicName(String nicName) {
this.nicName = nicName;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getHeadImgurl() {
return headImgurl;
}
public void setHeadImgurl(String headImgurl) {
this.headImgurl = headImgurl;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
}

View File

@ -0,0 +1,14 @@
package com.hb0730.boot.admin.modules.sys.auth.model.dto;
import lombok.Data;
@Data
public class LoginDto {
private String code;
/**
* 扩展字段
*/
public Object extendParam;
}

View File

@ -0,0 +1,92 @@
package com.hb0730.boot.admin.modules.sys.monitor.controller;
import com.hb0730.boot.admin.base.R;
import com.hb0730.boot.admin.base.util.JsonUtil;
import com.hb0730.boot.admin.config.cache.BootAdminCache;
import com.hb0730.boot.admin.config.cache.DefaultKeyValue;
import com.hb0730.boot.admin.modules.sys.monitor.model.vo.CacheVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
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;
import java.util.Arrays;
import java.util.List;
/**
* 系统缓存
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/6/14
*/
@RestController
@RequestMapping("/monitor/cache")
@Tag(name = "系统:系统缓存", description = "业务缓存与系统缓存")
@RequiredArgsConstructor
public class CacheController {
private final BootAdminCache bootAdminCache;
@GetMapping
@Operation(summary = "缓存列表")
@PreAuthorize("hasAuthority('cache:list')")
public R<List<CacheVO>> queryList(HttpServletRequest request) {
List<CacheVO> res = Arrays.stream(DefaultKeyValue.values()).map(e -> {
CacheVO cacheVo = new CacheVO();
cacheVo.setPrefix(e.getPrefix());
cacheVo.setName(e.getName());
cacheVo.setDesc(e.getDesc());
return cacheVo;
}).toList();
return R.OK(res);
}
@GetMapping("/query")
@Operation(summary = "查询缓存")
@PreAuthorize("hasAuthority('cache:query')")
public R<CacheVO> query(HttpServletRequest request, CacheVO vo) {
// 完整缓存:KEY值
String cacheKey = (vo.getPrefix() == null ? "" : vo.getPrefix() + ":") + vo.getKey();
boolean exist = bootAdminCache.hasKey(cacheKey);
if (!exist) {
return R.NG(String.format("缓存KEY:[%s]不存在", cacheKey));
}
// 缓存方式: 默认使用String方式
String cacheType = StringUtils.isNotBlank(vo.getType()) ? vo.getType() : "String";
switch (DefaultKeyValue.CacheType.valueOf(cacheType.toUpperCase())) {
case STRING, OBJECT ->
// <1> String 缓存
vo.setValue(bootAdminCache.getStr(cacheKey).orElse(""));
case HASHMAP ->
// <3> Map 缓存
bootAdminCache.hmget(cacheKey).ifPresent(e -> vo.setValue(JsonUtil.DEFAULT.toJson(e)));
case SET ->
// <4> Set 缓存
bootAdminCache.sGet(cacheKey).ifPresent(e -> vo.setValue(JsonUtil.DEFAULT.toJson(e)));
case LIST ->
// <5> List 缓存
bootAdminCache.lGet(cacheKey, 0, -1).ifPresent(e -> vo.setValue(JsonUtil.DEFAULT.toJson(e)));
default -> {
}
}
return R.OK(vo);
}
@DeleteMapping("/remove")
@Operation(summary = "删除缓存")
@PreAuthorize("hasAuthority('cache:remove')")
public R<String> remove(HttpServletRequest request, @RequestBody @Valid CacheVO vo) {
String cacheKey = (vo.getPrefix() == null ? "" : vo.getPrefix() + ":") + vo.getKey();
if (bootAdminCache.hasKey(cacheKey)) {
bootAdminCache.del(cacheKey);
}
return R.OK("");
}
}

View File

@ -0,0 +1,180 @@
package com.hb0730.boot.admin.modules.sys.monitor.controller;
import cn.hutool.core.bean.BeanUtil;
import com.hb0730.boot.admin.base.R;
import com.hb0730.boot.admin.data.domain.BasePage;
import com.hb0730.boot.admin.modules.sys.monitor.model.vo.QuartzJobVO;
import com.hb0730.boot.admin.modules.sys.monitor.model.entity.QuartzJob;
import com.hb0730.boot.admin.modules.sys.monitor.model.query.QuartzJobQuery;
import com.hb0730.boot.admin.modules.sys.monitor.service.QuartzJobService;
import com.hb0730.boot.admin.security.util.SecurityUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.quartz.CronExpression;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
import java.util.List;
/**
* Quartz定时任务Controller
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/6/12
*/
@RestController
@RequestMapping("/monitor/quartz/job")
@Tag(name = "定时任务")
@RequiredArgsConstructor
@Slf4j
public class QuartzJobController {
private final QuartzJobService quartzJobService;
/**
* 表达式是否正确
*
* @param request .
* @param cron .
* @return .
*/
@GetMapping("/check/cron")
@Operation(summary = "表达式是否正确")
public R<Boolean> checkCron(HttpServletRequest request, String cron) {
boolean success = CronExpression.isValidExpression(cron);
return success ? R.OK() : R.NG(200,"表达式错误");
}
@GetMapping("/query/page")
@Operation(summary = "分页查询")
@PreAuthorize("hasAuthority('sys:quartz:job:query')")
public R<BasePage<QuartzJobVO>> queryPage(HttpServletRequest request, @ParameterObject QuartzJobQuery query) {
return R.OK(quartzJobService.queryPage(query));
}
@GetMapping("/query/list")
@Operation(summary = "列表查询")
public R<List<QuartzJobVO>> queryList(HttpServletRequest request, @ParameterObject QuartzJobQuery query) {
return R.OK(quartzJobService.queryList(query));
}
@PostMapping("/save")
@Operation(summary = "保存")
@PreAuthorize("hasAuthority('sys:quartz:job:save')")
public R<QuartzJobVO> save(HttpServletRequest request, @RequestBody QuartzJobVO vo) {
String cronExpression = vo.getCronExpression();
boolean success = CronExpression.isValidExpression(cronExpression);
if (!success) {
return R.NG("表达式错误");
}
String username = SecurityUtil.getCurrentUsername();
QuartzJob quartzJob = BeanUtil.toBean(vo, QuartzJob.class);
quartzJob.setCreated(LocalDateTime.now());
quartzJob.setCreatedBy(username);
quartzJobService.saveAndScheduleJob(quartzJob);
vo = BeanUtil.toBean(quartzJob, QuartzJobVO.class);
return R.OK(vo);
}
@PutMapping("/update/{id}")
@Operation(summary = "更新")
@PreAuthorize("hasAuthority('sys:quartz:job:update')")
public R<QuartzJobVO> updateById(HttpServletRequest request, @PathVariable String id, @RequestBody QuartzJobVO vo) {
try {
QuartzJob job = quartzJobService.getById(id);
if (null == job) {
return R.NG("任务不存在");
}
String cronExpression = vo.getCronExpression();
boolean success = CronExpression.isValidExpression(cronExpression);
if (!success) {
return R.NG("表达式错误");
}
String username = SecurityUtil.getCurrentUsername();
QuartzJob quartzJob = BeanUtil.toBean(vo, QuartzJob.class);
quartzJob.setModified(LocalDateTime.now());
quartzJob.setModifiedBy(username);
quartzJobService.editAndScheduleJob(quartzJob);
vo = BeanUtil.toBean(quartzJob, QuartzJobVO.class);
return R.OK(vo);
} catch (Exception e) {
log.warn("更新定时任务失败", e);
return R.NG("更新定时任务失败");
}
}
@PutMapping("/pause/{id}")
@PreAuthorize("hasAuthority('sys:quartz:job:pause')")
@Operation(summary = "暂停")
public R<String> pause(HttpServletRequest request, @PathVariable String id) {
QuartzJob quartzJob = quartzJobService.getById(id);
if (null == quartzJob) {
return R.NG("任务不存在");
}
try {
quartzJobService.pauseJob(quartzJob);
return R.OK();
} catch (Exception e) {
log.warn("暂停定时任务失败", e);
return R.NG("暂停定时任务失败");
}
}
@PutMapping("/resume/{id}")
@PreAuthorize("hasAuthority('sys:quartz:job:resume')")
@Operation(summary = "恢复")
public R<String> resume(HttpServletRequest request, @PathVariable String id) {
QuartzJob quartzJob = quartzJobService.getById(id);
if (null == quartzJob) {
return R.NG("任务不存在");
}
try {
quartzJobService.resumeJob(quartzJob);
return R.OK();
} catch (Exception e) {
log.warn("恢复定时任务失败", e);
return R.NG("恢复定时任务失败");
}
}
@PutMapping("/execute/{id}")
@PreAuthorize("hasAuthority('sys:quartz:job:execute')")
@Operation(summary = "执行")
public R<String> execute(HttpServletRequest request, @PathVariable String id) {
QuartzJob quartzJob = quartzJobService.getById(id);
if (null == quartzJob) {
return R.NG("任务不存在");
}
try {
quartzJobService.executeJob(quartzJob);
return R.OK();
} catch (Exception e) {
log.warn("执行定时任务失败", e);
return R.NG("执行定时任务失败");
}
}
@DeleteMapping("/delete")
@Operation(summary = "删除")
@PreAuthorize("hasAuthority('sys:quartz:job:delete')")
public R<String> delete(HttpServletRequest request, @RequestParam String id) {
QuartzJob quartzJob = quartzJobService.getById(id);
if (null == quartzJob) {
return R.NG("任务不存在");
}
quartzJobService.deleteAndStopJob(quartzJob);
return R.OK();
}
}

View File

@ -0,0 +1,38 @@
package com.hb0730.boot.admin.modules.sys.monitor.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hb0730.boot.admin.modules.sys.monitor.model.entity.QuartzJob;
import com.hb0730.boot.admin.modules.sys.monitor.model.vo.QuartzJobVO;
import com.hb0730.boot.admin.modules.sys.monitor.model.query.QuartzJobQuery;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* 定时任务在线管理 MAPPER
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/6/12
*/
public interface QuartzJobMapper extends BaseMapper<QuartzJob> {
/**
* 根据任务实现类全名取得匹配的任务
*
* @param jobClassName 任务实现类全名
* @return 匹配的任务
*/
@Select("select * from sys_quartz_job where job_class_name = #{jobClassName}")
List<QuartzJob> findByJobClassName(@Param("jobClassName") String jobClassName);
/**
* 分页查询
*
* @param page .
* @param query .
* @return .
*/
List<QuartzJobVO> queryPage(Page<QuartzJobVO> page, @Param("query") QuartzJobQuery query);
}

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hb0730.boot.admin.modules.sys.monitor.mapper.QuartzJobMapper">
<select id="queryPage" resultType="com.hb0730.boot.admin.modules.sys.monitor.model.vo.QuartzJobVO">
SELECT *
FROM `sys_quartz_job`
WHERE 1 = 1
<if test="query.jobClassName != null and query.jobClassName != '' ">
and job_class_name = #{query.jobClassName}
</if>
<if test="query.status != null ">
and status = #{query.status}
</if>
ORDER BY created DESC
</select>
</mapper>

View File

@ -0,0 +1,41 @@
package com.hb0730.boot.admin.modules.sys.monitor.model.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.hb0730.boot.admin.data.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/**
* 定时任务在线管理表
*
* @author <a href="mailto:huangbing0730@gmail">hb0730</a>
* @date 2023/6/12
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ToString
@TableName("sys_quartz_job")
public class QuartzJob extends BaseEntity {
/**
* 任务类名
*/
private java.lang.String jobClassName;
/**
* 参数
*/
private java.lang.String parameter;
/**
* cron表达式
*/
private java.lang.String cronExpression;
/**
* 状态 1正常 0停止
*/
private java.lang.Integer status;
/**
* 描述
*/
private java.lang.String description;
}

Some files were not shown because too many files have changed in this diff Show More