Compare commits

...

76 Commits

Author SHA1 Message Date
曾文豪
e8cc8cf8f7 publish 2.0.30
All checks were successful
/ local-deploy (push) Successful in 26s
2025-06-27 13:36:11 +08:00
曾文豪
bb0e5098af publish 2.0.28
All checks were successful
/ local-deploy (push) Successful in 30s
2025-06-27 13:30:26 +08:00
曾文豪
6d91cc7c13 perf(http): 为 OkHttpClient 添加写超时设置 2025-06-27 13:29:56 +08:00
曾文豪
94f93f8a80 refactor(chart): 优化图表模板和记录功能 2025-06-03 09:28:46 +08:00
曾文豪
9363d08308 refactor(login): 移除登录签名验证相关代码 2025-05-27 16:34:06 +08:00
曾文豪
3797c0edd2 feat(TsTokenConfig): 开启登录签名验证 2025-05-27 11:59:45 +08:00
曾文豪
1cf97feabf refactor(chart): 优化图表模板接口返回数据 2025-05-22 16:52:13 +08:00
曾文豪
bce848af7e Merge remote-tracking branch 'origin/master' 2025-05-22 13:41:18 +08:00
曾文豪
a6b0062f8d feat(chart): 新增图表功能 2025-05-22 13:41:12 +08:00
885303e555 删除 springboot-ademo/.DS_Store 2025-05-16 00:00:54 +08:00
0cf30770f1 删除 springboot-util/.DS_Store 2025-05-15 23:59:58 +08:00
6a66f41925 删除 .DS_Store 2025-05-15 23:54:01 +08:00
曾文豪
2d8208e4dc publish 2.0.27
All checks were successful
/ local-deploy (push) Successful in 8m4s
2025-04-24 11:39:20 +08:00
曾文豪
c4ba637de7 build(springboot-util & springboot-web): 升级依赖版本 2025-04-24 11:38:56 +08:00
曾文豪
7b0b9e0925 feat(core-log): 添加操作日志时指定创建时间 2025-04-24 10:14:29 +08:00
曾文豪
463ddf1b1e publish 2.0.26
All checks were successful
/ local-deploy (push) Successful in 18s
2025-04-22 13:41:17 +08:00
曾文豪
6fdc69fc2d publish 2.0.25
All checks were successful
/ local-deploy (push) Successful in 19s
2025-04-22 13:33:29 +08:00
曾文豪
fde73e57b9 feat(cache): 添加重复操作检查功能 2025-04-22 13:32:58 +08:00
曾文豪
8a517b09fd fix(web): 修复 CoreConfigService 中的空值问题 2025-04-09 15:05:20 +08:00
曾文豪
217d044940 publish 2.0.24
All checks were successful
/ local-deploy (push) Successful in 19s
2025-04-07 15:45:21 +08:00
曾文豪
9ecf58d75e feat(role): 添加公开服务功能 2025-04-07 15:44:45 +08:00
曾文豪
5c0d47a011 publish 2.0.23
All checks were successful
/ local-deploy (push) Successful in 17s
2025-04-05 14:57:09 +08:00
曾文豪
08066f1367 Merge remote-tracking branch 'origin/master' 2025-04-05 14:55:06 +08:00
曾文豪
9e7ed69d37 feat(web): 修改配置备注为配置键 2025-04-05 14:55:00 +08:00
曾文豪
2793b2a634 publish 2.0.22
All checks were successful
/ local-deploy (push) Successful in 21s
2025-03-31 00:29:39 +08:00
曾文豪
9885e640e9 build: 更新代码仓库地址 2025-03-26 23:25:45 +08:00
曾文豪
9b285db5bd publish 2.0.21
All checks were successful
/ local-deploy (push) Successful in 18s
2025-03-24 17:10:33 +08:00
曾文豪
abbfac2f08 publish 2.0.20
All checks were successful
/ local-deploy (push) Successful in 17s
2025-03-21 17:53:13 +08:00
曾文豪
fba88da506 feat(login): 添加自定义 TokenBean 并更新相关逻辑 2025-03-21 17:51:40 +08:00
曾文豪
cb6e1c85b2 publish 2.0.19
All checks were successful
/ local-deploy (push) Successful in 18s
2025-03-20 16:20:40 +08:00
曾文豪
2649070850 build: 更新 ip2region 数据库链接 2025-03-20 16:19:51 +08:00
曾文豪
48a9d46d20 feat(login): 调整默认登录失败次数为0次,不进行校验 2025-03-07 14:16:19 +08:00
曾文豪
f8d7e49290 publish 2.0.18
All checks were successful
/ local-deploy (push) Successful in 19s
2024-12-13 20:20:29 +08:00
曾文豪
2cf88cefa7 publish 2.0.17
All checks were successful
/ local-deploy (push) Successful in 20s
2024-12-08 12:00:48 +08:00
曾文豪
9a56994342 publish 2.0.16
All checks were successful
/ local-deploy (push) Successful in 20s
2024-12-08 11:53:36 +08:00
曾文豪
a987689bd6 perf:优化登录次数校验 2024-12-08 11:53:11 +08:00
曾文豪
690dffa779 publish 2.0.15
All checks were successful
/ local-deploy (push) Successful in 18s
2024-12-08 10:23:38 +08:00
曾文豪
3ccbd6cd8e feat:configKey增加缓存 2024-12-08 10:22:44 +08:00
曾文豪
89e0c5d1d5 publish 2.0.14
All checks were successful
/ local-deploy (push) Successful in 21s
2024-11-21 15:22:36 +08:00
曾文豪
b15dbc6d4c perf:调整表结构 2024-11-21 15:21:58 +08:00
曾文豪
2f6b5b0b05 perf:更改一个方法的名称 2024-10-28 09:24:38 +08:00
曾文豪
832d615273 publish 2.0.13
All checks were successful
/ local-deploy (push) Successful in 19s
2024-10-10 16:20:35 +08:00
曾文豪
383a82e530 feat:增加useragent 2024-10-10 16:20:14 +08:00
曾文豪
6531709c69 feat:增加一个表单提交方法 2024-10-10 16:15:06 +08:00
曾文豪
6aaf91a755 publish 2.0.12
All checks were successful
/ local-deploy (push) Successful in 32s
2024-10-10 15:52:53 +08:00
曾文豪
f1ac7d6886 publish 2.0.12 2024-10-10 15:51:40 +08:00
曾文豪
2f07f9eb66 publish 2.0.11 2024-09-30 11:46:43 +08:00
曾文豪
919cd47623 publish 2.0.10 2024-09-23 15:50:36 +08:00
曾文豪
eb1c20b033 feat:授权增加一个备注字段 2024-09-19 14:13:13 +08:00
曾文豪
c1559e96be publish 2.0.9 2024-09-18 23:09:53 +08:00
曾文豪
9ef7d2d4a2 publish 2.0.8 2024-09-18 22:59:28 +08:00
曾文豪
b90e92f4cb perf: token兼容旧版本,旧版本使用的是10位数的秒作为数据 2024-09-18 22:59:10 +08:00
曾文豪
cb816d0ff0 publish 2.0.7 2024-09-18 17:27:45 +08:00
曾文豪
0470ca0b9a perf:空指针调整 2024-09-18 17:25:19 +08:00
曾文豪
d38077b0f8 perf:代码调整 2024-09-18 17:13:40 +08:00
曾文豪
2621c6dedc perf:可以不实现TsAuthorityHandler类 2024-09-18 16:47:29 +08:00
曾文豪
456a95778c publish 2.0.6 2024-09-18 16:30:49 +08:00
曾文豪
fd0976a30c Merge remote-tracking branch 'origin/master'
# Conflicts:
#	springboot-ademo/src/main/java/com/tiesheng/demo/controller/TestController.java
2024-09-18 14:53:10 +08:00
曾文豪
e519781207 fix:职位授权增加非空校验 2024-09-18 14:52:48 +08:00
曾文豪
e602f4c658 publish 2.0.5 2024-09-14 22:57:37 +08:00
曾文豪
a816acaddb fix:修复网络请求异常时,api日志记录不完整的bug 2024-09-14 22:57:03 +08:00
曾文豪
278429157a perf:钉钉单次同步调整为200 2024-09-14 22:38:07 +08:00
曾文豪
143b100819 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	springboot-platform/src/main/java/com/tiesheng/platform/config/ding/PlatformDingConfig.java
2024-09-14 22:36:38 +08:00
曾文豪
d0cd9aed0b perf:钉钉单次同步调整为200 2024-09-14 22:35:56 +08:00
曾文豪
3080d8a936 publish 2.0.4 2024-09-14 11:21:17 +08:00
曾文豪
3f951dfe47 fix:图像验证码的大小不能超过500x200 2024-09-12 14:20:17 +08:00
曾文豪
9c66dafe6b fix:权限组缺少deps属性 2024-09-12 14:17:18 +08:00
曾文豪
d6ed2b8037 publish 2.0.3 2024-09-10 11:08:06 +08:00
曾文豪
02c2ccc0ff perf:优化登录代码 2024-08-29 14:56:05 +08:00
曾文豪
f27d8d1658 publish 2.0.2 2024-08-28 20:40:43 +08:00
曾文豪
ba9d0da33f remove:移除了poi模块 2024-08-28 20:39:52 +08:00
曾文豪
4690fa9f88 perf:调整登录日志,同时限制登录失败次数(10分钟内最多5次) 2024-08-28 20:35:38 +08:00
曾文豪
a9f218de89 perf:移除encrypt模块,直接集成到web模块中 2024-08-28 19:41:45 +08:00
曾文豪
55324199cd feat:枚举表增加sort排序字段 2024-08-28 19:34:03 +08:00
曾文豪
0b32559630 feat:新增接口 /comm/role/group 获取角色、职位列表 2024-08-28 19:29:45 +08:00
曾文豪
01cc4f16ad perf:调用日志可以筛选 url 2024-08-28 19:22:26 +08:00
106 changed files with 2532 additions and 458 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -0,0 +1,25 @@
## 工作流触发时机
on:
push:
tags:
- '*'
jobs:
## 任务名称
local-deploy:
## 任务执行的服务器
runs-on: tiesheng-local
## 任务步骤
steps:
## 检出代码(固定配置)
- name: Check out repository code
uses: https://git.tieshengkeji.com/actions/checkout@v4
## maven打包
- name: Maven deploy
run: |
mvn deploy

View File

@@ -1,3 +1,8 @@
## 2.0.12
- 调整OkHttp日志
## 2.0.0.rc46
现在导入导出都接入底层流程,无需新增接口,只需要实现接口即可。

View File

