commit c1c49429ce1e22757190bd5c19cded888ec3ec56
Author: XinanXf <959700191@qq.com>
Date: Wed Jun 11 11:15:51 2025 +0800
青石-办公小程序后台初始化代码
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..8249d68
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,46 @@
+<<<<<<< HEAD
+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
+=======
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+>>>>>>> firstcommit
diff --git a/.mvn/wrapper/MavenWrapperDownloader.java b/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 0000000..e76d1f3
--- /dev/null
+++ b/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2007-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import java.net.*;
+import java.io.*;
+import java.nio.channels.*;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ private static final String WRAPPER_VERSION = "0.5.6";
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
+ String username = System.getenv("MVNW_USERNAME");
+ char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
+ Authenticator.setDefault(new Authenticator() {
+ @Override
+ protected PasswordAuthentication getPasswordAuthentication() {
+ return new PasswordAuthentication(username, password);
+ }
+ });
+ }
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..2cc7d4a
Binary files /dev/null and b/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..642d572
--- /dev/null
+++ b/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..e69de29
diff --git a/doc/trans_new_漫画翻译数据库文档_1.0.html b/doc/trans_new_漫画翻译数据库文档_1.0.html
new file mode 100644
index 0000000..3e17594
--- /dev/null
+++ b/doc/trans_new_漫画翻译数据库文档_1.0.html
@@ -0,0 +1 @@
+
fire数据库文档fire数据库文档
数据库名:trans_new
文档版本:1.0
文档描述:漫画翻译数据库文档
说明:
数据列:
序号 | 名称 | 数据类型 | 长度 | 小数位 | 允许空值 | 主键 | 默认值 | 说明 |
1 | id | int unsigned | 10 | 0 | N | Y | | id |
2 | font_name | varchar | 20 | 0 | N | N | | 字体名称 |
说明:
数据列:
序号 | 名称 | 数据类型 | 长度 | 小数位 | 允许空值 | 主键 | 默认值 | 说明 |
1 | id | int unsigned | 10 | 0 | N | Y | | id |
2 | language_name | varchar | 30 | 0 | N | N | | 语言名称 |
3 | language_code | varchar | 10 | 0 | N | N | | 语言代码 |
4 | split_type | int | 10 | 0 | N | N | | 分割字数方式 1中文 2英文 |
说明:权限表
数据列:
序号 | 名称 | 数据类型 | 长度 | 小数位 | 允许空值 | 主键 | 默认值 | 说明 |
1 | id | int unsigned | 10 | 0 | N | Y | | |
2 | parent_id | int | 10 | 0 | N | N | | 父级id |
3 | name | varchar | 50 | 0 | N | N | | 名称 |
4 | url | varchar | 200 | 0 | Y | N | | 地址 |
5 | sort | int | 10 | 0 | N | N | 1 | 排序 |
说明:角色表
数据列:
序号 | 名称 | 数据类型 | 长度 | 小数位 | 允许空值 | 主键 | 默认值 | 说明 |
1 | id | int unsigned | 10 | 0 | N | Y | | |
2 | name | varchar | 50 | 0 | N | N | | 名称 |
3 | level | int | 10 | 0 | N | N | 10 | 级别 |
说明:角色权限字典表
数据列:
序号 | 名称 | 数据类型 | 长度 | 小数位 | 允许空值 | 主键 | 默认值 | 说明 |
1 | id | int unsigned | 10 | 0 | N | Y | | |
2 | role_id | int | 10 | 0 | N | N | | 角色id |
3 | permission_id | int | 10 | 0 | N | N | | 权限id |
说明:
数据列:
序号 | 名称 | 数据类型 | 长度 | 小数位 | 允许空值 | 主键 | 默认值 | 说明 |
1 | id | int unsigned | 10 | 0 | N | Y | | id |
2 | user_id | int | 10 | 0 | N | N | | 用户id |
3 | work_name | varchar | 50 | 0 | N | N | | 工程名 |
4 | worker_label | varchar | 50 | 0 | Y | N | | 工程标签 |
5 | worker_cover_url | varchar | 200 | 0 | Y | N | | 工程封面 |
6 | dir_id | int | 10 | 0 | N | N | | 父文件夹id |
7 | width | int | 10 | 0 | N | N | | 宽度 |
8 | height | int | 10 | 0 | N | N | | 高度 |
9 | from_language_id | int | 10 | 0 | N | N | | 原语言id |
10 | to_language_id | int | 10 | 0 | N | N | | 翻译目标语言id |
11 | font_id | int | 10 | 0 | N | N | | 默认字体 |
12 | image_count | int | 10 | 0 | N | N | 0 | 工程图片数 |
13 | auto_clear_word | int | 10 | 0 | N | N | 0 | 是否自动清除文字 |
14 | auto_ocr | int | 10 | 0 | N | N | 0 | 是否自动识别文字 |
15 | auto_translate | int | 10 | 0 | N | N | 0 | 是否自动翻译 |
16 | word_count | int | 10 | 0 | N | N | 0 | 工程源语言字数 |
17 | worker_size | int | 10 | 0 | N | N | 0 | 工程占空间大小 |
18 | worker_status | int | 10 | 0 | N | N | 1 | 工程状态 |
19 | create_time | datetime | 19 | 0 | N | N | | 创建时间 |
20 | update_time | timestamp | 19 | 0 | N | N | CURRENT_TIMESTAMP | 更新时间 |
说明:用户表
数据列:
序号 | 名称 | 数据类型 | 长度 | 小数位 | 允许空值 | 主键 | 默认值 | 说明 |
1 | id | int unsigned | 10 | 0 | N | Y | | |
2 | user_name | varchar | 50 | 0 | N | N | | 账号 |
3 | password | varchar | 200 | 0 | N | N | | 密码 |
4 | nick | varchar | 50 | 0 | N | N | | 用户名 |
5 | role_id | int | 10 | 0 | N | N | | 角色id |
6 | user_status | int | 10 | 0 | N | N | 1 | 0不可用 1可用 |
7 | create_time | timestamp | 19 | 0 | N | N | CURRENT_TIMESTAMP | 创建时间 |
说明:
数据列:
序号 | 名称 | 数据类型 | 长度 | 小数位 | 允许空值 | 主键 | 默认值 | 说明 |
1 | id | int unsigned | 10 | 0 | N | Y | | id |
2 | worker_id | int | 10 | 0 | N | N | | 工程id |
3 | worker_image_id | int | 10 | 0 | N | N | | 工程图片id |
4 | ocr_content | text | 65535 | 0 | N | N | | OCR识别出的文字 |
5 | trans_content | text | 65535 | 0 | N | N | | 翻译出的文字 |
6 | content_status | int | 10 | 0 | N | N | 0 | 翻译状态 0:未翻译 1:已翻译 |
7 | left_x | int | 10 | 0 | N | N | | 左边界定位 |
8 | right_x | int | 10 | 0 | N | N | | 右边界定位 |
9 | up_y | int | 10 | 0 | N | N | | 上边界定位 |
10 | down_y | int | 10 | 0 | N | N | | 下边界定位 |
11 | font_size | int | 10 | 0 | N | N | | 字体大小 |
12 | font_id | int | 10 | 0 | N | N | | 文字字体id |
13 | content_color | varchar | 10 | 0 | N | N | | 文本颜色 例:#FFFFFF |
14 | content_word_count | int | 10 | 0 | N | N | | 文本长度 |
15 | trans_img_path | varchar | 200 | 0 | Y | N | | 翻译保存的图片路劲 |
16 | is_hide | int | 10 | 0 | N | N | 0 | 是否隐藏翻译后图片 0:隐藏 1:显示 |
17 | create_time | datetime | 19 | 0 | N | N | | 创建时间 |
说明:
数据列:
序号 | 名称 | 数据类型 | 长度 | 小数位 | 允许空值 | 主键 | 默认值 | 说明 |
1 | id | int unsigned | 10 | 0 | N | Y | | id |
2 | parent_id | int | 10 | 0 | N | N | 0 | 父级id |
3 | user_id | int | 10 | 0 | N | N | | 用户id |
4 | dir_name | varchar | 30 | 0 | N | N | | 文件夹名称 |
5 | dir_size | int | 10 | 0 | N | N | 0 | 文件大小 |
6 | dir_sub_total | int | 10 | 0 | N | N | 0 | 子文件数量 |
7 | worker_sub_total | int | 10 | 0 | N | N | 0 | 子工程数量 |
8 | dir_status | int | 10 | 0 | N | N | 1 | 文件状态 |
9 | create_time | datetime | 19 | 0 | N | N | | 创建时间 |
10 | update_time | timestamp | 19 | 0 | N | N | CURRENT_TIMESTAMP | 更新时间 |
说明:
数据列:
序号 | 名称 | 数据类型 | 长度 | 小数位 | 允许空值 | 主键 | 默认值 | 说明 |
1 | id | int unsigned | 10 | 0 | N | Y | | id |
2 | worker_id | int | 10 | 0 | N | N | | 工程id |
3 | file_path | varchar | 200 | 0 | N | N | | 图片存储路径 |
4 | file_num | int | 10 | 0 | N | N | | 图片编号 |
5 | width | int | 10 | 0 | N | N | | 图片宽度 |
6 | height | int | 10 | 0 | N | N | | 图片高度 |
7 | image_word_count | int | 10 | 0 | N | N | 0 | 源语言字数 |
8 | image_status | int | 10 | 0 | N | N | 0 | 图片状态 0:没有OCR 1:已OCR |
9 | create_time | datetime | 19 | 0 | N | N | | 创建时间 |
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..602faee
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,275 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.3.2.RELEASE
+
+
+ com.soft
+ soft
+ 1.0
+ soft
+ Demo project for Spring Boot
+
+
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-aop
+
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+
+ org.springframework
+ spring-expression
+
+
+
+ org.apache.poi
+ poi
+ 5.2.3
+
+
+ org.apache.poi
+ poi-ooxml
+ 5.2.3
+
+
+ org.apache.poi
+ poi-ooxml-schemas
+ 4.1.2
+
+
+ org.apache.xmlbeans
+ xmlbeans
+ 5.0.2
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.junit.vintage
+ junit-vintage-engine
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+ 2.2.4.RELEASE
+
+
+
+ com.baomidou
+ mybatis-plus-boot-starter
+ 3.4.3.4
+
+
+ com.alibaba
+ druid-spring-boot-starter
+ 1.1.10
+
+
+ com.baomidou
+ mybatis-plus-extension
+ 3.5.1
+
+
+
+ org.jsoup
+ jsoup
+ 1.14.3
+
+
+
+ mysql
+ mysql-connector-java
+ runtime
+
+
+ com.github.pagehelper
+ pagehelper-spring-boot-starter
+ 1.3.1
+
+
+
+
+ com.janeluo
+ ikanalyzer
+ 2012_u6
+
+
+ com.huaban
+ jieba-analysis
+ 1.0.2
+
+
+
+ org.bouncycastle
+ bcprov-jdk15on
+ 1.60
+
+
+
+ com.baidubce
+ bce-java-sdk
+ 0.10.154
+
+
+ com.google.guava
+ guava
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-thymeleaf
+
+
+
+ cn.hutool
+ hutool-all
+ 5.2.5
+
+
+ com.alibaba
+ fastjson
+ 1.2.58
+
+
+
+
+ org.projectlombok
+ lombok
+ 1.18.6
+
+
+
+ net.sf.json-lib
+ json-lib-ext-spring
+ 1.0.2
+
+
+
+
+ io.springfox
+ springfox-swagger2
+ 2.9.2
+
+
+
+
+
+ com.github.xiaoymin
+ knife4j-spring-boot-starter
+
+ 2.0.9
+
+
+ io.springfox
+ springfox-swagger-ui
+ 2.9.2
+
+
+ org.pegdown
+ pegdown
+ 1.4.2
+
+
+
+ commons-codec
+ commons-codec
+ 1.13
+
+
+ org.apache.commons
+ commons-lang3
+ 3.9
+
+
+ commons-io
+ commons-io
+ 2.11.0
+
+
+ org.apache.httpcomponents
+ httpclient
+ 4.5.9
+
+
+ org.apache.commons
+ commons-collections4
+ 4.4
+
+
+ junit
+ junit
+ 4.12-beta-3
+
+
+ com.github.wechatpay-apiv3
+ wechatpay-apache-httpclient
+ 0.4.7
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+
+
+
diff --git a/src/main/java/com/soft/SoftApplication.java b/src/main/java/com/soft/SoftApplication.java
new file mode 100644
index 0000000..77dc6fa
--- /dev/null
+++ b/src/main/java/com/soft/SoftApplication.java
@@ -0,0 +1,23 @@
+package com.soft;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+
+@SpringBootApplication
+@EnableAspectJAutoProxy
+@EnableScheduling
+public class SoftApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(SoftApplication.class, args);
+// RedisTemplate redisTemplate= SpringBeanUtil.getBean(RedisTemplate.class);
+// redisTemplate.opsForValue().set("user1", new User1(2,"lumia"));
+// System.out.println(redisTemplate.opsForValue().getOperations().getExpire("user1"));
+// Object name = redisTemplate.opsForValue().get("shopping_car1");
+// System.out.println(name);
+
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/soft/annotations/HasPermission.java b/src/main/java/com/soft/annotations/HasPermission.java
new file mode 100644
index 0000000..4cb3af1
--- /dev/null
+++ b/src/main/java/com/soft/annotations/HasPermission.java
@@ -0,0 +1,23 @@
+package com.soft.annotations;
+
+import com.soft.components.security.PermissionCalcType;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target({ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface HasPermission {
+ String[] value();
+
+ PermissionCalcType calcType() default PermissionCalcType.OR;
+
+ /**
+ * 用户ID的 SpEL 表达式(例如:#userId 或 #user.id)
+ */
+ String userId() default "";
+}
diff --git a/src/main/java/com/soft/annotations/NotNull.java b/src/main/java/com/soft/annotations/NotNull.java
new file mode 100644
index 0000000..ca9ef56
--- /dev/null
+++ b/src/main/java/com/soft/annotations/NotNull.java
@@ -0,0 +1,13 @@
+package com.soft.annotations;
+
+
+import java.lang.annotation.*;
+
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface NotNull {
+
+ String message() default "";
+
+}
diff --git a/src/main/java/com/soft/annotations/Valid.java b/src/main/java/com/soft/annotations/Valid.java
new file mode 100644
index 0000000..a280b96
--- /dev/null
+++ b/src/main/java/com/soft/annotations/Valid.java
@@ -0,0 +1,10 @@
+package com.soft.annotations;
+
+import java.lang.annotation.*;
+
+@Target(ElementType.PARAMETER)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface Valid {
+
+}
diff --git a/src/main/java/com/soft/aop/PermissionAspect.java b/src/main/java/com/soft/aop/PermissionAspect.java
new file mode 100644
index 0000000..cecfe52
--- /dev/null
+++ b/src/main/java/com/soft/aop/PermissionAspect.java
@@ -0,0 +1,83 @@
+package com.soft.aop;
+
+import com.alibaba.druid.util.StringUtils;
+import com.soft.annotations.HasPermission;
+import com.soft.service.PermissionService;
+import com.sun.tools.example.debug.expr.ExpressionParser;
+import org.apache.hadoop.hbase.security.AccessDeniedException;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.DefaultParameterNameDiscoverer;
+import org.springframework.expression.EvaluationContext;
+import org.springframework.expression.spel.standard.SpelExpressionParser;
+import org.springframework.expression.spel.support.StandardEvaluationContext;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+
+
+import java.lang.reflect.Method;
+
+@Aspect
+public class PermissionAspect {
+
+ @Autowired
+ private PermissionService permissionService; // 权限服务(需自行实现)
+
+ public PermissionAspect() {
+ }
+
+ @Pointcut("@annotation(com.soft.annotations.HasPermission) && execution(public * *(..))")
+ public void permissionPointCut() {
+ }
+
+ @Around("permissionPointCut()")
+ public Object permission(ProceedingJoinPoint joinPoint) throws Throwable {
+ MethodSignature signature = (MethodSignature) joinPoint.getSignature();
+ Method method = signature.getMethod();
+ HasPermission hasPermission = method.getAnnotation(HasPermission.class);
+
+ // 1. 解析用户ID(通过SpEL表达式)
+ String userIdSpEL = hasPermission.userId();
+ String userId = parseUserId(joinPoint, method, userIdSpEL);
+
+ // 2. 校验权限
+ if (!permissionService.hasPermission(
+ userId,
+ hasPermission.value(),
+ hasPermission.calcType())) {
+ throw new AccessDeniedException("用户[" + userId + "]无操作权限");
+ }
+
+ // 3. 执行目标方法
+ return joinPoint.proceed();
+ }
+
+ /**
+ * 解析SpEL表达式获取用户ID
+ */
+ private String parseUserId(ProceedingJoinPoint joinPoint, Method method, String spEL) {
+ if (StringUtils.isEmpty(spEL)) {
+ // 默认从安全上下文获取当前用户ID(例如Spring Security)
+ Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+ return authentication.getName();
+ }
+
+ // 使用Spring的SpEL解析器
+ SpelExpressionParser parser = new SpelExpressionParser();
+ EvaluationContext context = new StandardEvaluationContext();
+
+ // 将方法参数绑定到上下文
+ Object[] args = joinPoint.getArgs();
+ String[] paramNames = new DefaultParameterNameDiscoverer().getParameterNames(method);
+ for (int i = 0; i < args.length; i++) {
+ context.setVariable(paramNames[i], args[i]);
+ }
+ // 解析表达式并获取用户ID
+ return parser.parseExpression(spEL).getValue(context, String.class);
+ }
+}
+
diff --git a/src/main/java/com/soft/bo/SuperBo.java b/src/main/java/com/soft/bo/SuperBo.java
new file mode 100644
index 0000000..a6bc603
--- /dev/null
+++ b/src/main/java/com/soft/bo/SuperBo.java
@@ -0,0 +1,4 @@
+package com.soft.bo;
+
+public interface SuperBo {
+}
diff --git a/src/main/java/com/soft/bo/purchase/QueryPurchaseOrderBo.java b/src/main/java/com/soft/bo/purchase/QueryPurchaseOrderBo.java
new file mode 100644
index 0000000..b630e84
--- /dev/null
+++ b/src/main/java/com/soft/bo/purchase/QueryPurchaseOrderBo.java
@@ -0,0 +1,58 @@
+package com.soft.bo.purchase;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.soft.common.constants.StringPool;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Data
+public class QueryPurchaseOrderBo {
+ /**
+ * ID
+ */
+ @ApiModelProperty("ID")
+ private String id;
+
+ /**
+ * 单号
+ */
+ @ApiModelProperty("单号")
+ private String code;
+
+ /**
+ * 销售金额
+ */
+ @ApiModelProperty("销售金额")
+ private BigDecimal totalAmount;
+
+ /**
+ * 销售总商品数
+ */
+ @ApiModelProperty("销售总商品数")
+ private BigDecimal productAmount;
+
+ /**
+ * 创建人
+ */
+ @ApiModelProperty("创建人")
+ private String createBy;
+
+ /**
+ * 创建时间
+ */
+ @ApiModelProperty("创建时间")
+ @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN)
+ private LocalDateTime createTime;
+
+ /**
+ * 状态
+ */
+ @ApiModelProperty("状态")
+ private Integer status;
+
+ @ApiModelProperty(value = "商品名称")
+ private String productName;
+}
diff --git a/src/main/java/com/soft/bo/sale/QuerySaleOrderBo.java b/src/main/java/com/soft/bo/sale/QuerySaleOrderBo.java
new file mode 100644
index 0000000..70bc529
--- /dev/null
+++ b/src/main/java/com/soft/bo/sale/QuerySaleOrderBo.java
@@ -0,0 +1,59 @@
+package com.soft.bo.sale;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.soft.common.constants.StringPool;
+import com.soft.entitys.voice.SaleOrder;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Data
+public class QuerySaleOrderBo {
+ /**
+ * ID
+ */
+ @ApiModelProperty("ID")
+ private String id;
+
+ /**
+ * 单号
+ */
+ @ApiModelProperty("单号")
+ private String code;
+
+ /**
+ * 销售金额
+ */
+ @ApiModelProperty("销售金额")
+ private BigDecimal totalAmount;
+
+ /**
+ * 销售总商品数
+ */
+ @ApiModelProperty("销售总商品数")
+ private BigDecimal productAmount;
+
+ /**
+ * 创建人
+ */
+ @ApiModelProperty("创建人")
+ private String createBy;
+
+ /**
+ * 创建时间
+ */
+ @ApiModelProperty("创建时间")
+ @JsonFormat(pattern = StringPool.DATE_TIME_PATTERN)
+ private LocalDateTime createTime;
+
+ /**
+ * 状态
+ */
+ @ApiModelProperty("状态")
+ private Integer status;
+
+ @ApiModelProperty(value = "商品名称")
+ private String productName;
+}
diff --git a/src/main/java/com/soft/common/constants/ResponseConstants.java b/src/main/java/com/soft/common/constants/ResponseConstants.java
new file mode 100644
index 0000000..46cecf6
--- /dev/null
+++ b/src/main/java/com/soft/common/constants/ResponseConstants.java
@@ -0,0 +1,21 @@
+package com.soft.common.constants;
+
+public class ResponseConstants {
+ public static final Integer INVOKE_RESULT_SUCCESS_CODE = 200;
+ public static final Integer INVOKE_RESULT_FAIL_CODE_INPUT_ERROR = 400;
+ public static final Integer INVOKE_RESULT_FAIL_CODE_AUTH_EXPIRED = 401;
+ public static final Integer INVOKE_RESULT_FAIL_CODE_ACCESS_DENIED = 403;
+ public static final Integer INVOKE_RESULT_FAIL_CODE_REPEAT_REQUEST = 410;
+ public static final Integer INVOKE_RESULT_FAIL_USER_LOGIN_FAIL = 419;
+ public static final Integer INVOKE_RESULT_FAIL_CODE = 500;
+ public static final String INVOKE_RESULT_SUCCESS_MSG = "success";
+ public static final String INVOKE_RESULT_FAIL_MSG = "fail";
+ public static final String INVOKE_RESULT_ERROR_MSG = "系统出现内部错误,请联系系统管理员!";
+ public static final String INVOKE_RESULT_ERROR_MSG_INPUT_ERROR = "传入参数有误!";
+ public static final String INVOKE_RESULT_ERROR_MSG_AUTH_EXPIRED = "请重新登录!";
+ public static final String INVOKE_RESULT_ERROR_MSG_ACCESS_DENIED = "无系统权限!";
+ public static final String INVOKE_RESULT_ERROR_MSG_REPEAT_REQUEST = "请求过于频繁,请稍后再试!";
+
+ public ResponseConstants() {
+ }
+}
diff --git a/src/main/java/com/soft/common/constants/StringPool.java b/src/main/java/com/soft/common/constants/StringPool.java
new file mode 100644
index 0000000..bdba60c
--- /dev/null
+++ b/src/main/java/com/soft/common/constants/StringPool.java
@@ -0,0 +1,9 @@
+package com.soft.common.constants;
+
+public interface StringPool {
+ String EXCEL_DATE_PATTERN = "yyyy/MM/dd";
+ String DATE_PATTERN = "yyyy-MM-dd";
+ String TIME_PATTERN = "HH:mm:ss";
+ String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
+ String DATE_TIME_HOUR_PATTER = "yyyy-MM-dd HH";
+}
diff --git a/src/main/java/com/soft/common/functions/SFunction.java b/src/main/java/com/soft/common/functions/SFunction.java
new file mode 100644
index 0000000..e06fc78
--- /dev/null
+++ b/src/main/java/com/soft/common/functions/SFunction.java
@@ -0,0 +1,8 @@
+package com.soft.common.functions;
+
+import java.io.Serializable;
+import java.util.function.Function;
+
+@FunctionalInterface
+public interface SFunction extends Function, Serializable {
+}
diff --git a/src/main/java/com/soft/common/security/UserDetails.java b/src/main/java/com/soft/common/security/UserDetails.java
new file mode 100644
index 0000000..6e21782
--- /dev/null
+++ b/src/main/java/com/soft/common/security/UserDetails.java
@@ -0,0 +1,21 @@
+package com.soft.common.security;
+
+import java.io.Serializable;
+
+public interface UserDetails extends Serializable {
+ String getPassword();
+
+ String getUsername();
+
+ boolean isAccountNonExpired();
+
+ boolean isAccountNonLocked();
+
+ boolean isCredentialsNonExpired();
+
+ boolean isEnabled();
+
+ boolean isAdmin();
+
+ boolean hasAdminPermission();
+}
diff --git a/src/main/java/com/soft/common/util/DateUtils.java b/src/main/java/com/soft/common/util/DateUtils.java
new file mode 100644
index 0000000..d40b9a3
--- /dev/null
+++ b/src/main/java/com/soft/common/util/DateUtils.java
@@ -0,0 +1,21 @@
+package com.soft.common.util;
+
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.Date;
+
+public class DateUtils {
+ // Date 转 LocalDateTime(默认时区)
+ public static LocalDateTime toLocalDateTime(Date date) {
+ if (date == null) return null;
+ return date.toInstant()
+ .atZone(ZoneId.systemDefault())
+ .toLocalDateTime();
+ }
+
+ // LocalDateTime 转 Date(按需反向转换)
+ public static Date toDate(LocalDateTime localDateTime) {
+ if (localDateTime == null) return null;
+ return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
+ }
+}
diff --git a/src/main/java/com/soft/components/security/PermissionCalcType.java b/src/main/java/com/soft/components/security/PermissionCalcType.java
new file mode 100644
index 0000000..35e14e1
--- /dev/null
+++ b/src/main/java/com/soft/components/security/PermissionCalcType.java
@@ -0,0 +1,10 @@
+package com.soft.components.security;
+
+public enum PermissionCalcType {
+ OR,
+ AND;
+
+ private PermissionCalcType() {
+ }
+}
+
diff --git a/src/main/java/com/soft/config/BeanConfig.java b/src/main/java/com/soft/config/BeanConfig.java
new file mode 100644
index 0000000..1e45d19
--- /dev/null
+++ b/src/main/java/com/soft/config/BeanConfig.java
@@ -0,0 +1,17 @@
+package com.soft.config;
+
+import com.soft.utils.SpringBeanUtil;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.annotation.Order;
+
+@Configuration
+@Order(25)
+public class BeanConfig {
+
+ @Bean
+ public SpringBeanUtil getSpringBeanUtil(){
+ return new SpringBeanUtil();
+ }
+
+}
diff --git a/src/main/java/com/soft/config/DateConverterConfig.java b/src/main/java/com/soft/config/DateConverterConfig.java
new file mode 100644
index 0000000..e38d242
--- /dev/null
+++ b/src/main/java/com/soft/config/DateConverterConfig.java
@@ -0,0 +1,64 @@
+package com.soft.config;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.boot.jackson.JsonComponent;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+@Component
+public class DateConverterConfig implements Converter {
+
+
+ private static final String YYYY_MM_DD = "yyyy-MM-dd";
+ private static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
+
+ @JsonComponent
+ public static class DateJsonSerializer extends JsonSerializer {
+ @Override
+ public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
+ SimpleDateFormat sdf=new SimpleDateFormat(YYYY_MM_DD_HH_MM_SS);
+ jsonGenerator.writeString(sdf.format(date));
+ }
+ }
+
+ @Override
+ public Date convert(String source) {
+ if (StringUtils.isBlank(source)) {
+ return null;
+ }
+ source = source.trim();
+ if(source.matches("^\\d{4}-\\d{1,2}-\\d{1,2}$")){
+ return parseDate(source, YYYY_MM_DD);
+ }else if(source.matches("^\\d{4}-\\d{1,2}-\\d{1,2} {1}\\d{1,2}:\\d{1,2}:\\d{1,2}$")){
+ return parseDate(source, YYYY_MM_DD_HH_MM_SS);
+ }else {
+ throw new IllegalArgumentException("Invalid false value '" + source + "'");
+ }
+ }
+
+ /**
+ * 格式化日期
+ * @param dateStr String 字符型日期
+ * @param format String 格式
+ * @return Date 日期
+ */
+ private Date parseDate(String dateStr, String format) {
+ Date date;
+ try {
+ DateFormat dateFormat = new SimpleDateFormat(format);
+ date = dateFormat.parse(dateStr);
+ } catch (Exception e) {
+ throw new IllegalArgumentException(e.getLocalizedMessage());
+ }
+ return date;
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/soft/config/DruidConfig.java b/src/main/java/com/soft/config/DruidConfig.java
new file mode 100644
index 0000000..319f7ff
--- /dev/null
+++ b/src/main/java/com/soft/config/DruidConfig.java
@@ -0,0 +1,69 @@
+package com.soft.config;
+
+import com.alibaba.druid.support.http.StatViewServlet;
+import com.alibaba.druid.support.http.WebStatFilter;
+import com.alibaba.druid.support.spring.stat.DruidStatInterceptor;
+import org.springframework.aop.support.DefaultPointcutAdvisor;
+import org.springframework.aop.support.JdkRegexpMethodPointcut;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.boot.web.servlet.ServletRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Scope;
+import org.springframework.core.annotation.Order;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Configuration
+@Order(1)
+public class DruidConfig {
+
+ @Bean
+ public ServletRegistrationBean druidServlet() {
+ ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
+ Map initParam = new HashMap<>();
+ initParam.put("loginUsername","druid");
+ initParam.put("loginPassword","123456");
+ initParam.put("allow",""); //默认就是允许所有访问
+ initParam.put("deny",""); //默认访问
+ servletRegistrationBean.setInitParameters(initParam);
+ return servletRegistrationBean;
+ }
+
+ @Bean
+ public FilterRegistrationBean webStatFilter() {
+ FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
+ filterRegistrationBean.setFilter(new WebStatFilter());
+ Map initParams = new HashMap<>();
+ initParams.put("exclusions", "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*");
+ filterRegistrationBean.setInitParameters(initParams);
+ filterRegistrationBean.addUrlPatterns("/*");
+ filterRegistrationBean.setOrder(2);
+ filterRegistrationBean.setName("webStatFilter");
+ return filterRegistrationBean;
+ }
+
+ @Bean
+ public DruidStatInterceptor druidStatInterceptor() {
+ DruidStatInterceptor dsInterceptor = new DruidStatInterceptor();
+ return dsInterceptor;
+ }
+
+ @Bean
+ @Scope("prototype")
+ public JdkRegexpMethodPointcut druidStatPointcut() {
+ JdkRegexpMethodPointcut pointcut = new JdkRegexpMethodPointcut();
+ pointcut.setPattern("com.soft.mapper.*");
+ return pointcut;
+ }
+
+ @Bean
+ public DefaultPointcutAdvisor druidStatAdvisor(DruidStatInterceptor druidStatInterceptor, JdkRegexpMethodPointcut druidStatPointcut) {
+ DefaultPointcutAdvisor defaultPointAdvisor = new DefaultPointcutAdvisor();
+ defaultPointAdvisor.setPointcut(druidStatPointcut);
+ defaultPointAdvisor.setAdvice(druidStatInterceptor);
+ return defaultPointAdvisor;
+ }
+
+}
diff --git a/src/main/java/com/soft/config/RedisConfig.java b/src/main/java/com/soft/config/RedisConfig.java
new file mode 100644
index 0000000..7cdbc38
--- /dev/null
+++ b/src/main/java/com/soft/config/RedisConfig.java
@@ -0,0 +1,121 @@
+package com.soft.config;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.cache.CacheManager;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.core.annotation.Order;
+import org.springframework.data.redis.cache.RedisCacheConfiguration;
+import org.springframework.data.redis.cache.RedisCacheManager;
+import org.springframework.data.redis.cache.RedisCacheWriter;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.*;
+import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+import java.time.Duration;
+
+//@RefreshScope
+@Configuration
+@Order(20)
+public class RedisConfig {
+
+ @Bean
+ //如使用注解的话需要配置cacheManager
+ CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
+ //初始化一个RedisCacheWriter
+ RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory);
+ RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig();
+ //设置默认超过期时间是1天
+ //defaultCacheConfig.entryTtl(Duration.ofDays(1));
+ defaultCacheConfig.entryTtl(Duration.ofDays(-1));
+ //初始化RedisCacheManager
+ RedisCacheManager cacheManager = new RedisCacheManager(redisCacheWriter, defaultCacheConfig);
+ return cacheManager;
+ }
+
+ @Bean
+ @Primary
+ public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
+
+ RedisTemplate template = new RedisTemplate<>(); // 配置连接工厂
+ template.setConnectionFactory(factory); //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
+ Jackson2JsonRedisSerializer jacksonSerial = new Jackson2JsonRedisSerializer(Object.class);
+
+ ObjectMapper om = new ObjectMapper(); // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
+ om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
+ om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
+ jacksonSerial.setObjectMapper(om); // 值采用json序列化
+ template.setValueSerializer(jacksonSerial); //使用StringRedisSerializer来序列化和反序列化redis的key值
+ template.setKeySerializer(new StringRedisSerializer()); // 设置hash key 和value序列化模式
+ template.setHashKeySerializer(new StringRedisSerializer());
+ template.setHashValueSerializer(jacksonSerial);
+ template.afterPropertiesSet();
+ return template;
+ }
+
+ /**
+ * 对hash类型的数据操作
+ *
+ * @param redisTemplate
+ * @return
+ */
+
+ @Bean
+ public HashOperations hashOperations(RedisTemplate redisTemplate) {
+ return redisTemplate.opsForHash();
+ }
+
+ /**
+ * 对redis字符串类型数据操作
+ *
+ * @param redisTemplate
+ * @return
+ */
+
+ @Bean
+ public ValueOperations valueOperations(RedisTemplate redisTemplate) {
+ return redisTemplate.opsForValue();
+ }
+
+ /**
+ * 对链表类型的数据操作
+ *
+ * @param redisTemplate
+ * @return
+ */
+
+ @Bean
+ public ListOperations listOperations(RedisTemplate redisTemplate) {
+ return redisTemplate.opsForList();
+ }
+
+ /**
+ * 对无序集合类型的数据操作
+ *
+ * @param redisTemplate
+ * @return
+ */
+
+
+ @Bean
+ public SetOperations setOperations(RedisTemplate redisTemplate) {
+ return redisTemplate.opsForSet();
+ }
+
+ /**
+ * 对有序集合类型的数据操作
+ *
+ * @param redisTemplate
+ * @return
+ */
+ @Bean
+ public ZSetOperations zSetOperations(RedisTemplate redisTemplate) {
+ return redisTemplate.opsForZSet();
+ }
+
+
+}
diff --git a/src/main/java/com/soft/config/SecurityConfig.java b/src/main/java/com/soft/config/SecurityConfig.java
new file mode 100644
index 0000000..e8623fd
--- /dev/null
+++ b/src/main/java/com/soft/config/SecurityConfig.java
@@ -0,0 +1,40 @@
+package com.soft.config;
+
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.annotation.Order;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.builders.WebSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+
+
+@Configuration
+@EnableWebSecurity
+@Order(0)
+public class SecurityConfig extends WebSecurityConfigurerAdapter {
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ http
+ .authorizeRequests()
+ .antMatchers("/**").permitAll() // 所有路径无需认证
+ .anyRequest().permitAll()
+ .and()
+ .csrf().disable(); // 禁用CSRF
+ }
+
+ // 可选:忽略静态资源(如果不需要认证)
+ @Override
+ public void configure(WebSecurity web) throws Exception {
+ web.ignoring().antMatchers("/static/**");
+ }
+
+ @Bean
+ public PasswordEncoder passwordEncoder() {
+ return new BCryptPasswordEncoder(BCryptPasswordEncoder.BCryptVersion.$2A, 10);
+ }
+}
diff --git a/src/main/java/com/soft/config/SwaggerConfig.java b/src/main/java/com/soft/config/SwaggerConfig.java
new file mode 100644
index 0000000..6f3be1b
--- /dev/null
+++ b/src/main/java/com/soft/config/SwaggerConfig.java
@@ -0,0 +1,77 @@
+package com.soft.config;
+
+import com.soft.enums.AuthEnum;
+import com.soft.enums.CommEnum;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.annotation.Order;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.web.bind.annotation.RequestMethod;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.builders.ResponseMessageBuilder;
+import springfox.documentation.service.Contact;
+import springfox.documentation.service.ResponseMessage;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+@Configuration
+@EnableSwagger2
+@Order(55)
+public class SwaggerConfig extends WebSecurityConfigurerAdapter {
+
+ @Value("http:localhost:${server.port:8088}")
+ private String url;
+
+ @Bean
+ public Docket docketCommon() {
+ List responseMessageList = new ArrayList<>();
+ Arrays.stream(CommEnum.values()).forEach(enums -> {
+ responseMessageList.add(
+ new ResponseMessageBuilder().code(enums.getCode()).message(enums.getMessage()).build()
+ );
+ });
+ Arrays.stream(AuthEnum.values()).forEach(enums -> {
+ responseMessageList.add(
+ new ResponseMessageBuilder().code(enums.getCode()).message(enums.getMessage()).build()
+ );
+ });
+ return new Docket(DocumentationType.SWAGGER_2)
+ .globalResponseMessage(RequestMethod.GET, responseMessageList)
+ .globalResponseMessage(RequestMethod.POST, responseMessageList)
+ .globalResponseMessage(RequestMethod.PUT, responseMessageList)
+ .globalResponseMessage(RequestMethod.DELETE, responseMessageList)
+ .groupName("soft").select()
+ .apis(RequestHandlerSelectors.basePackage("com.soft.controller"))
+ .paths(PathSelectors.any())
+ .build()
+ .apiInfo(new ApiInfoBuilder().
+ title("soft API").
+ description("接口API").
+ contact(new Contact("", "", "")).termsOfServiceUrl(url).
+ version("1.0").
+ build());
+ }
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ http
+ .authorizeRequests()
+ // 限制 Swagger 路径需要 ADMIN 权限
+ .antMatchers("/swagger-ui/**", "/v3/api-docs/**").hasRole("ADMIN")
+ // 其他接口放行
+ .anyRequest().permitAll()
+ .and()
+ // 启用 Basic 认证(浏览器弹窗登录)
+ .httpBasic();
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/soft/config/TransDataSourceConfig.java b/src/main/java/com/soft/config/TransDataSourceConfig.java
new file mode 100644
index 0000000..c2d136e
--- /dev/null
+++ b/src/main/java/com/soft/config/TransDataSourceConfig.java
@@ -0,0 +1,27 @@
+package com.soft.config;
+
+import com.alibaba.druid.pool.DruidDataSource;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.core.annotation.Order;
+
+import javax.sql.DataSource;
+
+@Configuration
+@MapperScan(basePackages = "com.soft.mapper")
+@Order(10)
+public class TransDataSourceConfig {
+
+
+ @Bean
+ @Primary
+ @ConfigurationProperties(prefix = "spring.datasource")
+ public DataSource getDataSource() {
+ return new DruidDataSource();
+ }
+
+
+}
diff --git a/src/main/java/com/soft/config/UnifiedResultErrorConfig.java b/src/main/java/com/soft/config/UnifiedResultErrorConfig.java
new file mode 100644
index 0000000..9ad3792
--- /dev/null
+++ b/src/main/java/com/soft/config/UnifiedResultErrorConfig.java
@@ -0,0 +1,16 @@
+package com.soft.config;
+
+import com.soft.resp.Result;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+@RestControllerAdvice
+public class UnifiedResultErrorConfig {
+
+ @ExceptionHandler(value = RuntimeException.class)
+ public Result exception(RuntimeException e){
+ e.printStackTrace();
+ return Result.error();
+ }
+
+}
diff --git a/src/main/java/com/soft/config/WebConfiguration.java b/src/main/java/com/soft/config/WebConfiguration.java
new file mode 100644
index 0000000..51f0ca9
--- /dev/null
+++ b/src/main/java/com/soft/config/WebConfiguration.java
@@ -0,0 +1,29 @@
+package com.soft.config;
+
+import com.soft.filter.CrossFilter;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+/**
+ * @description WebConfiguration
+ * @author TDW
+ * @date 2021年3月4日
+ *
+ */
+//@Configuration
+public class WebConfiguration implements WebMvcConfigurer {
+
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ @Bean
+ public FilterRegistrationBean crossFilter(CrossFilter crossFilter) {
+ FilterRegistrationBean registrationBean = new FilterRegistrationBean(crossFilter);
+ registrationBean.setFilter(crossFilter);
+ registrationBean.addUrlPatterns("/*");
+ registrationBean.setOrder(1);
+ registrationBean.setName("crossFilter");
+ return registrationBean;
+ }
+
+}
diff --git a/src/main/java/com/soft/controller/AgentController.java b/src/main/java/com/soft/controller/AgentController.java
new file mode 100644
index 0000000..a656953
--- /dev/null
+++ b/src/main/java/com/soft/controller/AgentController.java
@@ -0,0 +1,52 @@
+package com.soft.controller;
+
+import com.soft.dto.UserIdDTO;
+import com.soft.resp.Result;
+import com.soft.entitys.user.User;
+import com.soft.mapper.UserMapper;
+import com.soft.service.AgentService;
+import com.soft.vo.*;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/agent")
+@Api(tags = "代理中心api")
+public class AgentController {
+
+ private Logger logger = LoggerFactory.getLogger(com.soft.controller.AgentController.class);
+
+ @Autowired
+ private AgentService agentService;
+
+ @Autowired
+ private UserMapper userMapper;
+
+ @GetMapping("/getAgentLevelList")
+ @ApiOperation(value = "代理等级和利润")
+ public Result> getAgentLevelList(){
+
+ return Result.success(agentService.getAgentLevelList());
+ }
+
+ @PostMapping("/getMySilverAgent")
+ @ApiOperation(value = "我的银牌代理")
+ public Result> getMySilverAgent(@RequestBody UserIdDTO userIdDTO){
+
+ return Result.success(userMapper.getMySilverAgent(userIdDTO.getUserId()));
+ }
+
+ @PostMapping("/getMyGoldMedalAgent")
+ @ApiOperation(value = "我的金牌代理")
+ public Result> getMyGoldMedalAgent(@RequestBody UserIdDTO userIdDTO){
+
+ return Result.success(userMapper.getMyGoldMedalAgent(userIdDTO.getUserId()));
+ }
+
+}
diff --git a/src/main/java/com/soft/controller/BaseController.java b/src/main/java/com/soft/controller/BaseController.java
new file mode 100644
index 0000000..49dbccf
--- /dev/null
+++ b/src/main/java/com/soft/controller/BaseController.java
@@ -0,0 +1,31 @@
+package com.soft.controller;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.soft.vo.page.PageVo;
+
+public abstract class BaseController {
+ public BaseController() {
+ }
+
+ public int getPageIndex(PageVo vo) {
+ return !ObjectUtil.isNull(vo) && !ObjectUtil.isNull(vo.getPageIndex()) && vo.getPageIndex() > 0 ? vo.getPageIndex() : 1;
+ }
+
+ public int getPageSize(PageVo vo) {
+ return !ObjectUtil.isNull(vo) && !ObjectUtil.isNull(vo.getPageSize()) && vo.getPageSize() > 0 ? vo.getPageSize() : 20;
+ }
+
+ public int getPageIndex() {
+ return this.getPageIndex((PageVo)null);
+ }
+
+ public int getPageSize() {
+ return this.getPageSize((PageVo)null);
+ }
+
+ public int getExportSize() {
+ return 2000;
+ }
+
+}
+
diff --git a/src/main/java/com/soft/controller/PurchaseOrderController.java b/src/main/java/com/soft/controller/PurchaseOrderController.java
new file mode 100644
index 0000000..13e905e
--- /dev/null
+++ b/src/main/java/com/soft/controller/PurchaseOrderController.java
@@ -0,0 +1,115 @@
+package com.soft.controller;
+
+
+import cn.hutool.core.collection.CollectionUtil;
+import com.soft.annotations.HasPermission;
+import com.soft.annotations.Valid;
+import com.soft.bo.purchase.QueryPurchaseOrderBo;
+import com.soft.dto.ApprovePassOrderDTO;
+import com.soft.entitys.voice.Product;
+import com.soft.entitys.voice.PurchaseOrderDetail;
+import com.soft.entitys.voice.SaleOrder;
+import com.soft.enums.OrderStatus;
+import com.soft.resp.InvokeResult;
+import com.soft.resp.InvokeResultBuilder;
+import com.soft.service.ProductService;
+import com.soft.service.PurchaseOrderDetailService;
+import com.soft.service.PurchaseOrderService;
+import com.soft.utils.PageResult;
+import com.soft.utils.PageResultUtil;
+import com.soft.utils.convert.purchase.QueryPurchaseOrderBOUtil;
+import com.soft.vo.sale.QuerySaleOrderVo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+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 com.soft.resp.Result;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@RestController
+@RequestMapping("/purchase/order")
+@Api(tags = "采购订单")
+public class PurchaseOrderController extends BaseController{
+
+ @Autowired
+ private PurchaseOrderService purchaseOrderService;
+
+ @Autowired
+ private PurchaseOrderDetailService purchaseOrderDetailService;
+
+ @Autowired
+ private ProductService productService;
+
+
+ /**
+ * 根据状态查询采购订单总数
+ */
+ @ApiOperation("根据状态查询采购订单总数")
+ @ApiImplicitParams({
+ @ApiImplicitParam(value = "订单审核状态(0-待审核,3-审核通过,6-审核拒绝)", name = "status", paramType = "query")})
+ @GetMapping("/total")
+ public Result queryPurchaseTotal(
+ Integer status) {
+ if (OrderStatus.valueOfCode(status) == null){
+ return Result.success(0);
+ }
+ Integer total = purchaseOrderService.getOrderSumByStatus(status);
+ return Result.success(total);
+ }
+
+ /**
+ * 采购订单审核
+ */
+ @ApiOperation("采购订单审核")
+ @HasPermission(
+ value = {"sale:order:approve"},
+ userId = "#approveOrder.sysUserId" // 使用SpEL引用方法参数
+ )
+ @GetMapping("/approve")
+ public Result approvePass(@RequestBody @Valid ApprovePassOrderDTO dto) {
+ purchaseOrderService.approvePass(dto);
+ return Result.success();
+
+ }
+
+ /**
+ * 查询未审核采购订单列表
+ */
+ @ApiOperation("查询未审核采购订单列表")
+ @GetMapping("/pendList")
+ public InvokeResult> pendApproveList(QuerySaleOrderVo vo) {
+ PageResult pageResult = purchaseOrderService.pendApproveList(getPageIndex(vo), getPageSize(vo), vo.getStatus());
+
+ List datas = pageResult.getDatas();
+ List results = null;
+
+ if (!CollectionUtil.isEmpty(datas)) {
+ results = datas.stream().map(QueryPurchaseOrderBOUtil::toQueryPurchaseOrderBo).collect(Collectors.toList());
+ }
+ //商品名称处理
+ if(results!=null){
+ for (QueryPurchaseOrderBo result : results) {
+ List orderDetails=purchaseOrderDetailService.getByOrderId(result.getId());
+
+ List productNames = new ArrayList<>();
+ for (PurchaseOrderDetail orderDetail : orderDetails) {
+ Product product= productService.findById(orderDetail.getProductId());
+ if (product != null && product.getName() != null) {
+ productNames.add(product.getName());
+ }
+
+ }
+ result.setProductName(String.join(", ", productNames));
+ }
+ }
+ return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results));
+ }
+}
diff --git a/src/main/java/com/soft/controller/SaleOrderController.java b/src/main/java/com/soft/controller/SaleOrderController.java
new file mode 100644
index 0000000..0a461aa
--- /dev/null
+++ b/src/main/java/com/soft/controller/SaleOrderController.java
@@ -0,0 +1,130 @@
+package com.soft.controller;
+
+import cn.hutool.core.collection.CollectionUtil;
+import com.soft.annotations.HasPermission;
+import com.soft.annotations.Valid;
+import com.soft.bo.sale.QuerySaleOrderBo;
+import com.soft.dto.ApprovePassOrderDTO;
+import com.soft.dto.SysUserDTO;
+import com.soft.entitys.voice.Product;
+import com.soft.entitys.voice.SaleOrder;
+import com.soft.entitys.voice.SaleOrderDetail;
+import com.soft.enums.OrderStatus;
+import com.soft.resp.InvokeResult;
+import com.soft.resp.InvokeResultBuilder;
+import com.soft.service.ProductService;
+import com.soft.service.SaleOrderDetailService;
+import com.soft.service.SaleOrderService;
+import com.soft.service.SysUserService;
+import com.soft.utils.PageResult;
+import com.soft.utils.PageResultUtil;
+import com.soft.utils.convert.sale.QuerySaleOrderBOUtil;
+import com.soft.vo.sale.QuerySaleOrderVo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+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 com.soft.resp.Result;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Api(tags = "销售订单")
+@Validated
+@RestController
+@RequestMapping("/sale/order")
+public class SaleOrderController extends BaseController{
+
+ @Autowired
+ private SaleOrderService saleOrderService;
+
+ @Autowired
+ private SysUserService sysUserService;
+
+ @Autowired
+ private SaleOrderDetailService saleOrderDetailService;
+
+ @Autowired
+ private ProductService productService;
+
+ /**
+ * 根据状态查询销售订单总数
+ */
+ @ApiOperation("根据状态查询销售订单总数")
+ @ApiImplicitParams({
+ @ApiImplicitParam(value = "订单审核状态(0-待审核,3-审核通过,6-审核拒绝)", name = "status", paramType = "query")})
+ @GetMapping("/total")
+ public Result querySaleTotal(
+ Integer status) {
+ if (OrderStatus.valueOfCode(status) == null){
+ return Result.success(0);
+ }
+ Integer total = saleOrderService.getOrderSumByStatus(status);
+ return Result.success(total);
+ }
+
+
+ /**
+ * 销售订单审核
+ */
+ @ApiOperation("销售订单审核")
+ @HasPermission(
+ value = {"sale:order:approve"}, //判断用户是否具有审核权限
+ userId = "#approveOrder.sysUserId" // 使用SpEL引用方法参数
+ )
+ @GetMapping("/approve")
+ public Result approvePass(@RequestBody @Valid ApprovePassOrderDTO approveOrder) {
+ //1. 查询用户id 关联的后台用户id; 3.判断订单是否存在,且状态是否是已审核状态
+ SysUserDTO sysUserDTO = sysUserService.selectById(approveOrder.getSysUserId());
+ if (sysUserDTO == null){
+ return Result.fail("系统用户不存在,请检查后重试!");
+ }
+ // 审核 修改订单状态
+ saleOrderService.approve(approveOrder.getOrderId(), approveOrder.getSysUserId());
+ return null;
+ }
+
+ /**
+ * 查询未审核销售订单
+ */
+ @ApiOperation("查询未审核销售订单列表")
+ @GetMapping("/pendList")
+ public InvokeResult> pendApproveList(QuerySaleOrderVo vo) {
+ PageResult pageResult = saleOrderService.pendApproveList(getPageIndex(vo), getPageSize(vo), vo.getStatus());
+
+ List datas = pageResult.getDatas();
+ List results = null;
+
+ //转换
+ if (!CollectionUtil.isEmpty(datas)) {
+ results = datas.stream().map(QuerySaleOrderBOUtil::toQuerySaleOrderBo).collect(Collectors.toList());
+ }
+ //商品名称处理
+ if(results!=null){
+ for (QuerySaleOrderBo result : results) {
+ List orderDetails=saleOrderDetailService.getBySaleOrderId(result.getId());
+
+ List productNames = new ArrayList<>();
+ for (SaleOrderDetail orderDetail : orderDetails) {
+ Product product= productService.findById(orderDetail.getProductId());
+ if (product != null && product.getName() != null) {
+ productNames.add(product.getName());
+ }
+
+ }
+ result.setProductName(String.join(", ", productNames));
+ }
+ }
+ return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results));
+ }
+
+
+
+}
diff --git a/src/main/java/com/soft/controller/SoftController.java b/src/main/java/com/soft/controller/SoftController.java
new file mode 100644
index 0000000..0573e52
--- /dev/null
+++ b/src/main/java/com/soft/controller/SoftController.java
@@ -0,0 +1,39 @@
+package com.soft.controller;
+
+import com.soft.dto.SaveDemandDTO;
+import com.soft.resp.Result;
+import com.soft.service.DemandService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+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;
+
+@RestController
+@RequestMapping("/soft")
+@Api(tags = "api")
+public class SoftController {
+
+ @Autowired
+ private DemandService demandService;
+
+
+ @PostMapping("/saveSoftWareDemand")
+ @ApiOperation(value = "提交表单")
+ public Result saveSoftWareDemand(@RequestBody SaveDemandDTO saveDemandDTO) {
+ if (saveDemandDTO == null) {
+ return Result.isEmpty();
+ }
+ Integer result=demandService.saveSoftWareDemand(saveDemandDTO);
+
+ if(result>0){
+ return Result.success("ok");
+ }else{
+ return Result.fail("fail");
+ }
+
+ }
+
+}
diff --git a/src/main/java/com/soft/controller/UserController.java b/src/main/java/com/soft/controller/UserController.java
new file mode 100644
index 0000000..50ec452
--- /dev/null
+++ b/src/main/java/com/soft/controller/UserController.java
@@ -0,0 +1,103 @@
+package com.soft.controller;
+
+import com.soft.dto.BindPhoneNumberDTO;
+import com.soft.dto.WeChatLoginRequestDTO;
+import com.soft.resp.Result;
+import com.soft.entitys.user.SystemUser;
+import com.soft.dto.SysUserDTO;
+import com.soft.entitys.user.User;
+import com.soft.service.SysUserService;
+import com.soft.service.UserService;
+import com.soft.vo.BindPhoneVo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Map;
+import java.util.Objects;
+
+@RestController
+@RequestMapping("/user")
+@Api(tags = "用户api")
+public class UserController {
+
+ @Autowired
+ private UserService userService;
+
+ @Autowired
+ private SysUserService sysUserService;
+
+
+ @PostMapping("/wxLogin")
+ @ApiOperation(value = "微信授权登录")
+ public Result