@@ -50,7 +50,7 @@
<repositories>
<repository>
<id>kepai-repo</id>
<url>http://git.kepai365.com/tiesheng/repository/raw/master</url>
<url>https://git.tieshengkeji.com/api/packages/tieshengkeji/maven</url>
</repository>
</repositories>
```

44
pom.xml
View File

@@ -6,7 +6,7 @@
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-parent</artifactId>
<version>2.0.1</version>
<version>2.0.30</version>
<packaging>pom</packaging>
<name>springboot-parent</name>
<description>杭州铁晟科技有限公司基础依赖</description>
@@ -23,12 +23,11 @@
<module>springboot-login</module>
<module>springboot-web</module>
<module>springboot-util</module>
<module>springboot-poi</module>
<module>springboot-platform</module>
<module>springboot-message</module>
<module>springboot-encrypt</module>
<module>springboot-annotation</module>
<module>springboot-role</module>
<module>springboot-chart</module>
</modules>
<properties>
@@ -60,61 +59,49 @@
<dependency>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-database</artifactId>
<version>2.0.1</version>
<version>2.0.30</version>
</dependency>
<dependency>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-login</artifactId>
<version>2.0.1</version>
<version>2.0.30</version>
</dependency>
<dependency>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-web</artifactId>
<version>2.0.1</version>
<version>2.0.30</version>
</dependency>
<dependency>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-util</artifactId>
<version>2.0.1</version>
<version>2.0.30</version>
</dependency>
<dependency>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-platform</artifactId>
<version>2.0.1</version>
<version>2.0.30</version>
</dependency>
<dependency>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-message</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-encrypt</artifactId>
<version>2.0.1</version>
<version>2.0.30</version>
</dependency>
<dependency>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-role</artifactId>
<version>2.0.1</version>
<version>2.0.30</version>
</dependency>
<dependency>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-annotation</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-poi</artifactId>
<version>2.0.1</version>
<version>2.0.30</version>
</dependency>
<dependency>
@@ -134,11 +121,18 @@
<pluginRepositories>
<pluginRepository>
<id>kepai-repo-plugin</id>
<url>http://git.kepai365.com/tiesheng/repository/raw/master</url>
<id>tiesheng-repo-plugin</id>
<url>https://git.tieshengkeji.com/api/packages/tieshengkeji/maven</url>
</pluginRepository>
</pluginRepositories>
<distributionManagement>
<repository>
<id>gitea</id>
<url>https://git.tieshengkeji.com/api/packages/tieshengkeji/maven</url>
</repository>
</distributionManagement>
<build>
<pluginManagement>
<plugins>

31
qodana.yaml Normal file
View File

@@ -0,0 +1,31 @@
#-------------------------------------------------------------------------------#
# Qodana analysis is configured by qodana.yaml file #
# https://www.jetbrains.com/help/qodana/qodana-yaml.html #
#-------------------------------------------------------------------------------#
version: "1.0"
#Specify inspection profile for code analysis
profile:
name: qodana.starter
#Enable inspections
#include:
# - name: <SomeEnabledInspectionId>
#Disable inspections
#exclude:
# - name: <SomeDisabledInspectionId>
# paths:
# - <path/where/not/run/inspection>
projectJDK: 17 #(Applied in CI/CD pipeline)
#Execute shell command before Qodana execution (Applied in CI/CD pipeline)
#bootstrap: sh ./prepare-qodana.sh
#Install IDE plugins before Qodana execution (Applied in CI/CD pipeline)
#plugins:
# - id: <plugin.id> #(plugin id can be found at https://plugins.jetbrains.com)
#Specify Qodana linter for analysis (Applied in CI/CD pipeline)
linter: jetbrains/qodana-jvm:latest

Binary file not shown.

View File

@@ -6,11 +6,11 @@
<parent>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-parent</artifactId>
<version>2.0.1</version>
<version>2.0.30</version>
</parent>
<artifactId>springboot-ademo</artifactId>
<version>2.0.1</version>
<version>2.0.30</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
@@ -46,8 +46,8 @@
<repositories>
<repository>
<id>kepai-repo</id>
<url>http://git.kepai365.com/tiesheng/repository/raw/master</url>
<id>tiesheng-repo</id>
<url>https://git.tieshengkeji.com/api/packages/tieshengkeji/maven</url>
</repository>
</repositories>

View File

@@ -16,10 +16,6 @@ import java.util.Objects;
@Component
public class DemoWebConfigurer implements TieshengWebConfigurer, TsLoginConfigurer {
@Autowired
GlobalConfig globalConfig;
@Override
public RequestUserInfo getCurrentUserName(TokenBean tokenBean) {
RequestUserInfo info = new RequestUserInfo();

View File

@@ -1,8 +1,6 @@
package com.tiesheng.demo.config;
import com.tiesheng.web.service.CoreConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@@ -13,9 +11,6 @@ import javax.annotation.PostConstruct;
@Component
public class TestJobConfig {
@Autowired
CoreConfigService coreConfigService;
@PostConstruct
public void init() {
}

View File

@@ -1,6 +1,5 @@
package com.tiesheng.demo.controller;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.io.FileUtil;
@@ -13,9 +12,9 @@ import com.alibaba.fastjson.JSONObject;
import com.tiesheng.annotation.role.RoleAuthority;
import com.tiesheng.annotation.token.TokenIgnore;
import com.tiesheng.database.config.DbBackupConfig;
import com.tiesheng.demo.pojos.CustTokenBean;
import com.tiesheng.demo.pojos.JsonTest;
import com.tiesheng.demo.pojos.PoiBean;
import com.tiesheng.demo.pojos.TestFile;
import com.tiesheng.platform.config.ding.PlatformDingConfig;
import com.tiesheng.platform.config.ding.bean.DingUserInfo;
import com.tiesheng.util.config.EncryptConfig;
@@ -31,11 +30,13 @@ import com.tiesheng.web.service.CoreLogService;
import okhttp3.Request;
import okhttp3.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.util.List;
import java.util.function.Consumer;
/**
@@ -43,7 +44,6 @@ import java.util.function.Consumer;
*/
@RestController
@RequestMapping("/test")
@RoleAuthority(value = "test", group = "test")
public class TestController {
@Autowired
@@ -65,15 +65,17 @@ public class TestController {
@RequestMapping("/index")
@TokenIgnore
public void index(HttpServletResponse response) {
globalConfig.redirect("mobile", "/test", response);
globalConfig.redirectWithVer("mobile", "/test", response);
}
@RequestMapping("/redirect")
@TokenIgnore
@RoleAuthority("redirect")
public ApiResp<JsonTest> redirect(@RequestBody JsonTest dto, HttpServletResponse response) {
public ApiResp<JsonTest> redirect(HttpServletResponse response) {
String s1 = encryptConfig.passwdCreate("qU3?wE3{bX", "");
LogFactory.get().info(s1);
JsonTest jsonTest = new JsonTest();
jsonTest.setNow(DateUtil.date());
@@ -82,7 +84,8 @@ public class TestController {
String jsonString = JSON.toJSONString(jsonTest);
LogFactory.get().info(jsonString);
LogFactory.get().info(JSON.toJSONString(dto));
String s = OkHttpUtil.get("http://toolbox.tieshengkeji.com/test/login/23232/3232");
LogFactory.get().info(s);
// ArrayList<String> strings = CollUtil.newArrayList("11111", "22222");
// coreLogService.addProcess("fdfd", strings, new ProcessImportConsumer<String>() {
@@ -109,8 +112,9 @@ public class TestController {
@GetMapping("/send")
@TokenIgnore
public ApiResp<String> sendMessage() {
public ApiResp<String> sendMessage(CustTokenBean tokenBean) {
tokenBean.test();
// MessageReqResp reqResp = coreMessageService.send(new UserChannel("13567116463", "sms"),
// JSONUtil.createObj().putOpt("action", "sms-visitor-invite"));
@@ -160,16 +164,6 @@ public class TestController {
return ApiResp.respOK(search);
}
@RequestMapping("desensitize")
@TokenIgnore
public ApiResp<List<TestFile>> desensitize() {
TestFile file = new TestFile("11111");
file.setTest("111111");
TestFile file1 = new TestFile("22222");
file1.setTest("22222");
return ApiResp.respOK(CollUtil.newArrayList(file, file1));
}
@RequestMapping("passwd")
@TokenIgnore
@@ -226,8 +220,10 @@ public class TestController {
"83_7xqG36kdgwuf8zzWLY3jtz7bg4ucziN-0oxbE0X9zBzwbjZ4S4Ss2RM9uHeSIcRp2K-wEp6MLzWhqo2AXj0Jpzd6IiJdUsRxqdHPvEWqAdOgt83vzZwdDf7tZBkGNGeAFASZS",
paramJson);
Response execute1 = OkHttpUtil.ofHttpClient().build().newCall(request).execute();
FileUtil.writeFromStream(execute1.body().byteStream(), file.getAbsolutePath());
execute1.close();
if (execute1.body() != null) {
FileUtil.writeFromStream(execute1.body().byteStream(), file.getAbsolutePath());
execute1.close();
}
} catch (Exception e) {
throw new ApiException("每分钟最多生成5000个二维码请稍后再试");
}

View File

@@ -0,0 +1,12 @@
package com.tiesheng.demo.pojos;
import com.tiesheng.util.pojos.TokenBean;
public class CustTokenBean extends TokenBean {
public void test() {
System.out.println("test: " + getId());
}
}

View File

@@ -1,21 +0,0 @@
package com.tiesheng.demo.pojos;
import com.tiesheng.poi.pojos.PoiWriteBase;
public class TestFile extends TestParent implements PoiWriteBase {
private String name;
public TestFile(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@@ -1,31 +0,0 @@
package com.tiesheng.demo.pojos;
import com.tiesheng.poi.pojos.PoiWriteBase;
public class TestParent implements PoiWriteBase {
private String id;
private String test;
///////////////////////////////////////////////////////////////////////////
// setter、getter
///////////////////////////////////////////////////////////////////////////
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTest() {
return test;
}
public void setTest(String test) {
this.test = test;
}
}

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-parent</artifactId>
<version>2.0.1</version>
<version>2.0.30</version>
</parent>
<artifactId>springboot-annotation</artifactId>

View File

@@ -6,10 +6,10 @@
<parent>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-parent</artifactId>
<version>2.0.1</version>
<version>2.0.30</version>
</parent>
<artifactId>springboot-poi</artifactId>
<artifactId>springboot-chart</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
@@ -18,17 +18,21 @@
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-util</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,111 @@
package com.tiesheng.role.controller;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.style.row.SimpleRowHeightStyleStrategy;
import com.alibaba.fastjson.JSONObject;
import com.tiesheng.annotation.operation.OperationIgnore;
import com.tiesheng.annotation.role.RoleAuthority;
import com.tiesheng.role.pojos.dto.ChartTemplateCheck;
import com.tiesheng.role.pojos.vo.TsTableVO;
import com.tiesheng.role.service.ChartService;
import com.tiesheng.role.util.AliExcelUtil;
import com.tiesheng.util.config.GlobalConfig;
import com.tiesheng.util.exception.ApiException;
import com.tiesheng.util.pojos.ApiResp;
import com.tiesheng.util.pojos.FileUploadPath;
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;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping("/chart/record")
@RoleAuthority(value = "template", group = "chart")
public class ChartRecordController {
@Resource
ChartService chartService;
@Resource
GlobalConfig globalConfig;
/**
* 获取列表
*
* @return
*/
@PostMapping("/check")
@OperationIgnore
public ApiResp<TsTableVO> check(@RequestBody @Valid ChartTemplateCheck dto) {
if (dto.getTemplate() == null) {
dto.setTemplate(chartService.getById(dto.getTemplateId()));
}
if (dto.getTemplate() == null) {
throw new ApiException("请选择或创建一个模版");
}
try {
List<JSONObject> chartRecordVOS = chartService.getBaseMapper()
.recordCheck(dto.getTemplate().getTableName(), dto.getCountType(),
dto.getTableXField(), dto.getWhere(),
dto.getTemplate().getSField(),
dto.getTableGroupBy());
chartRecordVOS.forEach(it -> {
it.put("xField", StrUtil.emptyToDefault(it.getString("xField"), "未分类"));
});
return ApiResp.respOK(TsTableVO.of(dto.getTemplate(), chartRecordVOS));
} catch (Exception e) {
throw new ApiException("表或字段配置有误,请检查");
}
}
/**
* 导出数据
*
* @return
*/
@PostMapping("/export")
@OperationIgnore
public ApiResp<String> export(@RequestBody @Valid ChartTemplateCheck dto) {
TsTableVO tsTableVO = check(dto).getData();
if (tsTableVO.getDataSource().isEmpty()) {
return ApiResp.respOK("");
}
List<List<String>> headers = new ArrayList<>();
for (TsTableVO.TableColumn column : tsTableVO.getColumns()) {
headers.add(CollUtil.newArrayList(column.getTitle()));
}
List<List<String>> contents = new ArrayList<>();
for (JSONObject obj : tsTableVO.getDataSource()) {
List<String> data = new ArrayList<>();
for (TsTableVO.TableColumn column : tsTableVO.getColumns()) {
data.add(obj.getString(column.getDataIndex()));
}
contents.add(data);
}
FileUploadPath xls = FileUploadPath.random("xls");
EasyExcel.write(xls.getAbsolutePath())
.sheet("数据统计")
.registerWriteHandler(new AliExcelUtil.ChatColumnWidthStyleStrategy())
.registerWriteHandler(new SimpleRowHeightStyleStrategy((short) 24, null))
.registerWriteHandler(AliExcelUtil.getCustomStyle())
.head(headers)
.doWrite(contents);
return ApiResp.respOK(globalConfig.buildPath(xls.getHttpPath()));
}
}

View File

@@ -0,0 +1,162 @@
package com.tiesheng.role.controller;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tiesheng.annotation.role.RoleAuthority;
import com.tiesheng.annotation.token.TokenIgnore;
import com.tiesheng.role.pojos.dao.CoreChartTable;
import com.tiesheng.role.pojos.dao.CoreChartTemplate;
import com.tiesheng.role.pojos.dto.ChartTableEditDTO;
import com.tiesheng.role.pojos.dto.ChartTemplateEditDTO;
import com.tiesheng.role.service.ChartService;
import com.tiesheng.util.exception.ApiException;
import com.tiesheng.util.pojos.ApiResp;
import com.tiesheng.util.pojos.IdDTO;
import com.tiesheng.util.pojos.PageDTO;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;
@RestController
@RequestMapping("/chart/template")
@RoleAuthority(value = "template", group = "chart")
public class ChartTemplateController {
@Resource
ChartService chartService;
/**
* 获取模版列表
*
* @return
*/
@GetMapping("/page")
public ApiResp<List<CoreChartTemplate>> page(PageDTO dto) {
QueryWrapper<CoreChartTemplate> queryWrapper = new QueryWrapper<CoreChartTemplate>()
.eq("is_deleted", 0)
.like(StrUtil.isNotEmpty(dto.getKeyword()), "table_name", dto.getKeyword())
.orderByAsc("sort");
dto.likeColumns(queryWrapper, "name", "table_name", "table_title");
Page<CoreChartTemplate> page = dto.pageObj();
chartService.page(page, queryWrapper);
return ApiResp.respOK(page.getRecords(), page.getTotal());
}
/**
* 获取模版列表
*
* @return
*/
@PostMapping("/edit")
public ApiResp<String> edit(@RequestBody @Valid ChartTemplateEditDTO dto) {
dto.setSField(StrUtil.emptyToDefault(dto.getSField(), ""));
CoreChartTemplate template = BeanUtil.copyProperties(dto, CoreChartTemplate.class);
template.setExts(JSON.toJSONString(dto.getExts()));
chartService.saveOrUpdate(template);
return ApiResp.respOK("");
}
/**
* 获取模版列表
*
* @return
*/
@PostMapping("/del")
public ApiResp<String> del(@RequestBody @Valid IdDTO dto) {
chartService.update(null, new UpdateWrapper<CoreChartTemplate>()
.set("is_deleted", 1)
.eq("id", dto.getId())
.eq("is_deleted", 0)
);
return ApiResp.respOK("");
}
///////////////////////////// 表信息
/**
* 获取模版列表
*
* @return
*/
@GetMapping("/table/list")
public ApiResp<List<CoreChartTable>> tableList(PageDTO dto) {
List<CoreChartTable> list = chartService.getCoreChartTableMapper()
.selectList(new QueryWrapper<CoreChartTable>()
.eq("is_deleted", 0)
.like(StrUtil.isNotEmpty(dto.getKeyword()), "table_name", dto.getKeyword())
);
return ApiResp.respOK(list, list.size());
}
/**
* 获取模版列表
*
* @return
*/
@PostMapping("/table/edit")
public ApiResp<String> tableEdit(@RequestBody @Valid ChartTableEditDTO dto) {
CoreChartTable exist = chartService.getCoreChartTableMapper().selectOne(
new QueryWrapper<CoreChartTable>()
.eq("table_name", dto.getTableName())
.ne(StrUtil.isNotEmpty(dto.getId()), "id", dto.getId())
.last("limit 1")
);
if (exist != null) {
throw new ApiException("不可添加重复的表名");
}
CoreChartTable template = BeanUtil.copyProperties(dto, CoreChartTable.class);
template.setIsDeleted(0);
template.setColumns(JSON.toJSONString(dto.getColumns()));
if (StrUtil.isNotEmpty(dto.getId())) {
chartService.getCoreChartTableMapper().updateById(template);
} else {
chartService.getCoreChartTableMapper().insert(template);
}
return ApiResp.respOK("");
}
/**
* 获取模版列表
*
* @return
*/
@PostMapping("/table/del")
public ApiResp<String> tableDel(@RequestBody @Valid IdDTO dto) {
chartService.getCoreChartTableMapper().update(null, new UpdateWrapper<CoreChartTable>()
.set("is_deleted", 1)
.eq("id", dto.getId())
.eq("is_deleted", 0)
);
return ApiResp.respOK("");
}
/**
* 获取table详情
*
* @return
*/
@GetMapping("/table/info")
@TokenIgnore
public ApiResp<CoreChartTable> getTableInfo(String tableName) {
return ApiResp.respOK(chartService.getCoreChartTableMapper().selectOne(new QueryWrapper<CoreChartTable>()
.eq("is_deleted", 0)
.eq("table_name", tableName)
.last("limit 1")
));
}
}

View File

@@ -0,0 +1,7 @@
package com.tiesheng.role.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tiesheng.role.pojos.dao.CoreChartTable;
public interface CoreChartTableMapper extends BaseMapper<CoreChartTable> {
}

View File

@@ -0,0 +1,27 @@
package com.tiesheng.role.mapper;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tiesheng.role.pojos.dao.CoreChartTemplate;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface CoreChartTemplateMapper extends BaseMapper<CoreChartTemplate> {
/**
* 根据字段查询数据
*
* @param table
* @param xField
* @param where
* @param sField
* @return
*/
List<JSONObject> recordCheck(@Param("table") String table,
@Param("type") String type,
@Param("xField") String xField,
@Param("where") String where,
@Param("sField") String sField,
@Param("groupBy") String groupBy
);
}

View File

@@ -0,0 +1,39 @@
package com.tiesheng.role.pojos.dao;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.tiesheng.util.pojos.DaoBase;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 图表-表信息
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName(value = "core_chart_table")
public class CoreChartTable extends DaoBase {
/**
* 表名
*/
@TableField(value = "`table_name`")
private String tableName;
/**
* 名称
*/
@TableField(value = "table_title")
private String tableTitle;
/**
* 所有字段
*/
@TableField(value = "`columns`")
private String columns;
/**
* 其他说明
*/
@TableField(value = "remark")
private String remark;
}

View File

@@ -0,0 +1,81 @@
package com.tiesheng.role.pojos.dao;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.tiesheng.util.pojos.DaoBase;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 图表-表信息
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName(value = "core_chart_template")
public class CoreChartTemplate extends DaoBase {
/**
* 模版名称
*/
@TableField(value = "`name`")
private String name;
/**
* 表名
*/
@TableField(value = "`table_name`")
private String tableName;
/**
* 名称
*/
@TableField(value = "table_title")
private String tableTitle;
/**
* 统计方式
*/
@TableField(value = "`type`")
private String type;
/**
* X轴字段
*/
@TableField(value = "x_field")
private String xField;
@TableField(value = "x_field_name")
private String xFieldName;
/**
* X轴格式化只有X轴字段为date时有效
*/
@TableField(value = "x_format")
private String xFormat;
/**
* S轴字段
*/
@TableField(value = "s_field")
private String sField;
@TableField(value = "s_field_name")
private String sFieldName;
/**
* 附件条件
*/
@TableField(value = "exts")
private String exts;
/**
* 其他说明
*/
@TableField(value = "remark")
private String remark;
/**
* 排序
*/
@TableField(value = "sort")
private Integer sort;
}

View File

@@ -0,0 +1,33 @@
package com.tiesheng.role.pojos.dto;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size;
import java.util.List;
@Data
public class ChartTableEditDTO {
private String id;
@NotEmpty(message = "请输入【表名】")
private String tableName;
@NotEmpty(message = "请输入【名称】")
private String tableTitle;
@Size(min = 1, message = "请配置【表字段】")
private List<TableColumn> columns;
private String remark;
@Data
public static class TableColumn {
private String key;
private String type;
private String remark;
private String enums;
}
}

View File

@@ -0,0 +1,108 @@
package com.tiesheng.role.pojos.dto;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.annotation.JSONField;
import com.tiesheng.role.pojos.dao.CoreChartTemplate;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@Data
public class ChartTemplateCheck {
private String templateId;
private CoreChartTemplate template;
private String xFormat;
private List<ChartTemplateEditDTO.TemplateExt> exts;
@JSONField(serialize = false)
public String getTableXField() {
String tmpXFormat = StrUtil.emptyToDefault(getXFormat(), getTemplate().getXFormat());
if (StrUtil.isNotEmpty(tmpXFormat)) {
return StrUtil.format("DATE_FORMAT({},'{}')", getTemplate().getXField(), tmpXFormat);
}
return getTemplate().getXField();
}
@JSONField(serialize = false)
public String getTableGroupBy() {
if (StrUtil.isNotEmpty(getTemplate().getSField())) {
return StrUtil.format("{},{}", getTableXField(), getTemplate().getSField());
}
return getTableXField();
}
public String getCountType() {
if (Objects.equals(getTemplate().getType(), "count_1")) {
return "count(1)";
}
return "sum(" + getTemplate().getType() + ")";
}
@JSONField(serialize = false)
public String getWhere() {
if (CollUtil.isEmpty(getExts())) {
setExts(JSON.parseArray(getTemplate().getExts(), ChartTemplateEditDTO.TemplateExt.class));
}
if (CollUtil.isEmpty(getExts())) {
return "";
}
List<String> list = new ArrayList<>();
for (ChartTemplateEditDTO.TemplateExt templateExt : getExts()) {
if (templateExt.isErrorExt()) {
continue;
}
if (Objects.equals(templateExt.getAction(), "eq")) {
list.add(StrUtil.format("{} = '{}'", templateExt.getKey(), templateExt.getValue()));
} else if (Objects.equals(templateExt.getAction(), "ne")) {
list.add(StrUtil.format("{} != '{}'", templateExt.getKey(), templateExt.getValue()));
} else if (Objects.equals(templateExt.getAction(), "btw")) {
List<String> split = StrUtil.split(templateExt.getValue(), ",");
if (split.isEmpty()) {
continue;
}
if (split.size() == 1) {
list.add(StrUtil.format("{} > '{}'", templateExt.getKey(), split.get(0)));
} else {
list.add(StrUtil.format("{} between '{}' and '{}'", templateExt.getKey(), split.get(0), split.get(1)));
}
} else if (Objects.equals(templateExt.getAction(), "nbtw")) {
List<String> split = StrUtil.split(templateExt.getValue(), ",");
if (split.isEmpty()) {
continue;
}
if (split.size() == 1) {
list.add(StrUtil.format("{} < '{}'", templateExt.getKey(), split.get(0)));
} else {
list.add(StrUtil.format("{} not between '{}' and '{}'", templateExt.getKey(), split.get(0), split.get(1)));
}
} else if (Objects.equals(templateExt.getAction(), "in")) {
List<String> split = StrUtil.split(templateExt.getValue(), ",");
if (split.isEmpty()) {
continue;
}
list.add(StrUtil.format("{} in ({})", templateExt.getKey(), split.stream().map(it -> "'" + it + "'")
.collect(Collectors.joining(","))));
} else if (Objects.equals(templateExt.getAction(), "nin")) {
List<String> split = StrUtil.split(templateExt.getValue(), ",");
if (split.isEmpty()) {
continue;
}
list.add(StrUtil.format("{} not in ({})", templateExt.getKey(), split.stream().map(it -> "'" + it + "'")
.collect(Collectors.joining(","))));
}
}
return StrUtil.join(" and ", list);
}
}

View File

@@ -0,0 +1,54 @@
package com.tiesheng.role.pojos.dto;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import java.util.List;
@Data
public class ChartTemplateEditDTO {
private String id;
@NotEmpty(message = "请输入【模版名称】")
private String name;
@NotEmpty(message = "请选择【表名】")
private String tableName;
private String tableTitle;
@NotEmpty(message = "请选择【X轴字段】")
private String xField;
private String xFieldName;
private String xFormat;
private String sField;
private String sFieldName;
private String type;
private List<TemplateExt> exts;
private String remark;
private Integer sort;
@Data
public static class TemplateExt {
private String key;
private String action;
private String value;
/**
* 该数据是否有效
*
* @return
*/
@JSONField(serialize = false)
public boolean isErrorExt() {
return StrUtil.isEmpty(getKey()) || StrUtil.isEmpty(getAction()) || StrUtil.isEmpty(getValue());
}
}
}

View File

@@ -0,0 +1,66 @@
package com.tiesheng.role.pojos.vo;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.tiesheng.role.pojos.dao.CoreChartTemplate;
import lombok.Data;
import java.util.List;
@Data
public class TsTableVO {
private List<TableColumn> columns;
private List<JSONObject> dataSource;
@Data
public static class TableColumn {
private String title;
private String dataIndex;
private String width;
public TableColumn(String title, String dataIndex) {
this.title = title;
this.dataIndex = dataIndex;
}
}
public TsTableVO addHeader(String title, String dataIndex) {
if (getColumns() == null) {
setColumns(CollUtil.newArrayList());
}
getColumns().add(new TableColumn(title, dataIndex));
return this;
}
public TsTableVO addData(JSONObject obj) {
if (getDataSource() == null) {
setDataSource(CollUtil.newArrayList());
}
getDataSource().add(obj);
return this;
}
public static TsTableVO of(CoreChartTemplate template, List<JSONObject> originData) {
TsTableVO tsTableVO = new TsTableVO();
tsTableVO.addHeader(template.getXFieldName(), "xField");
List<String> split = StrUtil.split(template.getSField(), ",");
List<String> sFieldNameList = StrUtil.split(template.getSFieldName(), ",");
if (!split.isEmpty() && split.size() == sFieldNameList.size()) {
int idx = 0;
for (String dataIndex : split) {
tsTableVO.addHeader(CollUtil.get(sFieldNameList, idx), StrUtil.toCamelCase(dataIndex));
idx++;
}
}
tsTableVO.addHeader("统计", "yField");
tsTableVO.setDataSource(originData);
return tsTableVO;
}
}

View File

@@ -0,0 +1,20 @@
package com.tiesheng.role.service;
import com.tiesheng.role.mapper.CoreChartTableMapper;
import com.tiesheng.role.mapper.CoreChartTemplateMapper;
import com.tiesheng.role.pojos.dao.CoreChartTemplate;
import com.tiesheng.util.service.TsServiceBase;
import lombok.Getter;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class ChartService extends TsServiceBase<CoreChartTemplateMapper, CoreChartTemplate> {
@Getter
@Resource
CoreChartTableMapper coreChartTableMapper;
}

View File

@@ -0,0 +1,59 @@
package com.tiesheng.role.util;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.excel.write.style.column.AbstractHeadColumnWidthStyleStrategy;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;
/**
* @author Administrator
*/
public class AliExcelUtil {
/**
* 导出数据
*
* @return
*/
public static HorizontalCellStyleStrategy getCustomStyle() {
// 头的策略
WriteCellStyle headWriteCellStyle = new WriteCellStyle();
WriteFont headWriteFont = new WriteFont();
headWriteFont.setBold(true);
headWriteFont.setFontHeightInPoints((short) 12);
headWriteCellStyle.setWriteFont(headWriteFont);
headWriteCellStyle.setFillBackgroundColor(IndexedColors.ROYAL_BLUE.getIndex());
headWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
// 内容的策略
WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
WriteFont contentWriteFont = new WriteFont();
contentWriteFont.setFontHeightInPoints((short) 11);
contentWriteCellStyle.setWriteFont(contentWriteFont);
contentWriteCellStyle.setWrapped(true);
contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
}
public static class ChatColumnWidthStyleStrategy extends AbstractHeadColumnWidthStyleStrategy {
@Override
protected Integer columnWidth(Head head, Integer integer) {
if (head.getColumnIndex() == 0) {
return 20;
}
return (head.getHeadNameList().get(0).length()) * 2 + 10;
}
}
}

View File

@@ -0,0 +1,43 @@
create table core_chart_table
(
id varchar(50) not null
primary key,
create_time datetime not null,
update_time datetime not null,
is_deleted int default 0 not null,
table_name varchar(100) not null comment '表名',
table_title varchar(500) not null comment '名称',
columns text not null comment '所有字段',
remark text null comment '其他说明'
)
ENGINE = InnoDB
CHARACTER SET = utf8mb4
COLLATE = utf8mb4_general_ci
comment '图表-表信息'
row_format = DYNAMIC;
create table core_chart_template
(
id varchar(50) not null
primary key,
create_time datetime not null,
update_time datetime not null,
is_deleted int default 0 not null,
name varchar(100) not null comment '模版名称',
table_name varchar(100) not null comment '表名',
table_title varchar(100) not null comment '名称',
type varchar(50) default 'count_1' null comment '统计方式',
x_field varchar(100) not null comment 'X轴字段',
x_field_name varchar(500) not null comment 'X轴字段',
x_format varchar(100) null comment 'X轴格式化只有X轴字段为date时有效',
s_field varchar(100) null comment 'S轴字段',
s_field_name varchar(500) null comment 'S轴字段',
exts text null comment '附件条件',
remark text null comment '其他说明',
sort int default 0 null comment '排序'
)
ENGINE = InnoDB
CHARACTER SET = utf8mb4
COLLATE = utf8mb4_general_ci
comment '图表-表信息'
row_format = DYNAMIC;

View File

@@ -0,0 +1,20 @@
<?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.tiesheng.zaxy.alarm.mapper.CoreChartTableMapper">
<resultMap id="BaseResultMap" type="com.tiesheng.zaxy.alarm.pojos.dao.CoreChartTable">
<!--@mbg.generated-->
<!--@Table core_chart_table-->
<id column="id" jdbcType="VARCHAR" property="id" />
<result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
<result column="is_deleted" jdbcType="INTEGER" property="isDeleted" />
<result column="table_name" jdbcType="VARCHAR" property="tableName" />
<result column="table_title" jdbcType="VARCHAR" property="tableTitle" />
<result column="columns" jdbcType="LONGVARCHAR" property="columns" />
<result column="remark" jdbcType="LONGVARCHAR" property="remark" />
</resultMap>
<sql id="Base_Column_List">
<!--@mbg.generated-->
id, create_time, update_time, is_deleted, `table_name`, table_title, `columns`, remark
</sql>
</mapper>

View File

@@ -0,0 +1,46 @@
<?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.tiesheng.zaxy.alarm.mapper.CoreChartTemplateMapper">
<resultMap id="BaseResultMap" type="com.tiesheng.zaxy.alarm.pojos.dao.CoreChartTemplate">
<!--@mbg.generated-->
<!--@Table core_chart_template-->
<id column="id" jdbcType="VARCHAR" property="id" />
<result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
<result column="is_deleted" jdbcType="INTEGER" property="isDeleted" />
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="table_name" jdbcType="VARCHAR" property="tableName" />
<result column="table_title" jdbcType="VARCHAR" property="tableTitle" />
<result column="type" jdbcType="VARCHAR" property="type" />
<result column="x_field" jdbcType="VARCHAR" property="xField" />
<result column="x_field_name" jdbcType="VARCHAR" property="xFieldName" />
<result column="x_format" jdbcType="VARCHAR" property="xFormat" />
<result column="s_field" jdbcType="VARCHAR" property="sField" />
<result column="s_field_name" jdbcType="VARCHAR" property="sFieldName" />
<result column="exts" jdbcType="LONGVARCHAR" property="exts" />
<result column="remark" jdbcType="LONGVARCHAR" property="remark" />
<result column="sort" jdbcType="INTEGER" property="sort" />
</resultMap>
<sql id="Base_Column_List">
<!--@mbg.generated-->
id, create_time, update_time, is_deleted, `name`, `table_name`, table_title, `type`,
x_field, x_field_name, x_format, s_field, s_field_name, exts, remark, sort
</sql>
<select id="recordCheck" resultType="com.alibaba.fastjson.JSONObject">
select ${xField} x_field,
<if test="sField != null and sField != ''">
${sField},
</if>
${type} y_field
from ${table}
where 1 = 1
<if test="where != null and where != ''">
and ${where}
</if>
<if test="groupBy != null and groupBy != ''">
group by ${groupBy}
</if>
order by ${groupBy} asc
</select>
</mapper>

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-parent</artifactId>
<version>2.0.1</version>
<version>2.0.30</version>
</parent>
<artifactId>springboot-database</artifactId>

Binary file not shown.

View File

@@ -1,40 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-parent</artifactId>
<version>2.0.1</version>
</parent>
<artifactId>springboot-encrypt</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-util</artifactId>
</dependency>
<dependency>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-annotation</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -1,10 +0,0 @@
package com.tiesheng.encrypt;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan({
"com.tiesheng.encrypt.**.*",
})
public class EncryptAutoConfigurer {
}

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-parent</artifactId>
<version>2.0.1</version>
<version>2.0.30</version>
</parent>
<artifactId>springboot-login</artifactId>

View File

@@ -1,5 +1,6 @@
package com.tiesheng.login.config;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.tiesheng.annotation.token.TokenIgnore;
@@ -40,7 +41,7 @@ public class TokenWebMvcConfigurer implements WebMvcConfigurer {
resolvers.add(new HandlerMethodArgumentResolver() {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterType().isAssignableFrom(TokenBean.class);
return TokenBean.class.isAssignableFrom(parameter.getParameterType());
}
@Override
@@ -54,7 +55,9 @@ public class TokenWebMvcConfigurer implements WebMvcConfigurer {
TokenIgnore annotation = method.getAnnotation(TokenIgnore.class);
thrExp = annotation == null;
}
return tsTokenConfig.validToken(header, thrExp);
TokenBean tokenBean = tsTokenConfig.validToken(header, thrExp);
return BeanUtil.copyProperties(tokenBean, parameter.getParameterType());
}
});
}

View File

@@ -65,7 +65,7 @@ public class LoginController {
@OperationIgnore
public void uniqueIndex(UniqueIndexDTO dto, HttpServletResponse response) {
if (tsTokenConfig.isValidLoginSign() && !dto.validSign()) {
corePlatformUniqueService.onSignError(response);
corePlatformUniqueService.redirect(null, dto.getTo(), dto.getExtra(), response);
return;
}
@@ -86,7 +86,7 @@ public class LoginController {
public ApiResp<String> uniqueIndex(@RequestBody UniqueIndexDTO dto) {
TokenBean tokenBean = corePlatformUniqueService.login(new DoLoginInfo("web_unique_index",
dto.getNo(), dto.getPlatform(), dto.getInfo()));
if (tokenBean == null || StrUtil.isEmpty(tokenBean.getId())) {
if (!TsTokenConfig.validToken(tokenBean)) {
throw new ApiException("登录失败");
}
return ApiResp.respOK(tokenBean.toToken());
@@ -219,7 +219,7 @@ public class LoginController {
WxminiLoginVo loginVo = new WxminiLoginVo();
loginVo.setOpenid(openid);
if (tokenBean != null) {
if (TsTokenConfig.validToken(tokenBean)) {
loginVo.setToken(tokenBean.toToken());
}
return ApiResp.respOK(loginVo);

View File

@@ -2,6 +2,17 @@ package com.tiesheng.login.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tiesheng.login.pojos.dao.CoreLogLogin;
import org.apache.ibatis.annotations.Param;
public interface CoreLogLoginMapper extends BaseMapper<CoreLogLogin> {
/**
* 获取登录失败的次数
*
* @param ip
* @return
*/
int getLoginErrorTimes(@Param("ip") String ip);
}

View File

@@ -1,5 +1,9 @@
package com.tiesheng.login.pojos;
import com.tiesheng.util.ServletKit;
import javax.servlet.http.HttpServletRequest;
public class DoLoginInfo {
private String appId;
@@ -7,12 +11,16 @@ public class DoLoginInfo {
private String platform;
private String info;
private String extra;
private String loginIp;
public DoLoginInfo(String appId, String unique, String platform, String info) {
this.appId = appId;
this.unique = unique;
this.platform = platform;
this.info = info;
// 设置IP
this.loginIp = ServletKit.getClientIP();
}
///////////////////////////////////////////////////////////////////////////
@@ -58,4 +66,12 @@ public class DoLoginInfo {
public void setExtra(String extra) {
this.extra = extra;
}
public String getLoginIp() {
return loginIp;
}
public void setLoginIp(String loginIp) {
this.loginIp = loginIp;
}
}

View File

@@ -16,13 +16,13 @@ public class CoreLogLogin extends DaoBase {
private String userId;
/**
* 用户id
* 用户姓名
*/
@TableField(value = "user_name")
private String userName;
/**
* ip
* 登录方式
*/
@TableField(value = "platform")
private String platform;
@@ -39,6 +39,18 @@ public class CoreLogLogin extends DaoBase {
@TableField(value = "address")
private String address;
/**
* 登录结果,0否1是
*/
@TableField(value = "`result`")
private Integer result;
/**
* 请求参数
*/
@TableField(value = "params")
private String params;
/**
* 获取用户id
*
@@ -57,18 +69,38 @@ public class CoreLogLogin extends DaoBase {
this.userId = userId;
}
/**
* 获取用户姓名
*
* @return user_name - 用户姓名
*/
public String getUserName() {
return userName;
}
/**
* 设置用户姓名
*
* @param userName 用户姓名
*/
public void setUserName(String userName) {
this.userName = userName;
}
/**
* 获取登录方式
*
* @return platform - 登录方式
*/
public String getPlatform() {
return platform;
}
/**
* 设置登录方式
*
* @param platform 登录方式
*/
public void setPlatform(String platform) {
this.platform = platform;
}
@@ -108,4 +140,40 @@ public class CoreLogLogin extends DaoBase {
public void setAddress(String address) {
this.address = address;
}
/**
* 获取登录结果,0否1是
*
* @return result - 登录结果,0否1是
*/
public Integer getResult() {
return result;
}
/**
* 设置登录结果,0否1是
*
* @param result 登录结果,0否1是
*/
public void setResult(Integer result) {
this.result = result;
}
/**
* 获取请求参数
*
* @return params - 请求参数
*/
public String getParams() {
return params;
}
/**
* 设置请求参数
*
* @param params 请求参数
*/
public void setParams(String params) {
this.params = params;
}
}

View File

@@ -1,23 +1,23 @@
package com.tiesheng.login.service;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.tiesheng.login.mapper.CoreLogLoginMapper;
import com.tiesheng.login.mapper.CorePlatformUniqueMapper;
import com.tiesheng.login.pojos.DoLoginInfo;
import com.tiesheng.login.pojos.RequestUserInfo;
import com.tiesheng.login.pojos.dao.CoreLogLogin;
import com.tiesheng.login.pojos.dao.CorePlatformUnique;
import com.tiesheng.util.ServletKit;
import com.tiesheng.util.config.Ip2regionConfig;
import com.tiesheng.util.config.TsTokenConfig;
import com.tiesheng.util.exception.ApiException;
import com.tiesheng.util.pojos.TokenBean;
import com.tiesheng.util.service.TsCacheService;
import com.tiesheng.util.service.TsServiceBase;
import com.tiesheng.util.service.role.TsAuthorityHandler;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;
@@ -35,9 +35,22 @@ public class CorePlatformUniqueService extends TsServiceBase<CorePlatformUniqueM
TsLoginConfigurer tsLoginConfigurer;
@Transactional(rollbackFor = Exception.class)
/**
* 登录操作
*
* @param loginInfo
* @return
*/
public TokenBean login(DoLoginInfo loginInfo) {
int loginErrorTimes = tsLoginConfigurer.getLoginErrorTimes();
if (loginErrorTimes > 0) {
int currentErrorTimes = coreLogLoginMapper.getLoginErrorTimes(loginInfo.getLoginIp());
if (currentErrorTimes >= loginErrorTimes) {
throw new ApiException("登录失败已达" + loginErrorTimes + "请10分钟后再试");
}
}
CorePlatformUnique platformUnique = getOneByColumn("unique_id", loginInfo.getUnique());
if (platformUnique == null) {
platformUnique = new CorePlatformUnique();
@@ -48,24 +61,32 @@ public class CorePlatformUniqueService extends TsServiceBase<CorePlatformUniqueM
platformUnique.setInfo(loginInfo.getInfo());
saveOrUpdate(platformUnique);
String oldUserId = platformUnique.getUserId();
TokenBean tokenBean = tsLoginConfigurer.login(platformUnique);
if (tokenBean != null) {
TokenBean tokenBean = null;
String errorMsg = null;
try {
tokenBean = tsLoginConfigurer.login(platformUnique);
} catch (Exception e) {
errorMsg = e.getMessage();
}
if (TsTokenConfig.validToken(tokenBean)) {
// 清除授权信息
TsCacheService.of().remove(StrUtil.format(TsAuthorityHandler.CACHE_AUTHORITY,
tokenBean.getRoleId(), tokenBean.getId()));
// 添加登录日志
addLoginLog(platformUnique, tokenBean);
// 更新唯一值
if (!StrUtil.isEmpty(tokenBean.getId()) &&
!Objects.equals(oldUserId, tokenBean.getId())) {
String oldUserId = platformUnique.getUserId();
if (!Objects.equals(oldUserId, tokenBean.getId())) {
platformUnique.setUserId(tokenBean.getId());
saveOrUpdate(platformUnique);
}
}
addLoginLog(tokenBean, loginInfo);
if (StrUtil.isNotEmpty(errorMsg)) {
throw new ApiException(errorMsg);
}
return tokenBean;
@@ -78,40 +99,37 @@ public class CorePlatformUniqueService extends TsServiceBase<CorePlatformUniqueM
* @param bean
*/
public void redirect(TokenBean bean, String to, String extra, HttpServletResponse response) {
tsLoginConfigurer.redirect(bean, to, extra, response);
if (TsTokenConfig.validToken(bean)) {
tsLoginConfigurer.redirect(bean, to, extra, response);
} else {
tsLoginConfigurer.onLoginError(to, response);
}
}
/**
* 签名错误的时候
*/
public void onSignError(HttpServletResponse response) {
tsLoginConfigurer.onSignError(response);
}
///////////////////////////////////////////////////////////////////////////
// 登录日志
///////////////////////////////////////////////////////////////////////////
/**
* 添加登录日志
*
* @param platformUnique
* @param tokenBean
* @param info
*/
public void addLoginLog(CorePlatformUnique platformUnique, TokenBean tokenBean) {
HttpServletRequest request = ServletKit.getRequest();
String ip = ServletKit.getClientIP(request);
public void addLoginLog(TokenBean tokenBean, DoLoginInfo info) {
CoreLogLogin login = new CoreLogLogin();
login.setUserId(tokenBean.getId());
login.setPlatform(platformUnique.getPlatform());
login.setPlatform(info.getPlatform());
login.setParams(JSON.toJSONString(info));
RequestUserInfo requestUserInfo = tsLoginConfigurer.getCachedUserInfo(tokenBean, true);
login.setUserName(requestUserInfo.getName());
if (TsTokenConfig.validToken(tokenBean)) {
RequestUserInfo requestUserInfo = tsLoginConfigurer.getCachedUserInfo(tokenBean, true);
login.setUserId(tokenBean.getId());
login.setUserName(requestUserInfo.getName());
login.setResult(1);
} else {
login.setUserName(info.getUnique());
login.setResult(0);
}
login.setIp(ip);
login.setIp(info.getLoginIp());
login.setAddress(ip2regionConfig.search(login.getIp()));
coreLogLoginMapper.insert(login);
}

View File

@@ -34,9 +34,9 @@ public interface TsLoginConfigurer {
/**
* 签名错误的时候
* 登录失败的时候
*/
default void onSignError(HttpServletResponse response) {
default void onLoginError(String to, HttpServletResponse response) {
ServletKit.write(response, "404", "text");
}
@@ -66,4 +66,14 @@ public interface TsLoginConfigurer {
*/
RequestUserInfo getCurrentUserName(TokenBean userId);
/**
* 获取登录失败的次数默认0次不校验
*
* @return
*/
default int getLoginErrorTimes() {
return 0;
}
}

View File

@@ -17,7 +17,8 @@ CREATE TABLE `core_log_login`
`address` varchar(255) DEFAULT NULL COMMENT 'ip地址',
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4 COMMENT ='日志-登录';
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci COMMENT ='日志-登录';
-- ----------------------------
-- Table structure for core_platform_unique
@@ -35,6 +36,7 @@ CREATE TABLE `core_platform_unique`
`info` text COMMENT '其他参数',
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4 COMMENT ='平台-唯一值';
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci COMMENT ='平台-唯一值';
SET FOREIGN_KEY_CHECKS = 1;

View File

@@ -13,9 +13,21 @@
<result column="platform" jdbcType="VARCHAR" property="platform" />
<result column="ip" jdbcType="VARCHAR" property="ip" />
<result column="address" jdbcType="VARCHAR" property="address" />
<result column="result" jdbcType="INTEGER" property="result" />
<result column="params" jdbcType="LONGVARCHAR" property="params" />
</resultMap>
<sql id="Base_Column_List">
<!--@mbg.generated-->
id, create_time, update_time, is_deleted, user_id, user_name, platform, ip, address
id, create_time, update_time, is_deleted, user_id, user_name, platform, ip, address,
`result`, params
</sql>
<select id="getLoginErrorTimes" resultType="int">
select count(1)
from core_log_login
where ip = #{ip}
and result = 0
and create_time > date_add(now(), interval -10 minute)
</select>
</mapper>

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-parent</artifactId>
<version>2.0.1</version>
<version>2.0.30</version>
</parent>
<artifactId>springboot-message</artifactId>

View File

@@ -99,7 +99,7 @@ public class AliyunSmsSender implements TsMessageSender {
String signature = specialUrlEncode(digest);
queryMap.put("Signature", signature);
String respBody = "";
String respBody;
try {
respBody = OkHttpUtil.get(ENDPOINT + "?Signature=" + signature + sortQueryStringTmp);
} catch (Exception e) {

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-parent</artifactId>
<version>2.0.1</version>
<version>2.0.30</version>
</parent>
<artifactId>springboot-platform</artifactId>

View File

@@ -76,15 +76,16 @@ public class PlatformDingConfig {
request = OkHttpUtil.ofPost(url, body);
}
request = request.newBuilder().header("x-acs-dingtalk-access-token", accessToken).build();
try {
Response response = OkHttpUtil.ofHttpClient().build().newCall(request).execute();
try (Response response = OkHttpUtil.ofHttpClient().build().newCall(request).execute()) {
if (response.isSuccessful() && response.body() != null) {
String rawBody = response.body().string();
DingResponse<T> bean = JSON.parseObject(rawBody, typeReference);
bean.setRawBody(rawBody);
return bean;
} else {
LogFactory.get().info(response.body().string());
if (response.body() != null) {
LogFactory.get().info(response.body().string());
}
}
} catch (Exception e) {
LogFactory.get().error(e);

Binary file not shown.

View File

@@ -1,8 +0,0 @@
package com.tiesheng.poi.pojos;
/**
* @author hao
*/
public interface PoiReadBase {
}

View File

@@ -1,19 +0,0 @@
package com.tiesheng.poi.pojos;
import com.alibaba.excel.annotation.write.style.*;
import com.alibaba.excel.enums.poi.HorizontalAlignmentEnum;
import com.alibaba.excel.enums.poi.VerticalAlignmentEnum;
/**
* @author hao
*/
@HeadRowHeight(24)
@HeadFontStyle(fontHeightInPoints = 13)
@HeadStyle(horizontalAlignment = HorizontalAlignmentEnum.LEFT)
@ContentRowHeight(20)
@ContentFontStyle(fontHeightInPoints = 12)
@ContentStyle(verticalAlignment = VerticalAlignmentEnum.CENTER)
@ColumnWidth(20)
public interface PoiWriteBase {
}

View File

@@ -1,23 +0,0 @@
package com.tiesheng.poi.util;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.listener.ReadListener;
import com.tiesheng.poi.pojos.PoiReadBase;
import java.io.File;
public class PoiReadUtil {
/**
* 读取文件
*
* @param file
* @param readListener
* @return
*/
public static <T extends PoiReadBase> void read(File file, Class<T> tClass, ReadListener<T> readListener) {
EasyExcel.read(file, tClass, readListener).autoTrim(true).headRowNumber(1).sheet().doRead();
}
}

View File

@@ -1,38 +0,0 @@
package com.tiesheng.poi.util;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.annotation.write.style.*;
import com.alibaba.excel.enums.poi.HorizontalAlignmentEnum;
import com.alibaba.excel.enums.poi.VerticalAlignmentEnum;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.tiesheng.poi.pojos.PoiWriteBase;
import java.util.List;
/**
* @author hao
*/
@HeadRowHeight(24)
@HeadFontStyle(fontHeightInPoints = 13)
@HeadStyle(horizontalAlignment = HorizontalAlignmentEnum.LEFT)
@ContentRowHeight(20)
@ContentFontStyle(fontHeightInPoints = 12)
@ContentStyle(verticalAlignment = VerticalAlignmentEnum.CENTER)
@ColumnWidth(20)
public class PoiWriteUtil {
/**
* 导出数据
*
* @param list
* @return
*/
public static <T extends PoiWriteBase> boolean export(List<T> list, Class<T> tClass, String absPath, String sheetName) {
EasyExcel.write(absPath, tClass).excelType(ExcelTypeEnum.XLSX)
.sheet(sheetName)
.doWrite(list);
return true;
}
}

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-parent</artifactId>
<version>2.0.1</version>
<version>2.0.30</version>
</parent>
<artifactId>springboot-role</artifactId>

View File

@@ -3,13 +3,17 @@ package com.tiesheng.role.controller;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tiesheng.role.pojos.dao.CoreRoleAuthority;
import com.tiesheng.role.pojos.dao.CoreRoleGroup;
import com.tiesheng.role.pojos.dao.CoreRoleServer;
import com.tiesheng.role.pojos.dto.OwnerMenuDTO;
import com.tiesheng.role.pojos.dto.OwnerPointDTO;
import com.tiesheng.role.pojos.vo.GroupTypeDTO;
import com.tiesheng.role.pojos.vo.ServiceMenuVO;
import com.tiesheng.role.service.CoreRoleService;
import com.tiesheng.util.pojos.ApiResp;
import com.tiesheng.util.pojos.DaoBase;
import com.tiesheng.util.pojos.TokenBean;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -40,12 +44,21 @@ public class CommRoleController {
List<CoreRoleAuthority> allOwnerMenus = coreRoleService.getOwnerAuthorityLeafList(tokenBean.getId(), tokenBean.getRoleId());
List<String> list = allOwnerMenus.stream().map(CoreRoleAuthority::getService).collect(Collectors.toList());
// 添加公开服务
list.addAll(coreRoleService.getServerMapper().selectList(new QueryWrapper<CoreRoleServer>()
.eq("is_public", 1).eq("is_deleted", 0).eq("is_open", 1)
).stream().map(DaoBase::getId).collect(Collectors.toList()));
// 去除重复
list = CollUtil.distinct(list);
List<CoreRoleServer> roleServerList = new ArrayList<>();
if (CollUtil.isNotEmpty(list)) {
roleServerList = coreRoleService.getServerMapper().selectList(new QueryWrapper<CoreRoleServer>()
.in("id", list)
.eq(CoreRoleServer.IS_DELETED, 0)
.eq("is_open", 1)
.orderByAsc("sort")
);
}
@@ -101,4 +114,24 @@ public class CommRoleController {
}
/**
* 角色、职位列表
*
* @return
*/
@GetMapping("/group")
public ApiResp<List<CoreRoleGroup>> groupPage(@Valid GroupTypeDTO dto) {
QueryWrapper<CoreRoleGroup> queryWrapper = new QueryWrapper<CoreRoleGroup>()
.eq("is_deleted", 0)
.eq(StrUtil.isNotEmpty(dto.getType()), "type", dto.getType())
.orderByAsc("sort");
dto.likeColumns(queryWrapper, "name");
Page<CoreRoleGroup> page = dto.pageObj();
coreRoleService.page(page, queryWrapper);
return ApiResp.respOK(page.getRecords(), page.getTotal());
}
}

View File

@@ -6,6 +6,7 @@ import com.tiesheng.annotation.role.RoleAuthority;
import com.tiesheng.role.pojos.dao.CoreRoleAuthority;
import com.tiesheng.role.pojos.dao.CoreRoleServer;
import com.tiesheng.role.pojos.dto.MenuListDTO;
import com.tiesheng.role.pojos.dto.ServerListDTO;
import com.tiesheng.role.pojos.vo.ServiceMenuVO;
import com.tiesheng.role.service.CoreRoleService;
import com.tiesheng.util.pojos.ApiResp;
@@ -29,10 +30,11 @@ public class RoleServerController {
* @return
*/
@GetMapping("/server/list")
public ApiResp<List<CoreRoleServer>> list() {
public ApiResp<List<CoreRoleServer>> list(ServerListDTO dto) {
return ApiResp.respOK(coreRoleService.getServerMapper().selectList(new QueryWrapper<CoreRoleServer>()
.eq(CoreRoleServer.IS_DELETED, 0)
.eq("is_open", 1)
.eq(StrUtil.isNotEmpty(dto.getIsOpen()), "is_open", dto.getIsOpen())
.orderByAsc("sort")
));
}

View File

@@ -66,6 +66,12 @@ public class CoreRoleServer extends DaoBase {
@TableField(value = "ext3")
private String ext3;
/**
* 是否公开
*/
@TableField(value = "is_public")
private Integer isPublic;
/**
* 获取名称
*
@@ -227,4 +233,22 @@ public class CoreRoleServer extends DaoBase {
public void setExt3(String ext3) {
this.ext3 = ext3;
}
/**
* 获取是否公开
*
* @return is_public - 是否公开
*/
public Integer getIsPublic() {
return isPublic;
}
/**
* 设置是否公开
*
* @param isPublic 是否公开
*/
public void setIsPublic(Integer isPublic) {
this.isPublic = isPublic;
}
}

View File

@@ -30,6 +30,12 @@ public class CoreRoleUser extends DaoBase {
@TableField(value = "type_id")
private String typeId;
/**
* 说明
*/
@TableField(value = "remark")
private String remark;
/**
* 过期时间,无则不过期
*/
@@ -108,6 +114,14 @@ public class CoreRoleUser extends DaoBase {
this.typeId = typeId;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
/**
* 获取过期时间,无则不过期
*
@@ -179,4 +193,4 @@ public class CoreRoleUser extends DaoBase {
public void setExt3(String ext3) {
this.ext3 = ext3;
}
}
}

View File

@@ -0,0 +1,15 @@
package com.tiesheng.role.pojos.dto;
public class ServerListDTO {
private String isOpen;
public String getIsOpen() {
return isOpen;
}
public void setIsOpen(String isOpen) {
this.isOpen = isOpen;
}
}

View File

@@ -138,7 +138,6 @@ public class CoreRoleService extends TsServiceBase<CoreRoleGroupMapper, CoreRole
coreRoleGroupRxMapper.batchInsert(list);
onRoleChange(dto.getId(), "");
}
}
@@ -148,6 +147,9 @@ public class CoreRoleService extends TsServiceBase<CoreRoleGroupMapper, CoreRole
* @param roleUser
*/
public void roleUserUpdate(CoreRoleUser roleUser) {
Validator.validateNotEmpty(roleUser.getType(), "请选择授权方式");
Validator.validateNotEmpty(roleUser.getTypeId(), "请选择授权" + (Objects.equals(roleUser.getType(), "menu") ? "菜单" : "职位"));
if (StrUtil.isNotEmpty(roleUser.getId())) {
coreRoleUserMapper.updateById(roleUser);
} else {

View File

@@ -60,6 +60,7 @@ public class RoleAuthorityHandler implements TsAuthorityHandler {
groupAuthority.setParent(parentId);
groupAuthority.setVersion(version);
groupAuthority.setSource("auto");
groupAuthority.setDeps("[]");
groupAuthority.setId(StrUtil.join("_", groupAuthority.getService(), groupAuthority.getNo()));
list.add(groupAuthority);
}

View File

@@ -24,6 +24,7 @@ create table core_role_authority
ext3 varchar(500) null comment '扩展3'
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci
comment '角色-权限';
create table core_role_group
@@ -43,6 +44,7 @@ create table core_role_group
ext3 varchar(500) null comment '扩展3'
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci
comment '角色-分组';
create table core_role_group_rx
@@ -56,6 +58,7 @@ create table core_role_group_rx
menu_id varchar(50) not null comment '菜单id'
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci
comment '角色-分组-关系';
create table core_role_server
@@ -76,6 +79,7 @@ create table core_role_server
ext3 varchar(500) null comment '扩展3'
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci
comment '角色-服务';
create table core_role_user
@@ -94,6 +98,7 @@ create table core_role_user
ext3 varchar(500) null comment '扩展3'
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci
comment '角色-用户';
alter table core_role_authority
@@ -108,4 +113,7 @@ alter table core_role_authority
alter table core_role_group_rx
add type varchar(10) null comment '关联类型dep-依赖bind-绑定';
alter table core_role_user
add remark varchar(500) null comment '说明' after type_id;
SET FOREIGN_KEY_CHECKS = 1;

View File

@@ -0,0 +1,3 @@
alter table core_role_server
add is_public int default 0 null comment '是否公开';

View File

@@ -17,10 +17,11 @@
<result column="ext1" jdbcType="VARCHAR" property="ext1" />
<result column="ext2" jdbcType="VARCHAR" property="ext2" />
<result column="ext3" jdbcType="VARCHAR" property="ext3" />
<result column="is_public" jdbcType="INTEGER" property="isPublic" />
</resultMap>
<sql id="Base_Column_List">
<!--@mbg.generated-->
id, create_time, update_time, is_deleted, `name`, remark, logo, sort, is_open, link,
ext1, ext2, ext3
ext1, ext2, ext3, is_public
</sql>
</mapper>

View File

@@ -11,6 +11,7 @@
<result column="user_id" jdbcType="VARCHAR" property="userId" />
<result column="type" jdbcType="VARCHAR" property="type" />
<result column="type_id" jdbcType="VARCHAR" property="typeId" />
<result column="remark" jdbcType="VARCHAR" property="remark" />
<result column="expire_time" jdbcType="TIMESTAMP" property="expireTime" />
<result column="ext1" jdbcType="VARCHAR" property="ext1" />
<result column="ext2" jdbcType="VARCHAR" property="ext2" />
@@ -18,7 +19,7 @@
</resultMap>
<sql id="Base_Column_List">
<!--@mbg.generated-->
id, create_time, update_time, is_deleted, user_id, `type`, type_id, expire_time,
id, create_time, update_time, is_deleted, user_id, `type`, type_id, remark, expire_time,
ext1, ext2, ext3
</sql>

Binary file not shown.

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-parent</artifactId>
<version>2.0.1</version>
<version>2.0.30</version>
</parent>
<artifactId>springboot-util</artifactId>
@@ -82,7 +82,7 @@
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
<version>8.0.33</version>
</dependency>
<dependency>
@@ -107,7 +107,7 @@
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15to18</artifactId>
<version>1.68</version>
<version>1.80</version>
</dependency>
<dependency>

View File

@@ -17,7 +17,25 @@ public class ServletKit extends ServletUtil {
public static HttpServletRequest getRequest() {
ServletRequestAttributes attributes = (ServletRequestAttributes)
RequestContextHolder.getRequestAttributes();
return attributes.getRequest();
if (attributes != null) {
return attributes.getRequest();
}
return null;
}
/**
* 获取请求头
*
* @param name 请求头
* @return 请求头
*/
public static String getHeader(String name) {
HttpServletRequest request = getRequest();
if (request == null) {
return "";
}
return getHeader(request, name, "utf-8");
}
/**
@@ -27,6 +45,9 @@ public class ServletKit extends ServletUtil {
*/
public static String getClientIP() {
HttpServletRequest request = getRequest();
if (request == null) {
return "";
}
return getClientIP(request);
}

View File

@@ -1,15 +1,12 @@
package com.tiesheng.util.config;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.symmetric.SM4;
import com.tiesheng.util.ServletKit;
import com.tiesheng.util.exception.ApiException;
import com.tiesheng.util.service.TsCacheService;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@@ -31,6 +28,7 @@ public class EncryptConfig {
private String key = "WmdUzPJXbngVNiaSsQrihg==";
private Integer saltSize = 8;
private boolean body = false;
private String pwdPatten = "^(?![A-Za-z0-9]+$)(?![a-z0-9\\W]+$)(?![A-Za-z\\W]+$)(?![A-Z0-9\\W]+$)[a-zA-Z0-9\\W]{8,}$";
public EncryptConfig() {
sm4 = SmUtil.sm4(Base64.decode(getKey()));
@@ -76,25 +74,13 @@ public class EncryptConfig {
if (StrUtil.isEmpty(salt) || StrUtil.length(salt) != getSaltSize()) {
salt = RandomUtil.randomString(saltSize);
}
if (!passwdComplexity(inputPasswd)) {
throw new ApiException("需要包含数字、大小写字母、特殊符号且长度不低于8位");
if (!inputPasswd.matches(getPwdPatten())) {
throw new ApiException("密码复杂度不够,请重新设置");
}
return encrypt(salt + SecureUtil.sha1(salt + inputPasswd));
}
/**
* 复杂度校验
*
* @param inputPasswd
* @return
*/
public boolean passwdComplexity(String inputPasswd) {
String password = "^(?![A-Za-z0-9]+$)(?![a-z0-9\\W]+$)(?![A-Za-z\\W]+$)(?![A-Z0-9\\W]+$)[a-zA-Z0-9\\W]{8,}$";
return inputPasswd.matches(password);
}
/**
* 密码校验
*
@@ -104,12 +90,6 @@ public class EncryptConfig {
String salt = decrypt(encrypted).substring(0, saltSize);
String inputEncrypted = passwdCreate(inputPasswd, salt);
if (!StrUtil.equals(inputEncrypted, encrypted)) {
String clientIp = "passwdVerify_" + ServletKit.getClientIP();
int num = NumberUtil.parseInt(TsCacheService.of().get(clientIp, -1));
if (num > 5) {
throw new ApiException("登录失败已达6次请10分钟后再试");
}
TsCacheService.of().put(clientIp, String.valueOf(num + 1), 10 * 60);
throw new ApiException("账号或密码错误");
}
}
@@ -142,4 +122,12 @@ public class EncryptConfig {
public void setBody(boolean body) {
this.body = body;
}
public String getPwdPatten() {
return pwdPatten;
}
public void setPwdPatten(String pwdPatten) {
this.pwdPatten = pwdPatten;
}
}

View File

@@ -95,12 +95,13 @@ public class GlobalConfig {
/**
* 重定向
* 构建待版本号的路径
*
* @param htmlDir 资源目录
* @param htmlDir
* @param route
* @return
*/
public void redirect(String htmlDir, String route, HttpServletResponse response) {
public String buildByVersion(String htmlDir, String route) {
if (!StrUtil.endWith(htmlDir, "/")) {
htmlDir = htmlDir + "/";
}
@@ -129,16 +130,32 @@ public class GlobalConfig {
throw new ApiException("无法重定向,请检查资源");
}
CollUtil.sort(versions, (o1, o2) -> -VersionComparator.INSTANCE.compare(o1, o2));
String path = buildPath(String.format("/%s%s/index.html#%s", htmlDir, versions.get(0), route));
response.sendRedirect(path);
return buildPath(String.format("/%s%s/index.html#%s", htmlDir, versions.get(0), route));
} catch (IOException e) {
LogFactory.get().info(e);
}
return "";
}
/**
* 重定向
*
* @param htmlDir 资源目录
* @param route
*/
public void redirectWithVer(String htmlDir, String route, HttpServletResponse response) {
try {
response.sendRedirect(buildByVersion(htmlDir, route));
} catch (Exception ignored) {
}
}
///////////////////////////////////////////////////////////////////////////
// setter\getter
///////////////////////////////////////////////////////////////////////////
/// ////////////////////////////////////////////////////////////////////////
public String getUploadDir() {

View File

@@ -16,7 +16,7 @@ import javax.annotation.PostConstruct;
@ConfigurationProperties(prefix = "tiesheng.ip2region")
public class Ip2regionConfig {
private String dbUrl = "http://git.kepai365.com/tiesheng/repository/raw/master/ipdb/ip2region.xdb";
private String dbUrl = "https://git.tieshengkeji.com/tieshengkeji/Ip2region/raw/branch/main/ip2region.xdb";
private String dbPath = System.getProperty("user.dir") + "/runtime/ip2region/ip2region.xdb";
///////////////////////////////////////////////////////////////////////////

View File

@@ -66,6 +66,16 @@ public class TsTokenConfig {
return validToken(token, thrExp);
}
/**
* token是否有效
*
* @param token
* @return
*/
public static boolean validToken(TokenBean token) {
return token != null && StrUtil.isNotEmpty(token.getId());
}
/**
* 验证token
@@ -100,7 +110,8 @@ public class TsTokenConfig {
///////////////////////////////////////////////////////////////////////////
// setter\getter
///////////////////////////////////////////////////////////////////////////
/// ////////////////////////////////////////////////////////////////////////
public Map<String, TokenBean> getTestMap() {
return testMap;
@@ -141,4 +152,5 @@ public class TsTokenConfig {
public void setValidLoginSign(boolean validLoginSign) {
this.validLoginSign = validLoginSign;
}
}

View File

@@ -384,7 +384,7 @@ public class JWT implements RegisteredPayload<JWT> {
* @since 5.7.4
*/
public boolean validate(long leeway) {
if (false == verify()) {
if (!verify()) {
return false;
}

View File

@@ -2,6 +2,7 @@ package com.tiesheng.util.jwt;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.exceptions.ValidateException;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.tiesheng.util.jwt.signers.JWTSigner;
import com.tiesheng.util.jwt.signers.NoneJWTSigner;
@@ -160,13 +161,13 @@ public class JWTValidator {
}
final String algorithmIdInSigner = signer.getAlgorithmId();
if (false == StrUtil.equals(algorithmId, algorithmIdInSigner)) {
if (!StrUtil.equals(algorithmId, algorithmIdInSigner)) {
throw new ValidateException("Algorithm [{}] defined in header doesn't match to [{}]!"
, algorithmId, algorithmIdInSigner);
}
// 通过算法验证签名是否正确
if (false == jwt.verify(signer)) {
if (!jwt.verify(signer)) {
throw new ValidateException("Signature verification failed!");
}
}
@@ -200,7 +201,10 @@ public class JWTValidator {
validateNotAfter(JWTPayload.NOT_BEFORE, notBefore, now, leeway);
// 检查失效时间(失效时间不能早于当前时间)
final Date expiresAt = payload.getClaimsJson().getDate(JWTPayload.EXPIRES_AT);
// 这里兼容一下旧版本旧版本使用的是10位数的秒作为数据
String string = payload.getClaimsJson().getString(JWTPayload.EXPIRES_AT);
Date expiresAt = StrUtil.length(string) == 10 ? DateUtil.date(NumberUtil.parseLong(string) * 1000L)
: DateUtil.parse(string);
validateNotBefore(JWTPayload.EXPIRES_AT, expiresAt, now, leeway);
// 检查签发时间(签发时间不能晚于当前时间)

View File

@@ -6,9 +6,21 @@ public class IdName {
private String name;
private String extra;
public IdName(String id, String name) {
this.id = id;
this.name = name;
}
public IdName(String id, String name, String extra) {
this.id = id;
this.name = name;
this.extra = extra;
}
///////////////////////////////////////////////////////////////////////////
// setter\getter
///////////////////////////////////////////////////////////////////////////
/// ////////////////////////////////////////////////////////////////////////
public String getId() {
return id;

View File

@@ -1,7 +1,6 @@
package com.tiesheng.util.service;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSON;
import com.tiesheng.util.ServletKit;
@@ -10,6 +9,7 @@ import com.tiesheng.util.service.cache.TsCacheHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Objects;
import java.util.Set;
@Service
@@ -84,7 +84,7 @@ public class TsCacheService {
* 验证 图片验证码
*/
public void verifyCaptcha(String value) {
String captchaKey = ServletUtil.getHeader(ServletKit.getRequest(), "captcha", "utf-8");
String captchaKey = ServletKit.getHeader("captcha");
String cache = get(captchaKey);
if (StrUtil.isEmpty(cache) || !StrUtil.equals(cache, value)) {
throw new ApiException("验证码不正确");
@@ -92,4 +92,20 @@ public class TsCacheService {
remove(captchaKey);
}
/**
* 验证是否重复操作
*
* @param key
* @param value
* @param seconds
*/
public void checkRepeat(String key, String value, int seconds) {
String s = get(key);
if (StrUtil.isNotEmpty(s) && Objects.equals(s, value)) {
throw new ApiException("操作频繁,请稍后再试");
}
put(key, value, seconds);
}
}

View File

@@ -10,7 +10,7 @@ import java.util.Set;
import java.util.stream.Collectors;
@Configuration
@ConditionalOnMissingBean(value = TsCacheHandler.class, ignored = {TsCacheTimedHandler.class, TsCacheTimedHandler.class})
@ConditionalOnMissingBean(value = TsCacheHandler.class, ignored = {TsCacheTimedHandler.class})
public class TsCacheTimedHandler implements TsCacheHandler {
private static volatile TimedCache<String, String> timedCache;

View File

@@ -23,7 +23,8 @@ public class OkHttpUtil {
public static OkHttpClient.Builder ofHttpClient() {
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.connectTimeout(OkHttpConfig.GLOBAL_TIMEOUT, TimeUnit.MILLISECONDS)
.readTimeout(OkHttpConfig.GLOBAL_TIMEOUT, TimeUnit.MILLISECONDS);
.readTimeout(OkHttpConfig.GLOBAL_TIMEOUT, TimeUnit.MILLISECONDS)
.writeTimeout(OkHttpConfig.GLOBAL_TIMEOUT, TimeUnit.MILLISECONDS);
for (Interceptor interceptor : OkHttpConfig.INTERCEPTORS) {
builder.addInterceptor(interceptor);
@@ -32,6 +33,7 @@ public class OkHttpUtil {
return builder;
}
public static Request ofRequest(String method, String url, RequestBody body) {
return new Request.Builder()
.url(url).method(method, body).build();
@@ -57,6 +59,14 @@ public class OkHttpUtil {
return ResponseBody.create(MediaType.parse("application/json; charset=utf-8"), json);
}
public static FormBody ofFormResponse(Map<String, String> form) {
FormBody.Builder formBuilder = new FormBody.Builder();
for (String key : form.keySet()) {
formBuilder.add(key, form.get(key));
}
return formBuilder.build();
}
public static MultipartBody.Builder ofMultipartBody(File file) {
return new MultipartBody.Builder()
.setType(MultipartBody.FORM)
@@ -66,7 +76,8 @@ public class OkHttpUtil {
///////////////////////////////////////////////////////////////////////////
// get请求
///////////////////////////////////////////////////////////////////////////
/// ////////////////////////////////////////////////////////////////////////
public static String get(String urlString) {
return get(urlString, OkHttpConfig.GLOBAL_TIMEOUT);
@@ -83,9 +94,13 @@ public class OkHttpUtil {
}
public static String get(String urlString, int timeout) {
try {
return ofHttpClient().connectTimeout(timeout, TimeUnit.MILLISECONDS)
.build().newCall(ofGet(urlString)).execute().body().string();
try (Response execute = ofHttpClient().connectTimeout(timeout, TimeUnit.MILLISECONDS)
.readTimeout(timeout, TimeUnit.MILLISECONDS)
.writeTimeout(timeout, TimeUnit.MILLISECONDS)
.build().newCall(ofGet(urlString)).execute()) {
if (execute.body() != null) {
return execute.body().string();
}
} catch (IOException ignored) {
}
return null;
@@ -94,18 +109,15 @@ public class OkHttpUtil {
///////////////////////////////////////////////////////////////////////////
// Post请求
///////////////////////////////////////////////////////////////////////////
public static String post(String urlString, Map<String, String> paramMap) {
return post(urlString, paramMap, OkHttpConfig.GLOBAL_TIMEOUT);
/// ////////////////////////////////////////////////////////////////////////
public static String post(String urlString, Map<String, String> formMap) {
return post(urlString, formMap, OkHttpConfig.GLOBAL_TIMEOUT);
}
public static String post(String urlString, Map<String, String> paramMap, int timeout) {
FormBody.Builder formBuilder = new FormBody.Builder();
for (String key : paramMap.keySet()) {
formBuilder.add(key, paramMap.get(key));
}
return post(urlString, formBuilder.build(), timeout);
public static String post(String urlString, Map<String, String> formMap, int timeout) {
return post(urlString, ofFormResponse(formMap), timeout);
}
public static String post(String urlString, JSONObject body) {
@@ -117,9 +129,13 @@ public class OkHttpUtil {
}
public static String post(String urlString, RequestBody body, int timeout) {
try {
return ofHttpClient().connectTimeout(timeout, TimeUnit.MILLISECONDS)
.build().newCall(ofPost(urlString, body)).execute().body().string();
try (Response response = ofHttpClient().connectTimeout(timeout, TimeUnit.MILLISECONDS)
.readTimeout(timeout, TimeUnit.MILLISECONDS)
.writeTimeout(timeout, TimeUnit.MILLISECONDS)
.build().newCall(ofPost(urlString, body)).execute()) {
if (response.body() != null) {
return response.body().string();
}
} catch (IOException ignored) {
}
return null;
@@ -128,18 +144,19 @@ public class OkHttpUtil {
///////////////////////////////////////////////////////////////////////////
// Download下载文件
///////////////////////////////////////////////////////////////////////////
/// ////////////////////////////////////////////////////////////////////////
public static File downloadFile(String url, String destFile) {
return downloadFile(url, FileUtil.file(destFile));
}
public static File downloadFile(String url, File destFile) {
try {
Response response = ofHttpClient()
.connectTimeout(0, TimeUnit.MILLISECONDS)
.readTimeout(0, TimeUnit.MILLISECONDS)
.build().newCall(ofGet(url)).execute();
try (Response response = ofHttpClient()
.connectTimeout(0, TimeUnit.MILLISECONDS)
.readTimeout(0, TimeUnit.MILLISECONDS)
.writeTimeout(0, TimeUnit.MILLISECONDS)
.build().newCall(ofGet(url)).execute()) {
if (response.isSuccessful() && response.body() != null) {
FileUtil.writeFromStream(response.body().byteStream(), destFile);
}
@@ -150,11 +167,11 @@ public class OkHttpUtil {
}
public static byte[] downloadBytes(String url) {
try {
Response response = ofHttpClient()
.connectTimeout(0, TimeUnit.MILLISECONDS)
.readTimeout(0, TimeUnit.MILLISECONDS)
.build().newCall(ofGet(url)).execute();
try (Response response = ofHttpClient()
.connectTimeout(0, TimeUnit.MILLISECONDS)
.readTimeout(0, TimeUnit.MILLISECONDS)
.writeTimeout(0, TimeUnit.MILLISECONDS)
.build().newCall(ofGet(url)).execute()) {
if (response.isSuccessful() && response.body() != null) {
return response.body().bytes();
}

View File

@@ -0,0 +1,140 @@
package com.tiesheng.util.useragent;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ReUtil;
import java.util.List;
import java.util.regex.Pattern;
/**
* 浏览器对象
*
* @author looly
* @since 4.2.1
*/
public class Browser extends UserAgentInfo {
private static final long serialVersionUID = 1L;
/**
* 未知
*/
public static final Browser Unknown = new Browser(NameUnknown, null, null);
/**
* 其它版本
*/
public static final String Other_Version = "[\\/ ]([\\d\\w\\.\\-]+)";
/**
* 支持的浏览器类型
*/
public static final List<Browser> browers = CollUtil.newArrayList(
// 部分特殊浏览器是基于安卓、Iphone等的需要优先判断
// 企业微信 企业微信使用微信浏览器内核,会包含 MicroMessenger 所以要放在前面
new Browser("wxwork", "wxwork", "wxwork\\/([\\d\\w\\.\\-]+)"),
// 微信
new Browser("MicroMessenger", "MicroMessenger", Other_Version),
// 微信小程序
new Browser("miniProgram", "miniProgram", Other_Version),
// QQ浏览器
new Browser("QQBrowser", "MQQBrowser", "MQQBrowser\\/([\\d\\w\\.\\-]+)"),
// 钉钉PC端浏览器
new Browser("DingTalk-win", "dingtalk-win", "DingTalk\\(([\\d\\w\\.\\-]+)\\)"),
// 钉钉内置浏览器
new Browser("DingTalk", "DingTalk", "AliApp\\(DingTalk\\/([\\d\\w\\.\\-]+)\\)"),
// 支付宝内置浏览器
new Browser("Alipay", "AlipayClient", "AliApp\\(AP\\/([\\d\\w\\.\\-]+)\\)"),
// 淘宝内置浏览器
new Browser("Taobao", "taobao", "AliApp\\(TB\\/([\\d\\w\\.\\-]+)\\)"),
// UC浏览器
new Browser("UCBrowser", "UC?Browser", "UC?Browser\\/([\\d\\w\\.\\-]+)"),
// XiaoMi 浏览器
new Browser("MiuiBrowser", "MiuiBrowser|mibrowser", "MiuiBrowser\\/([\\d\\w\\.\\-]+)"),
// 夸克浏览器
new Browser("Quark", "Quark", Other_Version),
// 联想浏览器
new Browser("Lenovo", "SLBrowser", "SLBrowser/([\\d\\w\\.\\-]+)"),
new Browser("MSEdge", "Edge|Edg", "(?:edge|Edg|EdgA)\\/([\\d\\w\\.\\-]+)"),
new Browser("Chrome", "chrome", Other_Version),
new Browser("Firefox", "firefox", Other_Version),
new Browser("IEMobile", "iemobile", Other_Version),
new Browser("Android Browser", "android", "version\\/([\\d\\w\\.\\-]+)"),
new Browser("Safari", "safari", "version\\/([\\d\\w\\.\\-]+)"),
new Browser("Opera", "opera", Other_Version),
new Browser("Konqueror", "konqueror", Other_Version),
new Browser("PS3", "playstation 3", "([\\d\\w\\.\\-]+)\\)\\s*$"),
new Browser("PSP", "playstation portable", "([\\d\\w\\.\\-]+)\\)?\\s*$"),
new Browser("Lotus", "lotus.notes", "Lotus-Notes\\/([\\w.]+)"),
new Browser("Thunderbird", "thunderbird", Other_Version),
new Browser("Netscape", "netscape", Other_Version),
new Browser("Seamonkey", "seamonkey", Other_Version),
new Browser("Outlook", "microsoft.outlook", Other_Version),
new Browser("Evolution", "evolution", Other_Version),
new Browser("MSIE", "msie", "msie ([\\d\\w\\.\\-]+)"),
new Browser("MSIE11", "rv:11", "rv:([\\d\\w\\.\\-]+)"),
new Browser("Gabble", "Gabble", Other_Version),
new Browser("Yammer Desktop", "AdobeAir", "([\\d\\w\\.\\-]+)\\/Yammer"),
new Browser("Yammer Mobile", "Yammer[\\s]+([\\d\\w\\.\\-]+)", "Yammer[\\s]+([\\d\\w\\.\\-]+)"),
new Browser("Apache HTTP Client", "Apache\\\\-HttpClient", "Apache\\-HttpClient\\/([\\d\\w\\.\\-]+)"),
new Browser("BlackBerry", "BlackBerry", "BlackBerry[\\d]+\\/([\\d\\w\\.\\-]+)")
);
/**
* 添加自定义的浏览器类型
*
* @param name 浏览器名称
* @param regex 关键字或表达式
* @param versionRegex 匹配版本的正则
* @since 5.7.4
*/
synchronized public static void addCustomBrowser(String name, String regex, String versionRegex) {
browers.add(new Browser(name, regex, versionRegex));
}
private Pattern versionPattern;
/**
* 构造
*
* @param name 浏览器名称
* @param regex 关键字或表达式
* @param versionRegex 匹配版本的正则
*/
public Browser(String name, String regex, String versionRegex) {
super(name, regex);
if (Other_Version.equals(versionRegex)) {
versionRegex = name + versionRegex;
}
if (null != versionRegex) {
this.versionPattern = Pattern.compile(versionRegex, Pattern.CASE_INSENSITIVE);
}
}
/**
* 获取浏览器版本
*
* @param userAgentString User-Agent字符串
* @return 版本
*/
public String getVersion(String userAgentString) {
if(isUnknown()){
return null;
}
return ReUtil.getGroup1(this.versionPattern, userAgentString);
}
/**
* 是否移动浏览器
*
* @return 是否移动浏览器
*/
public boolean isMobile() {
final String name = this.getName();
return "PSP".equals(name) ||
"Yammer Mobile".equals(name) ||
"Android Browser".equals(name) ||
"IEMobile".equals(name) ||
"MicroMessenger".equals(name) ||
"miniProgram".equals(name) ||
"DingTalk".equals(name);
}
}

View File

@@ -0,0 +1,62 @@
package com.tiesheng.util.useragent;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ReUtil;
import java.util.List;
import java.util.regex.Pattern;
/**
* 引擎对象
*
* @author looly
* @since 4.2.1
*/
public class Engine extends UserAgentInfo {
private static final long serialVersionUID = 1L;
/** 未知 */
public static final Engine Unknown = new Engine(NameUnknown, null);
/**
* 支持的引擎类型
*/
public static final List<Engine> engines = CollUtil.newArrayList(
new Engine("Trident", "trident"),
new Engine("Webkit", "webkit"),
new Engine("Chrome", "chrome"),
new Engine("Opera", "opera"),
new Engine("Presto", "presto"),
new Engine("Gecko", "gecko"),
new Engine("KHTML", "khtml"),
new Engine("Konqueror", "konqueror"),
new Engine("MIDP", "MIDP")
);
private final Pattern versionPattern;
/**
* 构造
*
* @param name 引擎名称
* @param regex 关键字或表达式
*/
public Engine(String name, String regex) {
super(name, regex);
this.versionPattern = Pattern.compile(name + "[/\\- ]([\\d\\w.\\-]+)", Pattern.CASE_INSENSITIVE);
}
/**
* 获取引擎版本
*
* @param userAgentString User-Agent字符串
* @return 版本
* @since 5.7.4
*/
public String getVersion(String userAgentString) {
if(isUnknown()){
return null;
}
return ReUtil.getGroup1(this.versionPattern, userAgentString);
}
}

View File

@@ -0,0 +1,107 @@
package com.tiesheng.util.useragent;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ReUtil;
import java.util.List;
import java.util.regex.Pattern;
/**
* 系统对象
*
* @author looly
* @since 4.2.1
*/
public class OS extends UserAgentInfo {
private static final long serialVersionUID = 1L;
/**
* 未知
*/
public static final OS Unknown = new OS(NameUnknown, null);
/**
* 支持的引擎类型
*/
public static final List<OS> oses = CollUtil.newArrayList(//
new OS("Windows 10 or Windows Server 2016", "windows nt 10\\.0", "windows nt (10\\.0)"),//
new OS("Windows 8.1 or Windows Server 2012R2", "windows nt 6\\.3", "windows nt (6\\.3)"),//
new OS("Windows 8 or Windows Server 2012", "windows nt 6\\.2", "windows nt (6\\.2)"),//
new OS("Windows Vista", "windows nt 6\\.0", "windows nt (6\\.0)"), //
new OS("Windows 7 or Windows Server 2008R2", "windows nt 6\\.1", "windows nt (6\\.1)"), //
new OS("Windows 2003", "windows nt 5\\.2", "windows nt (5\\.2)"), //
new OS("Windows XP", "windows nt 5\\.1", "windows nt (5\\.1)"), //
new OS("Windows 2000", "windows nt 5\\.0", "windows nt (5\\.0)"), //
new OS("Windows Phone", "windows (ce|phone|mobile)( os)?", "windows (?:ce|phone|mobile) (\\d+([._]\\d+)*)"), //
new OS("Windows", "windows"), //
new OS("OSX", "os x (\\d+)[._](\\d+)", "os x (\\d+([._]\\d+)*)"), //
new OS("Android", "Android", "Android (\\d+([._]\\d+)*)"),//
new OS("Android", "XiaoMi|MI\\s+", "\\(X(\\d+([._]\\d+)*)"),//
new OS("Linux", "linux"), //
new OS("Wii", "wii", "wii libnup/(\\d+([._]\\d+)*)"), //
new OS("PS3", "playstation 3", "playstation 3; (\\d+([._]\\d+)*)"), //
new OS("PSP", "playstation portable", "Portable\\); (\\d+([._]\\d+)*)"), //
new OS("iPad", "\\(iPad.*os (\\d+)[._](\\d+)", "\\(iPad.*os (\\d+([._]\\d+)*)"), //
new OS("iPhone", "\\(iPhone.*os (\\d+)[._](\\d+)", "\\(iPhone.*os (\\d+([._]\\d+)*)"), //
new OS("YPod", "iPod touch[\\s\\;]+iPhone.*os (\\d+)[._](\\d+)", "iPod touch[\\s\\;]+iPhone.*os (\\d+([._]\\d+)*)"), //
new OS("YPad", "iPad[\\s\\;]+iPhone.*os (\\d+)[._](\\d+)", "iPad[\\s\\;]+iPhone.*os (\\d+([._]\\d+)*)"), //
new OS("YPhone", "iPhone[\\s\\;]+iPhone.*os (\\d+)[._](\\d+)", "iPhone[\\s\\;]+iPhone.*os (\\d+([._]\\d+)*)"), //
new OS("Symbian", "symbian(os)?"), //
new OS("Darwin", "Darwin\\/([\\d\\w\\.\\-]+)", "Darwin\\/([\\d\\w\\.\\-]+)"), //
new OS("Adobe Air", "AdobeAir\\/([\\d\\w\\.\\-]+)", "AdobeAir\\/([\\d\\w\\.\\-]+)"), //
new OS("Java", "Java[\\s]+([\\d\\w\\.\\-]+)", "Java[\\s]+([\\d\\w\\.\\-]+)")//
);
/**
* 添加自定义的系统类型
*
* @param name 浏览器名称
* @param regex 关键字或表达式
* @param versionRegex 匹配版本的正则
* @since 5.7.4
*/
synchronized public static void addCustomOs(String name, String regex, String versionRegex) {
oses.add(new OS(name, regex, versionRegex));
}
private Pattern versionPattern;
/**
* 构造
*
* @param name 系统名称
* @param regex 关键字或表达式
*/
public OS(String name, String regex) {
this(name, regex, null);
}
/**
* 构造
*
* @param name 系统名称
* @param regex 关键字或表达式
* @param versionRegex 版本正则表达式
* @since 5.7.4
*/
public OS(String name, String regex, String versionRegex) {
super(name, regex);
if (null != versionRegex) {
this.versionPattern = Pattern.compile(versionRegex, Pattern.CASE_INSENSITIVE);
}
}
/**
* 获取浏览器版本
*
* @param userAgentString User-Agent字符串
* @return 版本
*/
public String getVersion(String userAgentString) {
if(isUnknown() || null == this.versionPattern){
// 无版本信息
return null;
}
return ReUtil.getGroup1(this.versionPattern, userAgentString);
}
}

View File

@@ -0,0 +1,147 @@
package com.tiesheng.util.useragent;
import cn.hutool.core.collection.CollUtil;
import java.util.ArrayList;
import java.util.List;
/**
* 平台对象
*
* @author looly
* @since 4.2.1
*/
public class Platform extends UserAgentInfo {
private static final long serialVersionUID = 1L;
/**
* 未知
*/
public static final Platform Unknown = new Platform(NameUnknown, null);
/**
* Iphone
*/
public static final Platform IPHONE = new Platform("iPhone", "iphone");
/**
* ipod
*/
public static final Platform IPOD = new Platform("iPod", "ipod");
/**
* ipad
*/
public static final Platform IPAD = new Platform("iPad", "ipad");
/**
* android
*/
public static final Platform ANDROID = new Platform("Android", "android");
/**
* android
*/
public static final Platform GOOGLE_TV = new Platform("GoogleTV", "googletv");
/**
* Windows Phone
*/
public static final Platform WINDOWS_PHONE = new Platform("Windows Phone", "windows (ce|phone|mobile)( os)?");
/**
* 支持的移动平台类型
*/
public static final List<Platform> mobilePlatforms = CollUtil.newArrayList(//
WINDOWS_PHONE, //
IPAD, //
IPOD, //
IPHONE, //
new Platform("Android", "XiaoMi|MI\\s+"), //
ANDROID, //
GOOGLE_TV, //
new Platform("htcFlyer", "htc_flyer"), //
new Platform("Symbian", "symbian(os)?"), //
new Platform("Blackberry", "blackberry") //
);
/**
* 支持的桌面平台类型
*/
public static final List<Platform> desktopPlatforms = CollUtil.newArrayList(//
new Platform("Windows", "windows"), //
new Platform("Mac", "(macintosh|darwin)"), //
new Platform("Linux", "linux"), //
new Platform("Wii", "wii"), //
new Platform("Playstation", "playstation"), //
new Platform("Java", "java") //
);
/**
* 支持的平台类型
*/
public static final List<Platform> platforms;
static {
platforms = new ArrayList<>(13);
platforms.addAll(mobilePlatforms);
platforms.addAll(desktopPlatforms);
}
/**
* 构造
*
* @param name 平台名称
* @param regex 关键字或表达式
*/
public Platform(String name, String regex) {
super(name, regex);
}
/**
* 是否为移动平台
*
* @return 是否为移动平台
*/
public boolean isMobile() {
return mobilePlatforms.contains(this);
}
/**
* 是否为Iphone或者iPod设备
*
* @return 是否为Iphone或者iPod设备
* @since 5.2.3
*/
public boolean isIPhoneOrIPod() {
return this.equals(IPHONE) || this.equals(IPOD);
}
/**
* 是否为Iphone或者iPod设备
*
* @return 是否为Iphone或者iPod设备
* @since 5.2.3
*/
public boolean isIPad() {
return this.equals(IPAD);
}
/**
* 是否为IOS平台包括IPhone、IPod、IPad
*
* @return 是否为IOS平台包括IPhone、IPod、IPad
* @since 5.2.3
*/
public boolean isIos() {
return isIPhoneOrIPod() || isIPad();
}
/**
* 是否为Android平台包括Android和Google TV
*
* @return 是否为Android平台包括Android和Google TV
* @since 5.2.3
*/
public boolean isAndroid() {
return this.equals(ANDROID) || this.equals(GOOGLE_TV);
}
}

View File

@@ -0,0 +1,196 @@
package com.tiesheng.util.useragent;
import java.io.Serializable;
/**
* User-Agent信息对象
*
* @author looly
* @since 4.2.1
*/
public class UserAgent implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 是否为移动平台
*/
private boolean mobile;
/**
* 浏览器类型
*/
private Browser browser;
/**
* 浏览器版本
*/
private String version;
/**
* 平台类型
*/
private Platform platform;
/**
* 系统类型
*/
private OS os;
/**
* 系统版本
*/
private String osVersion;
/**
* 引擎类型
*/
private Engine engine;
/**
* 引擎版本
*/
private String engineVersion;
/**
* 是否为移动平台
*
* @return 是否为移动平台
*/
public boolean isMobile() {
return mobile;
}
/**
* 设置是否为移动平台
*
* @param mobile 是否为移动平台
*/
public void setMobile(boolean mobile) {
this.mobile = mobile;
}
/**
* 获取浏览器类型
*
* @return 浏览器类型
*/
public Browser getBrowser() {
return browser;
}
/**
* 设置浏览器类型
*
* @param browser 浏览器类型
*/
public void setBrowser(Browser browser) {
this.browser = browser;
}
/**
* 获取平台类型
*
* @return 平台类型
*/
public Platform getPlatform() {
return platform;
}
/**
* 设置平台类型
*
* @param platform 平台类型
*/
public void setPlatform(Platform platform) {
this.platform = platform;
}
/**
* 获取系统类型
*
* @return 系统类型
*/
public OS getOs() {
return os;
}
/**
* 设置系统类型
*
* @param os 系统类型
*/
public void setOs(OS os) {
this.os = os;
}
/**
* 获取系统版本
*
* @return 系统版本
* @since 5.7.4
*/
public String getOsVersion() {
return this.osVersion;
}
/**
* 设置系统版本
*
* @param osVersion 系统版本
* @since 5.7.4
*/
public void setOsVersion(String osVersion) {
this.osVersion = osVersion;
}
/**
* 获取引擎类型
*
* @return 引擎类型
*/
public Engine getEngine() {
return engine;
}
/**
* 设置引擎类型
*
* @param engine 引擎类型
*/
public void setEngine(Engine engine) {
this.engine = engine;
}
/**
* 获取浏览器版本
*
* @return 浏览器版本
*/
public String getVersion() {
return version;
}
/**
* 设置浏览器版本
*
* @param version 浏览器版本
*/
public void setVersion(String version) {
this.version = version;
}
/**
* 获取引擎版本
*
* @return 引擎版本
*/
public String getEngineVersion() {
return engineVersion;
}
/**
* 设置引擎版本
*
* @param engineVersion 引擎版本
*/
public void setEngineVersion(String engineVersion) {
this.engineVersion = engineVersion;
}
}

View File

@@ -0,0 +1,114 @@
package com.tiesheng.util.useragent;
import cn.hutool.core.util.ReUtil;
import java.io.Serializable;
import java.util.regex.Pattern;
/**
* User-agent信息
*
* @author looly
* @since 4.2.1
*/
public class UserAgentInfo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 未知类型
*/
public static final String NameUnknown = "Unknown";
/** 信息名称 */
private final String name;
/** 信息匹配模式 */
private final Pattern pattern;
/**
* 构造
*
* @param name 名字
* @param regex 表达式
*/
public UserAgentInfo(String name, String regex) {
this(name, (null == regex) ? null : Pattern.compile(regex, Pattern.CASE_INSENSITIVE));
}
/**
* 构造
*
* @param name 名字
* @param pattern 匹配模式
*/
public UserAgentInfo(String name, Pattern pattern) {
this.name = name;
this.pattern = pattern;
}
/**
* 获取信息名称
*
* @return 信息名称
*/
public String getName() {
return name;
}
/**
* 获取匹配模式
*
* @return 匹配模式
*/
public Pattern getPattern() {
return pattern;
}
/**
* 指定内容中是否包含匹配此信息的内容
*
* @param content User-Agent字符串
* @return 是否包含匹配此信息的内容
*/
public boolean isMatch(String content) {
return ReUtil.contains(this.pattern, content);
}
/**
* 是否为Unknown
*
* @return 是否为Unknown
*/
public boolean isUnknown() {
return NameUnknown.equals(this.name);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final UserAgentInfo other = (UserAgentInfo) obj;
if (name == null) {
return other.name == null;
} else return name.equals(other.name);
}
@Override
public String toString() {
return this.name;
}
}

View File

@@ -0,0 +1,108 @@
package com.tiesheng.util.useragent;
import cn.hutool.core.util.StrUtil;
/**
* User-Agent解析器
*
* @author looly
* @since 4.2.1
*/
public class UserAgentParser {
/**
* 解析User-Agent
*
* @param userAgentString User-Agent字符串
* @return {@link UserAgent}
*/
public static UserAgent parse(String userAgentString) {
if(StrUtil.isBlank(userAgentString)){
return null;
}
final UserAgent userAgent = new UserAgent();
// 浏览器
final Browser browser = parseBrowser(userAgentString);
userAgent.setBrowser(browser);
userAgent.setVersion(browser.getVersion(userAgentString));
// 浏览器引擎
final Engine engine = parseEngine(userAgentString);
userAgent.setEngine(engine);
userAgent.setEngineVersion(engine.getVersion(userAgentString));
// 操作系统
final OS os = parseOS(userAgentString);
userAgent.setOs(os);
userAgent.setOsVersion(os.getVersion(userAgentString));
// 平台
final Platform platform = parsePlatform(userAgentString);
userAgent.setPlatform(platform);
userAgent.setMobile(platform.isMobile() || browser.isMobile());
return userAgent;
}
/**
* 解析浏览器类型
*
* @param userAgentString User-Agent字符串
* @return 浏览器类型
*/
private static Browser parseBrowser(String userAgentString) {
for (Browser browser : Browser.browers) {
if (browser.isMatch(userAgentString)) {
return browser;
}
}
return Browser.Unknown;
}
/**
* 解析引擎类型
*
* @param userAgentString User-Agent字符串
* @return 引擎类型
*/
private static Engine parseEngine(String userAgentString) {
for (Engine engine : Engine.engines) {
if (engine.isMatch(userAgentString)) {
return engine;
}
}
return Engine.Unknown;
}
/**
* 解析系统类型
*
* @param userAgentString User-Agent字符串
* @return 系统类型
*/
private static OS parseOS(String userAgentString) {
for (OS os : OS.oses) {
if (os.isMatch(userAgentString)) {
return os;
}
}
return OS.Unknown;
}
/**
* 解析平台类型
*
* @param userAgentString User-Agent字符串
* @return 平台类型
*/
private static Platform parsePlatform(String userAgentString) {
for (Platform platform : Platform.platforms) {
if (platform.isMatch(userAgentString)) {
return platform;
}
}
return Platform.Unknown;
}
}

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-parent</artifactId>
<version>2.0.1</version>
<version>2.0.30</version>
</parent>
<artifactId>springboot-web</artifactId>
@@ -30,9 +30,39 @@
<artifactId>spring-boot-starter-json</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
<exclusion>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-el</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-websocket</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>9.0.104</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-el</artifactId>
<version>9.0.104</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-websocket</artifactId>
<version>9.0.104</version>
</dependency>
<!-- aspect -->
<dependency>
<groupId>org.springframework.boot</groupId>
@@ -49,11 +79,6 @@
<artifactId>springboot-database</artifactId>
</dependency>
<dependency>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-poi</artifactId>
</dependency>
<dependency>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-login</artifactId>
@@ -64,11 +89,6 @@
<artifactId>springboot-message</artifactId>
</dependency>
<dependency>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-encrypt</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -1,7 +1,6 @@
package com.tiesheng.web;
import com.tiesheng.database.DatabaseAutoConfigurer;
import com.tiesheng.encrypt.EncryptAutoConfigurer;
import com.tiesheng.message.MessageAutoConfigurer;
import com.tiesheng.platform.PlatformAutoConfigurer;
import com.tiesheng.util.UtilAutoConfigurer;
@@ -21,7 +20,6 @@ import java.lang.annotation.*;
MessageAutoConfigurer.class,
WebAutoConfigurer.class,
DatabaseAutoConfigurer.class,
EncryptAutoConfigurer.class,
PlatformAutoConfigurer.class,
})
public @interface EnableTieshengWeb {

View File

@@ -1,4 +1,4 @@
package com.tiesheng.encrypt.config;
package com.tiesheng.web.config.encrypt;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.CharsetUtil;

View File

@@ -1,4 +1,4 @@
package com.tiesheng.encrypt.config;
package com.tiesheng.web.config.encrypt;
import cn.hutool.core.annotation.AnnotationUtil;
import cn.hutool.log.LogFactory;

View File

@@ -1,6 +1,8 @@
package com.tiesheng.web.config.operation;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
@@ -56,8 +58,14 @@ public class OperationAspect {
@Around("methodArgs()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
// GET请求不处理
DateTime crateTime = DateUtil.date();
HttpServletRequest request = ServletKit.getRequest();
if (request == null) {
return joinPoint.proceed();
}
// GET请求不处理
if (StrUtil.equalsIgnoreCase(request.getMethod(), "GET")) {
return joinPoint.proceed(joinPoint.getArgs());
}
@@ -111,7 +119,7 @@ public class OperationAspect {
}
}
coreLogService.addOperationLog(
coreLogService.addOperationLog(crateTime,
tsTokenConfig.validToken(request, false), title, subject, reqMaps);
return response;

View File

@@ -15,6 +15,7 @@ import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@@ -24,6 +25,7 @@ import java.util.stream.Collectors;
@Aspect
@Component
@ConditionalOnBean(value = TsAuthorityHandler.class)
public class RoleAuthorityAspect {
@Resource

View File

@@ -5,12 +5,13 @@ import cn.hutool.core.date.DateUtil;
import com.tiesheng.annotation.role.RoleAuthority;
import com.tiesheng.util.service.role.TsAuthorityHandler;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
@@ -18,19 +19,15 @@ import java.util.List;
import java.util.Map;
@Service
@ConditionalOnBean(value = TsAuthorityHandler.class)
public class RoleAuthorityCreator implements ApplicationListener<ContextRefreshedEvent> {
@Autowired(required = false)
@Resource
TsAuthorityHandler tsAuthorityHandler;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
if (tsAuthorityHandler == null) {
return;
}
ApplicationContext applicationContext = event.getApplicationContext();
Map<String, Object> beansOfType = applicationContext.getBeansWithAnnotation(RoleAuthority.class);

View File

@@ -62,6 +62,7 @@ public class CommWebController {
QueryWrapper<CoreConfigEnum> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("is_deleted", 0);
queryWrapper.eq("type", dto.getType());
queryWrapper.orderByAsc("type", "sort");
List<CoreConfigEnum> selectList = coreConfigService.getEnumMapper().selectList(queryWrapper);
return ApiResp.respOK(selectList);

View File

@@ -41,6 +41,7 @@ public class ConfigEnumController {
if (!StrUtil.isEmpty(dto.getType())) {
queryWrapper.eq("type", dto.getType());
}
queryWrapper.orderByAsc("type", "sort");
List<CoreConfigEnum> selectList = coreConfigService.getEnumMapper().selectList(queryWrapper);
return ApiResp.respOK(selectList);

View File

@@ -4,7 +4,6 @@ package com.tiesheng.web.controller.system;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tiesheng.annotation.role.RoleAuthority;
import com.tiesheng.util.exception.ApiException;
import com.tiesheng.util.pojos.ApiResp;
import com.tiesheng.util.pojos.PageDTO;
import com.tiesheng.web.pojos.dao.CoreConfigSystem;
@@ -57,21 +56,8 @@ public class ConfigSystemController {
*/
@PostMapping("/system/update")
public ApiResp<String> systemUpdate(@RequestBody ConfigSystemDTO dto) {
CoreConfigSystem configKey = coreConfigService.getOneByColumn("config_key", dto.getConfigKey());
if (configKey == null) {
throw new ApiException("该配置不存在,请检查");
}
if (configKey.getReadOnly() == 1) {
throw new ApiException("该配置只读,不可修改");
}
configKey.setConfigVal(dto.getConfigVal());
configKey.setRemark(dto.getRemark());
configKey.setExtra(dto.getExtra());
tieshengWebConfigurer.configSystemCheck(configKey);
coreConfigService.updateById(configKey);
tieshengWebConfigurer.configSystemCheck(dto);
coreConfigService.updateConfigSystem(dto);
return ApiResp.respOK("");
}

View File

@@ -41,7 +41,7 @@ public class LogApiController {
if (!StrUtil.isEmpty(result)) {
queryWrapper.eq("result", result);
}
dto.likeColumns(queryWrapper, "type", "content");
dto.likeColumns(queryWrapper, "type", "url", "content");
queryWrapper.orderByDesc("create_time");
Page<CoreLogApi> page = dto.pageObj();

View File

@@ -5,8 +5,8 @@ import com.baomidou.mybatisplus.annotation.TableName;
import com.tiesheng.util.pojos.DaoBase;
/**
* 配置-枚举
*/
* 配置-枚举
*/
@TableName(value = "core_config_enum")
public class CoreConfigEnum extends DaoBase {
/**
@@ -21,6 +21,12 @@ public class CoreConfigEnum extends DaoBase {
@TableField(value = "`name`")
private String name;
/**
* 排序
*/
@TableField(value = "sort")
private Integer sort;
/**
* 备注
*/
@@ -69,6 +75,24 @@ public class CoreConfigEnum extends DaoBase {
this.name = name;
}
/**
* 获取排序
*
* @return sort - 排序
*/
public Integer getSort() {
return sort;
}
/**
* 设置排序
*
* @param sort 排序
*/
public void setSort(Integer sort) {
this.sort = sort;
}
/**
* 获取备注
*

View File

@@ -26,6 +26,10 @@ public class ImageCodeDTO {
if (height == null) {
height = 62;
}
width = Math.min(width, 500);
height = Math.min(height, 200);
LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(width, height, 4, lineCount);
lineCaptcha.setGenerator(new RandomGenerator("0123456789", 4));

View File

@@ -1,12 +1,18 @@
package com.tiesheng.web.service;
import cn.hutool.core.util.StrUtil;
import com.tiesheng.util.exception.ApiException;
import com.tiesheng.util.service.TsCacheService;
import com.tiesheng.util.service.TsServiceBase;
import com.tiesheng.web.mapper.CoreConfigEnumMapper;
import com.tiesheng.web.mapper.CoreConfigSystemMapper;
import com.tiesheng.web.pojos.dao.CoreConfigSystem;
import com.tiesheng.util.service.TsServiceBase;
import com.tiesheng.web.pojos.dto.config.ConfigSystemDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* @author hao
*/
@@ -15,6 +21,11 @@ public class CoreConfigService extends TsServiceBase<CoreConfigSystemMapper, Cor
@Autowired
CoreConfigEnumMapper coreConfigEnumMapper;
@Resource
TsCacheService tsCacheService;
private static final String CONFIG_SYSTEM_PREFIX = "CONFIG:SYSTEM:";
public CoreConfigEnumMapper getEnumMapper() {
return coreConfigEnumMapper;
@@ -28,17 +39,51 @@ public class CoreConfigService extends TsServiceBase<CoreConfigSystemMapper, Cor
* @return
*/
public CoreConfigSystem getTextOrCreate(String configKey, String defaultValue) {
CoreConfigSystem oneByColumn = getOneByColumn("config_key", configKey);
CoreConfigSystem oneByColumn = tsCacheService.getObj(CONFIG_SYSTEM_PREFIX + configKey,
CoreConfigSystem.class, -1);
if (oneByColumn != null && StrUtil.isNotEmpty(oneByColumn.getConfigVal())) {
return oneByColumn;
}
oneByColumn = getOneByColumn("config_key", configKey);
if (oneByColumn == null) {
oneByColumn = new CoreConfigSystem();
oneByColumn.setId(configKey);
oneByColumn.setConfigKey(configKey);
oneByColumn.setConfigVal(defaultValue);
oneByColumn.setRemark(defaultValue);
oneByColumn.setRemark(configKey);
oneByColumn.setConfigType(0);
save(oneByColumn);
}
tsCacheService.putObj(CONFIG_SYSTEM_PREFIX + configKey, oneByColumn, 10 * 60);
return oneByColumn;
}
/**
* 更新数据
*
* @param dto
*/
public void updateConfigSystem(ConfigSystemDTO dto) {
CoreConfigSystem coreConfigSystem = getOneByColumn("config_key", dto.getConfigKey());
if (coreConfigSystem == null) {
throw new ApiException("该配置不存在,请检查");
}
if (coreConfigSystem.getReadOnly() == 1) {
throw new ApiException("该配置只读,不可修改");
}
coreConfigSystem.setConfigVal(dto.getConfigVal());
coreConfigSystem.setRemark(dto.getRemark());
coreConfigSystem.setExtra(dto.getExtra());
updateById(coreConfigSystem);
tsCacheService.putObj(CONFIG_SYSTEM_PREFIX + coreConfigSystem.getConfigKey(),
coreConfigSystem, 10 * 60);
}
}

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