Merge remote-tracking branch 'origin/feature/1.8.0-uniapp' into feature/1.8.0-uniapp

This commit is contained in:
sfmind 2022-05-05 19:09:48 +08:00
commit 3e01d5d40c
294 changed files with 28524 additions and 14833 deletions

View File

@ -5,6 +5,10 @@
**「我喜欢写代码,乐此不疲」**
**「我喜欢做开源,以此为乐」**
我 🐶 在上海艰苦奋斗,早中晚在 top3 大厂认真搬砖,夜里为开源做贡献。
如果这个项目让你有所收获,记得 Star 关注哦,这对我是非常不错的鼓励与支持。
## 🐯 平台简介
**芋道**,以开发者为中心,打造中国第一流的快速开发平台,全部开源,个人与企业可 100% 免费使用。
@ -15,6 +19,7 @@
* 前端采用 [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin) ,正在支持 Vue 3 + ElementUI Plus 最新方案。
* 后端采用 Spring Boot、MySQL + MyBatis Plus、Redis + Redisson。
* 数据库可使用 MySQL、Oracle、PostgreSQL、SQL Server、MariaDB、国产达梦 DM、TiDB 等
* 权限认证使用 Spring Security & Token & Redis支持多终端、多种用户的认证系统。
* 支持加载动态权限菜单,按钮级别权限控制,本地缓存提升性能。
* 支持 SaaS 多租户系统,可自定义每个租户的权限,提供透明化的多租户底层封装。

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

3
sql/db2/README.md Normal file
View File

@ -0,0 +1,3 @@
暂未适配 IBM DB2 数据库,如果你有需要,可以微信联系 wangwenbin-server 一起建设。
你需要把表结构与数据导入到 DM 数据库,我来测试与适配代码。

3
sql/dm/README.md Normal file
View File

@ -0,0 +1,3 @@
暂未适配国产 DM 数据库,如果你有需要,可以微信联系 wangwenbin-server 一起建设。
你需要把表结构与数据导入到 DM 数据库,我来测试与适配代码。

2471
sql/mysql/ruoyi-vue-pro.sql Normal file

File diff suppressed because it is too large Load Diff

5560
sql/oracle/ruoyi-vue-pro.sql Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,288 +0,0 @@
/*
Navicat Premium Data Transfer
Source Server : 127.0.0.1
Source Server Type : MySQL
Source Server Version : 80026
Source Host : localhost:3306
Source Schema : ruoyi-vue-pro
Target Server Type : MySQL
Target Server Version : 80026
File Encoding : 65001
Date: 05/02/2022 00:50:30
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for QRTZ_BLOB_TRIGGERS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_BLOB_TRIGGERS`;
CREATE TABLE `QRTZ_BLOB_TRIGGERS` (
`SCHED_NAME` varchar(120) COLLATE utf8mb4_unicode_ci NOT NULL,
`TRIGGER_NAME` varchar(190) COLLATE utf8mb4_unicode_ci NOT NULL,
`TRIGGER_GROUP` varchar(190) COLLATE utf8mb4_unicode_ci NOT NULL,
`BLOB_DATA` blob,
PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
KEY `SCHED_NAME` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
CONSTRAINT `qrtz_blob_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ----------------------------
-- Records of QRTZ_BLOB_TRIGGERS
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for QRTZ_CALENDARS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_CALENDARS`;
CREATE TABLE `QRTZ_CALENDARS` (
`SCHED_NAME` varchar(120) COLLATE utf8mb4_unicode_ci NOT NULL,
`CALENDAR_NAME` varchar(190) COLLATE utf8mb4_unicode_ci NOT NULL,
`CALENDAR` blob NOT NULL,
PRIMARY KEY (`SCHED_NAME`,`CALENDAR_NAME`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ----------------------------
-- Records of QRTZ_CALENDARS
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for QRTZ_CRON_TRIGGERS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_CRON_TRIGGERS`;
CREATE TABLE `QRTZ_CRON_TRIGGERS` (
`SCHED_NAME` varchar(120) COLLATE utf8mb4_unicode_ci NOT NULL,
`TRIGGER_NAME` varchar(190) COLLATE utf8mb4_unicode_ci NOT NULL,
`TRIGGER_GROUP` varchar(190) COLLATE utf8mb4_unicode_ci NOT NULL,
`CRON_EXPRESSION` varchar(120) COLLATE utf8mb4_unicode_ci NOT NULL,
`TIME_ZONE_ID` varchar(80) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
CONSTRAINT `qrtz_cron_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ----------------------------
-- Records of QRTZ_CRON_TRIGGERS
-- ----------------------------
BEGIN;
INSERT INTO `QRTZ_CRON_TRIGGERS` VALUES ('schedulerName', 'payNotifyJob', 'DEFAULT', '* * * * * ?', 'Asia/Shanghai');
INSERT INTO `QRTZ_CRON_TRIGGERS` VALUES ('schedulerName', 'userSessionTimeoutJob', 'DEFAULT', '0 * * * * ? *', 'Asia/Shanghai');
COMMIT;
-- ----------------------------
-- Table structure for QRTZ_FIRED_TRIGGERS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_FIRED_TRIGGERS`;
CREATE TABLE `QRTZ_FIRED_TRIGGERS` (
`SCHED_NAME` varchar(120) COLLATE utf8mb4_unicode_ci NOT NULL,
`ENTRY_ID` varchar(95) COLLATE utf8mb4_unicode_ci NOT NULL,
`TRIGGER_NAME` varchar(190) COLLATE utf8mb4_unicode_ci NOT NULL,
`TRIGGER_GROUP` varchar(190) COLLATE utf8mb4_unicode_ci NOT NULL,
`INSTANCE_NAME` varchar(190) COLLATE utf8mb4_unicode_ci NOT NULL,
`FIRED_TIME` bigint NOT NULL,
`SCHED_TIME` bigint NOT NULL,
`PRIORITY` int NOT NULL,
`STATE` varchar(16) COLLATE utf8mb4_unicode_ci NOT NULL,
`JOB_NAME` varchar(190) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`JOB_GROUP` varchar(190) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`IS_NONCONCURRENT` varchar(1) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`REQUESTS_RECOVERY` varchar(1) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`SCHED_NAME`,`ENTRY_ID`),
KEY `IDX_QRTZ_FT_TRIG_INST_NAME` (`SCHED_NAME`,`INSTANCE_NAME`),
KEY `IDX_QRTZ_FT_INST_JOB_REQ_RCVRY` (`SCHED_NAME`,`INSTANCE_NAME`,`REQUESTS_RECOVERY`),
KEY `IDX_QRTZ_FT_J_G` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`),
KEY `IDX_QRTZ_FT_JG` (`SCHED_NAME`,`JOB_GROUP`),
KEY `IDX_QRTZ_FT_T_G` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
KEY `IDX_QRTZ_FT_TG` (`SCHED_NAME`,`TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ----------------------------
-- Records of QRTZ_FIRED_TRIGGERS
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for QRTZ_JOB_DETAILS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_JOB_DETAILS`;
CREATE TABLE `QRTZ_JOB_DETAILS` (
`SCHED_NAME` varchar(120) COLLATE utf8mb4_unicode_ci NOT NULL,
`JOB_NAME` varchar(190) COLLATE utf8mb4_unicode_ci NOT NULL,
`JOB_GROUP` varchar(190) COLLATE utf8mb4_unicode_ci NOT NULL,
`DESCRIPTION` varchar(250) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`JOB_CLASS_NAME` varchar(250) COLLATE utf8mb4_unicode_ci NOT NULL,
`IS_DURABLE` varchar(1) COLLATE utf8mb4_unicode_ci NOT NULL,
`IS_NONCONCURRENT` varchar(1) COLLATE utf8mb4_unicode_ci NOT NULL,
`IS_UPDATE_DATA` varchar(1) COLLATE utf8mb4_unicode_ci NOT NULL,
`REQUESTS_RECOVERY` varchar(1) COLLATE utf8mb4_unicode_ci NOT NULL,
`JOB_DATA` blob,
PRIMARY KEY (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`),
KEY `IDX_QRTZ_J_REQ_RECOVERY` (`SCHED_NAME`,`REQUESTS_RECOVERY`),
KEY `IDX_QRTZ_J_GRP` (`SCHED_NAME`,`JOB_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ----------------------------
-- Records of QRTZ_JOB_DETAILS
-- ----------------------------
BEGIN;
INSERT INTO `QRTZ_JOB_DETAILS` VALUES ('schedulerName', 'payNotifyJob', 'DEFAULT', NULL, 'cn.iocoder.yudao.framework.quartz.core.handler.JobHandlerInvoker', '0', '1', '1', '0', 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000027400064A4F425F49447372000E6A6176612E6C616E672E4C6F6E673B8BE490CC8F23DF0200014A000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B020000787000000000000000057400104A4F425F48414E444C45525F4E414D4574000C7061794E6F746966794A6F627800);
INSERT INTO `QRTZ_JOB_DETAILS` VALUES ('schedulerName', 'userSessionTimeoutJob', 'DEFAULT', NULL, 'cn.iocoder.yudao.framework.quartz.core.handler.JobHandlerInvoker', '0', '1', '1', '0', 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000027400064A4F425F49447372000E6A6176612E6C616E672E4C6F6E673B8BE490CC8F23DF0200014A000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B0200007870000000000000000D7400104A4F425F48414E444C45525F4E414D457400157573657253657373696F6E54696D656F75744A6F627800);
COMMIT;
-- ----------------------------
-- Table structure for QRTZ_LOCKS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_LOCKS`;
CREATE TABLE `QRTZ_LOCKS` (
`SCHED_NAME` varchar(120) COLLATE utf8mb4_unicode_ci NOT NULL,
`LOCK_NAME` varchar(40) COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (`SCHED_NAME`,`LOCK_NAME`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ----------------------------
-- Records of QRTZ_LOCKS
-- ----------------------------
BEGIN;
INSERT INTO `QRTZ_LOCKS` VALUES ('schedulerName', 'STATE_ACCESS');
INSERT INTO `QRTZ_LOCKS` VALUES ('schedulerName', 'TRIGGER_ACCESS');
COMMIT;
-- ----------------------------
-- Table structure for QRTZ_PAUSED_TRIGGER_GRPS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_PAUSED_TRIGGER_GRPS`;
CREATE TABLE `QRTZ_PAUSED_TRIGGER_GRPS` (
`SCHED_NAME` varchar(120) COLLATE utf8mb4_unicode_ci NOT NULL,
`TRIGGER_GROUP` varchar(190) COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (`SCHED_NAME`,`TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ----------------------------
-- Records of QRTZ_PAUSED_TRIGGER_GRPS
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for QRTZ_SCHEDULER_STATE
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_SCHEDULER_STATE`;
CREATE TABLE `QRTZ_SCHEDULER_STATE` (
`SCHED_NAME` varchar(120) COLLATE utf8mb4_unicode_ci NOT NULL,
`INSTANCE_NAME` varchar(190) COLLATE utf8mb4_unicode_ci NOT NULL,
`LAST_CHECKIN_TIME` bigint NOT NULL,
`CHECKIN_INTERVAL` bigint NOT NULL,
PRIMARY KEY (`SCHED_NAME`,`INSTANCE_NAME`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ----------------------------
-- Records of QRTZ_SCHEDULER_STATE
-- ----------------------------
BEGIN;
INSERT INTO `QRTZ_SCHEDULER_STATE` VALUES ('schedulerName', 'Yunai.local1635571630493', 1635572537879, 15000);
COMMIT;
-- ----------------------------
-- Table structure for QRTZ_SIMPLE_TRIGGERS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_SIMPLE_TRIGGERS`;
CREATE TABLE `QRTZ_SIMPLE_TRIGGERS` (
`SCHED_NAME` varchar(120) COLLATE utf8mb4_unicode_ci NOT NULL,
`TRIGGER_NAME` varchar(190) COLLATE utf8mb4_unicode_ci NOT NULL,
`TRIGGER_GROUP` varchar(190) COLLATE utf8mb4_unicode_ci NOT NULL,
`REPEAT_COUNT` bigint NOT NULL,
`REPEAT_INTERVAL` bigint NOT NULL,
`TIMES_TRIGGERED` bigint NOT NULL,
PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
CONSTRAINT `qrtz_simple_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ----------------------------
-- Records of QRTZ_SIMPLE_TRIGGERS
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for QRTZ_SIMPROP_TRIGGERS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_SIMPROP_TRIGGERS`;
CREATE TABLE `QRTZ_SIMPROP_TRIGGERS` (
`SCHED_NAME` varchar(120) COLLATE utf8mb4_unicode_ci NOT NULL,
`TRIGGER_NAME` varchar(190) COLLATE utf8mb4_unicode_ci NOT NULL,
`TRIGGER_GROUP` varchar(190) COLLATE utf8mb4_unicode_ci NOT NULL,
`STR_PROP_1` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`STR_PROP_2` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`STR_PROP_3` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`INT_PROP_1` int DEFAULT NULL,
`INT_PROP_2` int DEFAULT NULL,
`LONG_PROP_1` bigint DEFAULT NULL,
`LONG_PROP_2` bigint DEFAULT NULL,
`DEC_PROP_1` decimal(13,4) DEFAULT NULL,
`DEC_PROP_2` decimal(13,4) DEFAULT NULL,
`BOOL_PROP_1` varchar(1) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`BOOL_PROP_2` varchar(1) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
CONSTRAINT `qrtz_simprop_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ----------------------------
-- Records of QRTZ_SIMPROP_TRIGGERS
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for QRTZ_TRIGGERS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_TRIGGERS`;
CREATE TABLE `QRTZ_TRIGGERS` (
`SCHED_NAME` varchar(120) COLLATE utf8mb4_unicode_ci NOT NULL,
`TRIGGER_NAME` varchar(190) COLLATE utf8mb4_unicode_ci NOT NULL,
`TRIGGER_GROUP` varchar(190) COLLATE utf8mb4_unicode_ci NOT NULL,
`JOB_NAME` varchar(190) COLLATE utf8mb4_unicode_ci NOT NULL,
`JOB_GROUP` varchar(190) COLLATE utf8mb4_unicode_ci NOT NULL,
`DESCRIPTION` varchar(250) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`NEXT_FIRE_TIME` bigint DEFAULT NULL,
`PREV_FIRE_TIME` bigint DEFAULT NULL,
`PRIORITY` int DEFAULT NULL,
`TRIGGER_STATE` varchar(16) COLLATE utf8mb4_unicode_ci NOT NULL,
`TRIGGER_TYPE` varchar(8) COLLATE utf8mb4_unicode_ci NOT NULL,
`START_TIME` bigint NOT NULL,
`END_TIME` bigint DEFAULT NULL,
`CALENDAR_NAME` varchar(190) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`MISFIRE_INSTR` smallint DEFAULT NULL,
`JOB_DATA` blob,
PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
KEY `IDX_QRTZ_T_J` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`),
KEY `IDX_QRTZ_T_JG` (`SCHED_NAME`,`JOB_GROUP`),
KEY `IDX_QRTZ_T_C` (`SCHED_NAME`,`CALENDAR_NAME`),
KEY `IDX_QRTZ_T_G` (`SCHED_NAME`,`TRIGGER_GROUP`),
KEY `IDX_QRTZ_T_STATE` (`SCHED_NAME`,`TRIGGER_STATE`),
KEY `IDX_QRTZ_T_N_STATE` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`,`TRIGGER_STATE`),
KEY `IDX_QRTZ_T_N_G_STATE` (`SCHED_NAME`,`TRIGGER_GROUP`,`TRIGGER_STATE`),
KEY `IDX_QRTZ_T_NEXT_FIRE_TIME` (`SCHED_NAME`,`NEXT_FIRE_TIME`),
KEY `IDX_QRTZ_T_NFT_ST` (`SCHED_NAME`,`TRIGGER_STATE`,`NEXT_FIRE_TIME`),
KEY `IDX_QRTZ_T_NFT_MISFIRE` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`),
KEY `IDX_QRTZ_T_NFT_ST_MISFIRE` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`,`TRIGGER_STATE`),
KEY `IDX_QRTZ_T_NFT_ST_MISFIRE_GRP` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`,`TRIGGER_GROUP`,`TRIGGER_STATE`),
CONSTRAINT `qrtz_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) REFERENCES `QRTZ_JOB_DETAILS` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ----------------------------
-- Records of QRTZ_TRIGGERS
-- ----------------------------
BEGIN;
INSERT INTO `QRTZ_TRIGGERS` VALUES ('schedulerName', 'payNotifyJob', 'DEFAULT', 'payNotifyJob', 'DEFAULT', NULL, 1635572540000, 1635572539000, 5, 'WAITING', 'CRON', 1635294882000, 0, NULL, 0, 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000037400114A4F425F48414E444C45525F504152414D707400124A4F425F52455452595F494E54455256414C737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000078700000000074000F4A4F425F52455452595F434F554E5471007E000B7800);
INSERT INTO `QRTZ_TRIGGERS` VALUES ('schedulerName', 'userSessionTimeoutJob', 'DEFAULT', 'userSessionTimeoutJob', 'DEFAULT', NULL, 1643993400000, -1, 5, 'WAITING', 'CRON', 1643993386000, 0, NULL, 0, 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000037400114A4F425F48414E444C45525F504152414D707400124A4F425F52455452595F494E54455256414C737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B0200007870000007D074000F4A4F425F52455452595F434F554E547371007E0009000000037800);
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -25,6 +25,7 @@
<mysql.version>5.1.46</mysql.version>
<druid.version>1.2.8</druid.version>
<mybatis-plus.version>3.4.3.4</mybatis-plus.version>
<mybatis-plus-generator.version>3.5.2</mybatis-plus-generator.version>
<dynamic-datasource.version>3.5.0</dynamic-datasource.version>
<redisson.version>3.17.0</redisson.version>
<!-- Config 配置中心相关 -->
@ -45,6 +46,7 @@
<activiti.version>7.1.0.M6</activiti.version>
<flowable.version>6.7.0</flowable.version>
<!-- 工具类相关 -->
<jasypt-spring-boot-starter.version>3.0.4</jasypt-spring-boot-starter.version>
<lombok.version>1.18.20</lombok.version>
<mapstruct.version>1.4.1.Final</mapstruct.version>
<hutool.version>5.6.1</hutool.version>
@ -192,6 +194,11 @@
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId> <!-- 代码生成器,使用它解析表结构 -->
<version>${mybatis-plus-generator.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId> <!-- 多数据源 -->
@ -428,6 +435,12 @@
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId> <!-- 加解密 -->
<version>${jasypt-spring-boot-starter.version}</version>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-excel</artifactId>

View File

@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;
import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig;
import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayQrPayClient;
import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayWapPayClient;
import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXNativePayClient;
import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig;
import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPubPayClient;
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
@ -63,6 +64,7 @@ public class PayClientFactoryImpl implements PayClientFactory {
case WX_PUB: return (AbstractPayClient<Config>) new WXPubPayClient(channelId, (WXPayClientConfig) config);
case WX_LITE: return (AbstractPayClient<Config>) new WXPubPayClient(channelId, (WXPayClientConfig) config);
case WX_APP: return (AbstractPayClient<Config>) new WXPubPayClient(channelId, (WXPayClientConfig) config);
case WX_NATIVE: return (AbstractPayClient<Config>) new WXNativePayClient(channelId, (WXPayClientConfig) config);
case ALIPAY_WAP: return (AbstractPayClient<Config>) new AlipayWapPayClient(channelId, (AlipayPayClientConfig) config);
case ALIPAY_QR: return (AbstractPayClient<Config>) new AlipayQrPayClient(channelId, (AlipayPayClientConfig) config);
case ALIPAY_APP: return (AbstractPayClient<Config>) new AlipayQrPayClient(channelId, (AlipayPayClientConfig) config);

View File

@ -18,6 +18,7 @@ import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
@ -54,7 +55,8 @@ public abstract class AbstractAlipayClient extends AbstractPayClient<AlipayPayCl
*/
@Override
public PayOrderNotifyRespDTO parseOrderNotify(PayNotifyDataDTO data) throws Exception {
Map<String, String> params = data.getParams();
Map<String, String> params = strToMap(data.getBody());
return PayOrderNotifyRespDTO.builder().orderExtensionNo(params.get("out_trade_no"))
.channelOrderNo(params.get("trade_no")).channelUserId(params.get("seller_id"))
.tradeStatus(params.get("trade_status"))
@ -64,7 +66,7 @@ public abstract class AbstractAlipayClient extends AbstractPayClient<AlipayPayCl
@Override
public PayRefundNotifyDTO parseRefundNotify(PayNotifyDataDTO notifyData) {
Map<String, String> params = notifyData.getParams();
Map<String, String> params = strToMap(notifyData.getBody());
PayRefundNotifyDTO notifyDTO = PayRefundNotifyDTO.builder().channelOrderNo(params.get("trade_no"))
.tradeNo(params.get("out_trade_no"))
.reqNo(params.get("out_biz_no"))
@ -128,4 +130,17 @@ public abstract class AbstractAlipayClient extends AbstractPayClient<AlipayPayCl
}
}
public static Map<String, String> strToMap(String s) {
Map<String, String> stringStringMap = new HashMap<>();
//调整时间格式
String s3 = s.replaceAll("%3A", ":");
//获取map
String s4 = s3.replace("+", " ");
String[] split = s4.split("&");
for (String s1 : split) {
String[] split1 = s1.split("=");
stringStringMap.put(split1[0], split1[1]);
}
return stringStringMap;
}
}

View File

@ -0,0 +1,141 @@
package cn.iocoder.yudao.framework.pay.core.client.impl.wx;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.util.io.FileUtils;
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
import cn.iocoder.yudao.framework.pay.core.client.PayCommonResult;
import cn.iocoder.yudao.framework.pay.core.client.dto.*;
import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.order.WxPayNativeOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request;
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import lombok.extern.slf4j.Slf4j;
import java.util.Objects;
import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
import static cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXCodeMapping.CODE_SUCCESS;
import static cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXCodeMapping.MESSAGE_SUCCESS;
@Slf4j
public class WXNativePayClient extends AbstractPayClient<WXPayClientConfig> {
private WxPayService client;
public WXNativePayClient(Long channelId, WXPayClientConfig config) {
super(channelId, PayChannelEnum.WX_NATIVE.getCode(), config, new WXCodeMapping());
}
@Override
protected void doInit() {
WxPayConfig payConfig = new WxPayConfig();
BeanUtil.copyProperties(config, payConfig, "keyContent");
payConfig.setTradeType(WxPayConstants.TradeType.NATIVE); // 设置使用 native 支付方式
// if (StrUtil.isNotEmpty(config.getKeyContent())) {
// payConfig.setKeyContent(config.getKeyContent().getBytes(StandardCharsets.UTF_8));
// }
if (StrUtil.isNotEmpty(config.getPrivateKeyContent())) {
// weixin-pay-java 存在 BUG无法直接设置内容所以创建临时文件来解决
payConfig.setPrivateKeyPath(FileUtils.createTempFile(config.getPrivateKeyContent()).getPath());
}
if (StrUtil.isNotEmpty(config.getPrivateCertContent())) {
// weixin-pay-java 存在 BUG无法直接设置内容所以创建临时文件来解决
payConfig.setPrivateCertPath(FileUtils.createTempFile(config.getPrivateCertContent()).getPath());
}
// 真实客户端
this.client = new WxPayServiceImpl();
client.setConfig(payConfig);
}
@Override
public PayCommonResult<String> doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) {
// 这里原生的返回的是支付的 url 所以直接使用string接收
//"invokeResponse": "weixin://wxpay/bizpayurl?pr=EGYAem7zz"
String responseV3;
try {
switch (config.getApiVersion()) {
case WXPayClientConfig.API_VERSION_V2:
responseV3 = unifiedOrderV2(reqDTO).getCodeUrl();
break;
case WXPayClientConfig.API_VERSION_V3:
responseV3 = this.unifiedOrderV3(reqDTO);
break;
default:
throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));
}
} catch (WxPayException e) {
log.error("[unifiedOrder][request({}) 发起支付失败,原因({})]", toJsonString(reqDTO), e);
return PayCommonResult.build(ObjectUtils.defaultIfNull(e.getErrCode(), e.getReturnCode(), "CustomErrorCode"),
ObjectUtils.defaultIfNull(e.getErrCodeDes(), e.getCustomErrorMsg()), null, codeMapping);
}
return PayCommonResult.build(CODE_SUCCESS, MESSAGE_SUCCESS, responseV3, codeMapping);
}
private WxPayNativeOrderResult unifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) throws WxPayException {
//前端
String trade_type = reqDTO.getChannelExtras().get("trade_type");
// 构建 WxPayUnifiedOrderRequest 对象
WxPayUnifiedOrderRequest request = WxPayUnifiedOrderRequest
.newBuilder()
.outTradeNo(reqDTO.getMerchantOrderId())
.body(reqDTO.getBody())
.totalFee(reqDTO.getAmount().intValue()) // 单位分
.timeExpire(DateUtil.format(reqDTO.getExpireTime(), "yyyy-MM-dd'T'HH:mm:ssXXX"))
.spbillCreateIp(reqDTO.getUserIp())
.notifyUrl(reqDTO.getNotifyUrl())
.productId(trade_type)
.build();
// 执行请求
return client.createOrder(request);
}
private String unifiedOrderV3(PayOrderUnifiedReqDTO reqDTO) throws WxPayException {
// 构建 WxPayUnifiedOrderRequest 对象
WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request();
request.setOutTradeNo(reqDTO.getMerchantOrderId());
request.setDescription(reqDTO.getBody());
request.setAmount(new WxPayUnifiedOrderV3Request.Amount().setTotal(reqDTO.getAmount().intValue())); // 单位分
request.setSceneInfo(new WxPayUnifiedOrderV3Request.SceneInfo().setPayerClientIp(reqDTO.getUserIp()));
request.setNotifyUrl(reqDTO.getNotifyUrl());
// 执行请求
// log.info("支付字段request:{}",request.getTimeExpire());
return client.createOrderV3(TradeTypeEnum.NATIVE, request);
}
@Override
public PayOrderNotifyRespDTO parseOrderNotify(PayNotifyDataDTO data) throws WxPayException {
WxPayOrderNotifyResult notifyResult = client.parseOrderNotifyResult(data.getBody());
Assert.isTrue(Objects.equals(notifyResult.getResultCode(), "SUCCESS"), "支付结果非 SUCCESS");
// 转换结果
return PayOrderNotifyRespDTO.builder().orderExtensionNo(notifyResult.getOutTradeNo())
.channelOrderNo(notifyResult.getTransactionId()).channelUserId(notifyResult.getOpenid())
.successTime(DateUtil.parse(notifyResult.getTimeEnd(), "yyyy-MM-dd'T'HH:mm:ssXXX"))
.data(data.getBody()).build();
}
@Override
public PayRefundNotifyDTO parseRefundNotify(PayNotifyDataDTO notifyData) {
//TODO 需要实现
throw new UnsupportedOperationException("需要实现");
}
@Override
protected PayCommonResult<PayRefundUnifiedRespDTO> doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) throws Throwable {
//TODO 需要实现
throw new UnsupportedOperationException();
}
}

View File

@ -98,7 +98,7 @@ public class WXPubPayClient extends AbstractPayClient<WXPayClientConfig> {
// TODO 芋艿貌似没 title
.body(reqDTO.getBody())
.totalFee(reqDTO.getAmount().intValue()) // 单位分
.timeExpire(DateUtil.format(reqDTO.getExpireTime(), "yyyyMMddHHmmss"))
.timeExpire(DateUtil.format(reqDTO.getExpireTime(), "yyyy-MM-dd'T'HH:mm:ssXXX"))
.spbillCreateIp(reqDTO.getUserIp())
.openid(getOpenid(reqDTO))
.notifyUrl(reqDTO.getNotifyUrl())
@ -114,7 +114,7 @@ public class WXPubPayClient extends AbstractPayClient<WXPayClientConfig> {
// TODO 芋艿貌似没 title
request.setDescription(reqDTO.getBody());
request.setAmount(new WxPayUnifiedOrderV3Request.Amount().setTotal(reqDTO.getAmount().intValue())); // 单位分
request.setTimeExpire(DateUtil.format(reqDTO.getExpireTime(), "yyyyMMddHHmmss"));
request.setTimeExpire(DateUtil.format(reqDTO.getExpireTime(), "yyyy-MM-dd'T'HH:mm:ssXXX"));
request.setPayer(new WxPayUnifiedOrderV3Request.Payer().setOpenid(getOpenid(reqDTO)));
request.setSceneInfo(new WxPayUnifiedOrderV3Request.SceneInfo().setPayerClientIp(reqDTO.getUserIp()));
request.setNotifyUrl(reqDTO.getNotifyUrl());

View File

@ -20,6 +20,8 @@ public enum PayChannelEnum {
WX_PUB("wx_pub", "微信 JSAPI 支付", WXPayClientConfig.class), // 公众号网页
WX_LITE("wx_lite", "微信小程序支付", WXPayClientConfig.class),
WX_APP("wx_app", "微信 App 支付", WXPayClientConfig.class),
WX_NATIVE("wx_native", "微信 native 支付", WXPayClientConfig.class),
ALIPAY_PC("alipay_pc", "支付宝 PC 网站支付", AlipayPayClientConfig.class),
ALIPAY_WAP("alipay_wap", "支付宝 Wap 网站支付", AlipayPayClientConfig.class),

View File

@ -1,6 +1,9 @@
package cn.iocoder.yudao.framework.social.config;
import cn.hutool.core.util.ReflectUtil;
import cn.iocoder.yudao.framework.social.core.YudaoAuthRequestFactory;
import com.xkcoding.http.HttpUtil;
import com.xkcoding.http.support.hutool.HutoolImpl;
import com.xkcoding.justauth.autoconfigure.JustAuthProperties;
import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.cache.AuthStateCache;
@ -23,6 +26,9 @@ public class YudaoSocialAutoConfiguration {
@Bean
@ConditionalOnProperty(prefix = "justauth", value = "enabled", havingValue = "true", matchIfMissing = true)
public YudaoAuthRequestFactory yudaoAuthRequestFactory(JustAuthProperties properties, AuthStateCache authStateCache) {
// 需要修改 HttpUtil 使用的实现避免类报错
HttpUtil.setHttp(new HutoolImpl());
// 创建 YudaoAuthRequestFactory
return new YudaoAuthRequestFactory(properties, authStateCache);
}

View File

@ -4,19 +4,30 @@ import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.tenant.config.TenantProperties;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import lombok.AllArgsConstructor;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import java.util.HashSet;
import java.util.Set;
/**
* 基于 MyBatis Plus 多租户的功能实现 DB 层面的多租户的功能
*
* @author 芋道源码
*/
@AllArgsConstructor
public class TenantDatabaseInterceptor implements TenantLineHandler {
private final TenantProperties properties;
private final Set<String> ignoreTables = new HashSet<>();
public TenantDatabaseInterceptor(TenantProperties properties) {
// 不同 DB 大小写的习惯不同所以需要都添加进去
properties.getIgnoreTables().forEach(table -> {
ignoreTables.add(table.toLowerCase());
ignoreTables.add(table.toUpperCase());
});
// OracleKeyGenerator 生成主键时会查询这个表查询这个表后会自动拼接 TENANT_ID 导致报错
ignoreTables.add("DUAL");
}
@Override
public Expression getTenantId() {
@ -26,7 +37,7 @@ public class TenantDatabaseInterceptor implements TenantLineHandler {
@Override
public boolean ignoreTable(String tableName) {
return TenantContextHolder.isIgnore() // 情况一全局忽略多租户
|| CollUtil.contains(properties.getIgnoreTables(), tableName); // 情况二忽略多租户的表
|| CollUtil.contains(ignoreTables, tableName); // 情况二忽略多租户的表
}
}

View File

@ -15,12 +15,12 @@ import java.util.List;
public interface ConfigFrameworkDAO {
/**
* 查询是否存在比 maxUpdateTime 更新记录更晚的配置
* 查询是否存在比 maxUpdateTime 的更新记录数量
*
* @param maxUpdateTime 最大更新时间
* @return 是否存在
*/
boolean selectExistsByUpdateTimeAfter(Date maxUpdateTime);
int selectCountByUpdateTimeGt(Date maxUpdateTime);
/**
* 查询配置列表

View File

@ -24,7 +24,6 @@ import java.util.List;
import java.util.Properties;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.function.Predicate;
@Slf4j
public class DBConfigRepository extends AbstractConfigRepository {
@ -172,7 +171,7 @@ public class DBConfigRepository extends AbstractConfigRepository {
if (maxUpdateTime == null) { // 如果更新时间为空说明 DB 一定有新数据
log.info("[loadConfigIfUpdate][首次加载全量配置]");
} else { // 判断数据库中是否有更新的配置
if (!configFrameworkDAO.selectExistsByUpdateTimeAfter(maxUpdateTime)) {
if (configFrameworkDAO.selectCountByUpdateTimeGt(maxUpdateTime) == 0) {
return null;
}
log.info("[loadConfigIfUpdate][增量加载全量配置]");

View File

@ -36,7 +36,6 @@
<artifactId>jakarta.validation-api</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -15,10 +15,6 @@
<description>数据库连接池、多数据源、事务、MyBatis 拓展</description>
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
<properties>
<mysql.version>5.1.46</mysql.version>
</properties>
<dependencies>
<dependency>
<groupId>cn.iocoder.boot</groupId>
@ -36,8 +32,20 @@
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>

View File

@ -0,0 +1,108 @@
package cn.iocoder.yudao.framework.mybatis.config;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
import cn.iocoder.yudao.framework.mybatis.core.enums.SqlConstants;
import cn.iocoder.yudao.framework.mybatis.core.util.JdbcUtils;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.IdType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.core.env.ConfigurableEnvironment;
import java.util.Set;
/**
* IdType {@link IdType#NONE} 根据 PRIMARY 数据源所使用的数据库自动设置
*
* @author 芋道源码
*/
@Slf4j
public class IdTypeEnvironmentPostProcessor implements EnvironmentPostProcessor {
private static final String ID_TYPE_KEY = "mybatis-plus.global-config.db-config.id-type";
private static final String DATASOURCE_DYNAMIC_KEY = "spring.datasource.dynamic";
private static final String QUARTZ_JOB_STORE_DRIVER_KEY = "spring.quartz.properties.org.quartz.jobStore.driverDelegateClass";
private static final Set<DbType> INPUT_ID_TYPES = SetUtils.asSet(DbType.ORACLE, DbType.ORACLE_12C,
DbType.POSTGRE_SQL, DbType.KINGBASE_ES, DbType.DB2, DbType.H2);
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
// 如果获取不到 DbType则不进行处理
DbType dbType = getDbType(environment);
if (dbType == null) {
return;
}
// 设置 Quartz JobStore 对应的 Driver
// TODO 芋艿暂时没有找到特别合适的地方先放在这里
setJobStoreDriverIfPresent(environment, dbType);
// 初始化 SQL 静态变量
SqlConstants.init(dbType);
// 如果非 NONE则不进行处理
IdType idType = getIdType(environment);
if (idType != IdType.NONE) {
return;
}
// 情况一用户输入 ID适合 OraclePostgreSQLKingbaseDB2H2 数据库
if (INPUT_ID_TYPES.contains(dbType)) {
setIdType(environment, IdType.INPUT);
return;
}
// 情况二自增 ID适合 MySQL 等直接自增的数据库
setIdType(environment, IdType.AUTO);
}
public IdType getIdType(ConfigurableEnvironment environment) {
return environment.getProperty(ID_TYPE_KEY, IdType.class);
}
public void setIdType(ConfigurableEnvironment environment, IdType idType) {
environment.getSystemProperties().put(ID_TYPE_KEY, idType);
log.info("[setIdType][修改 MyBatis Plus 的 idType 为({})]", idType);
}
public void setJobStoreDriverIfPresent(ConfigurableEnvironment environment, DbType dbType) {
String driverClass = environment.getProperty(QUARTZ_JOB_STORE_DRIVER_KEY);
if (StrUtil.isNotEmpty(driverClass)) {
return;
}
// 根据 dbType 类型获取对应的 driverClass
switch (dbType) {
case POSTGRE_SQL:
driverClass = "org.quartz.impl.jdbcjobstore.PostgreSQLDelegate";
break;
case ORACLE:
case ORACLE_12C:
driverClass = "org.quartz.impl.jdbcjobstore.oracle.OracleDelegate";
break;
case SQL_SERVER:
case SQL_SERVER2005:
driverClass = "org.quartz.impl.jdbcjobstore.MSSQLDelegate";
break;
}
// 设置 driverClass 变量
if (StrUtil.isNotEmpty(driverClass)) {
environment.getSystemProperties().put(QUARTZ_JOB_STORE_DRIVER_KEY, driverClass);
}
}
public static DbType getDbType(ConfigurableEnvironment environment) {
String primary = environment.getProperty(DATASOURCE_DYNAMIC_KEY + "." + "primary");
if (StrUtil.isEmpty(primary)) {
return null;
}
String url = environment.getProperty(DATASOURCE_DYNAMIC_KEY + ".datasource." + primary + ".url");
if (StrUtil.isEmpty(url)) {
return null;
}
return JdbcUtils.getDbType(url);
}
}

View File

@ -1,13 +1,22 @@
package cn.iocoder.yudao.framework.mybatis.config;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.mybatis.core.handler.DefaultDBFieldHandler;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator;
import com.baomidou.mybatisplus.extension.incrementer.H2KeyGenerator;
import com.baomidou.mybatisplus.extension.incrementer.KingbaseKeyGenerator;
import com.baomidou.mybatisplus.extension.incrementer.OracleKeyGenerator;
import com.baomidou.mybatisplus.extension.incrementer.PostgreKeyGenerator;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.apache.ibatis.annotations.Mapper;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.ConfigurableEnvironment;
/**
* MyBaits 配置类
@ -31,4 +40,25 @@ public class YudaoMybatisAutoConfiguration {
return new DefaultDBFieldHandler(); // 自动填充参数类
}
@Bean
@ConditionalOnProperty(prefix = "mybatis-plus.global-config.db-config", name = "id-type", havingValue = "INPUT")
public IKeyGenerator keyGenerator(ConfigurableEnvironment environment) {
DbType dbType = IdTypeEnvironmentPostProcessor.getDbType(environment);
if (dbType != null) {
switch (dbType) {
case POSTGRE_SQL:
return new PostgreKeyGenerator();
case ORACLE:
case ORACLE_12C:
return new OracleKeyGenerator();
case H2:
return new H2KeyGenerator();
case KINGBASE_ES:
return new KingbaseKeyGenerator();
}
}
// 找不到合适的 IKeyGenerator 实现类
throw new IllegalArgumentException(StrUtil.format("DbType{} 找不到合适的 IKeyGenerator 实现类", dbType));
}
}

View File

@ -3,8 +3,8 @@ package cn.iocoder.yudao.framework.mybatis.core.dataobject;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableLogic;
import lombok.Builder;
import lombok.Data;
import org.apache.ibatis.type.JdbcType;
import java.io.Serializable;
import java.util.Date;
@ -32,14 +32,14 @@ public abstract class BaseDO implements Serializable {
*
* 使用 String 类型的原因是未来可能会存在非数值的情况留好拓展性
*/
@TableField(fill = FieldFill.INSERT)
@TableField(fill = FieldFill.INSERT, jdbcType = JdbcType.VARCHAR)
private String creator;
/**
* 更新者目前使用 SysUser id 编号
*
* 使用 String 类型的原因是未来可能会存在非数值的情况留好拓展性
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
@TableField(fill = FieldFill.INSERT_UPDATE, jdbcType = JdbcType.VARCHAR)
private String updater;
/**
* 是否删除

View File

@ -1,11 +1,21 @@
package cn.iocoder.yudao.framework.mybatis.core.enums;
import com.baomidou.mybatisplus.annotation.DbType;
/**
* SQL相关常量类
*
* @author 芋道源码
*/
public interface SqlConstants {
public class SqlConstants {
/**
* 数据库的类型
*/
public static DbType DB_TYPE;
String LIMIT1 = "LIMIT 1";
public static void init(DbType dbType) {
DB_TYPE = dbType;
}
}

View File

@ -1,5 +1,7 @@
package cn.iocoder.yudao.framework.mybatis.core.query;
import cn.hutool.core.lang.Assert;
import cn.iocoder.yudao.framework.mybatis.core.enums.SqlConstants;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ArrayUtils;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
@ -124,4 +126,28 @@ public class QueryWrapperX<T> extends QueryWrapper<T> {
return this;
}
/**
* 设置只返回最后一条
*
* TODO 芋艿不是完美解需要在思考下如果使用多数据源并且数据源是多种类型时可能会存在问题实现之返回一条的语法不同
*
* @return this
*/
public QueryWrapperX<T> limit1() {
Assert.notNull(SqlConstants.DB_TYPE, "获取不到数据库的类型");
switch (SqlConstants.DB_TYPE) {
case ORACLE:
case ORACLE_12C:
super.eq("ROWNUM", 1);
break;
case SQL_SERVER:
case SQL_SERVER2005:
super.select("TOP 1 *"); // 由于 SQL Server 是通过 SELECT TOP 1 实现限制一条所以只好使用 * 查询剩余字段
break;
default:
super.last("LIMIT 1");
}
return this;
}
}

View File

@ -0,0 +1,42 @@
package cn.iocoder.yudao.framework.mybatis.core.util;
import com.baomidou.mybatisplus.annotation.DbType;
import java.sql.Connection;
import java.sql.DriverManager;
/**
* JDBC 工具类
*
* @author 芋道源码
*/
public class JdbcUtils {
/**
* 判断连接是否正确
*
* @param url 数据源连接
* @param username 账号
* @param password 密码
* @return 是否正确
*/
public static boolean isConnectionOK(String url, String username, String password) {
try (Connection ignored = DriverManager.getConnection(url, username, password)) {
return true;
} catch (Exception ex) {
return false;
}
}
/**
* 获得 URL 对应的 DB 类型
*
* @param url URL
* @return DB 类型
*/
public static DbType getDbType(String url) {
String name = com.alibaba.druid.util.JdbcUtils.getDbType(url, null);
return DbType.getDbType(name);
}
}

View File

@ -1,3 +1,5 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration,\
cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration
org.springframework.boot.env.EnvironmentPostProcessor=\
cn.iocoder.yudao.framework.mybatis.config.IdTypeEnvironmentPostProcessor

View File

@ -3,7 +3,7 @@ package cn.iocoder.yudao.framework.security.config;
import cn.iocoder.yudao.framework.security.core.aop.PreAuthenticatedAspect;
import cn.iocoder.yudao.framework.security.core.authentication.MultiUserDetailsAuthenticationProvider;
import cn.iocoder.yudao.framework.security.core.context.TransmittableThreadLocalSecurityContextHolderStrategy;
import cn.iocoder.yudao.framework.security.core.filter.JWTAuthenticationTokenFilter;
import cn.iocoder.yudao.framework.security.core.filter.TokenAuthenticationFilter;
import cn.iocoder.yudao.framework.security.core.handler.AccessDeniedHandlerImpl;
import cn.iocoder.yudao.framework.security.core.handler.AuthenticationEntryPointImpl;
import cn.iocoder.yudao.framework.security.core.handler.LogoutSuccessHandlerImpl;
@ -86,9 +86,9 @@ public class YudaoSecurityAutoConfiguration {
* Token 认证过滤器 Bean
*/
@Bean
public JWTAuthenticationTokenFilter authenticationTokenFilter(MultiUserDetailsAuthenticationProvider authenticationProvider,
public TokenAuthenticationFilter authenticationTokenFilter(MultiUserDetailsAuthenticationProvider authenticationProvider,
GlobalExceptionHandler globalExceptionHandler) {
return new JWTAuthenticationTokenFilter(securityProperties, authenticationProvider, globalExceptionHandler);
return new TokenAuthenticationFilter(securityProperties, authenticationProvider, globalExceptionHandler);
}
/**

View File

@ -2,7 +2,7 @@ package cn.iocoder.yudao.framework.security.config;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.security.core.authentication.MultiUserDetailsAuthenticationProvider;
import cn.iocoder.yudao.framework.security.core.filter.JWTAuthenticationTokenFilter;
import cn.iocoder.yudao.framework.security.core.filter.TokenAuthenticationFilter;
import cn.iocoder.yudao.framework.web.config.WebProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
@ -55,7 +55,7 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap
* Token 认证过滤器 Bean
*/
@Resource
private JWTAuthenticationTokenFilter authenticationTokenFilter;
private TokenAuthenticationFilter authenticationTokenFilter;
/**
* 自定义的权限映射 Bean

View File

@ -18,13 +18,13 @@ import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* JWT 过滤器验证 token 的有效性
* Token 过滤器验证 token 的有效性
* 验证通过后获得 {@link LoginUser} 信息并加入到 Spring Security 上下文
*
* @author 芋道源码
*/
@RequiredArgsConstructor
public class JWTAuthenticationTokenFilter extends OncePerRequestFilter {
public class TokenAuthenticationFilter extends OncePerRequestFilter {
private final SecurityProperties securityProperties;
@ -43,7 +43,7 @@ public class JWTAuthenticationTokenFilter extends OncePerRequestFilter {
LoginUser loginUser = authenticationProvider.verifyTokenAndRefresh(request, token);
// 模拟 Login 功能方便日常开发调试
if (loginUser == null) {
loginUser = this.mockLoginUser(request, token);
loginUser = mockLoginUser(request, token);
}
// 设置当前用户
if (loginUser != null) {

View File

@ -3,12 +3,8 @@ package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.Map;
@ApiModel("管理后台 - 通过流程任务的 Request VO")
@Data
@ -20,6 +16,6 @@ public class BpmTaskApproveReqVO {
@ApiModelProperty(value = "审批意见", required = true, example = "不错不错!")
@NotEmpty(message = "审批意见不能为空")
private String comment;
private String reason;
}

View File

@ -22,6 +22,6 @@ public class BpmTaskDonePageItemRespVO extends BpmTaskTodoPageItemRespVO {
@ApiModelProperty(value = "任务结果", required = true, notes = "参见 bpm_process_instance_result", example = "2")
private Integer result;
@ApiModelProperty(value = "审批建议", required = true, example = "不请假了!")
private String comment;
private String reason;
}

View File

@ -16,6 +16,6 @@ public class BpmTaskRejectReqVO {
@ApiModelProperty(value = "审批意见", required = true, example = "不错不错!")
@NotEmpty(message = "审批意见不能为空")
private String comment;
private String reason;
}

View File

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.bpm.dal.dataobject.definition;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
@ -16,6 +17,7 @@ import java.util.List;
* @author 芋道源码
*/
@TableName(value = "bpm_form", autoResultMap = true)
@KeySequence("bpm_form_seq") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)

View File

@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.bpm.dal.dataobject.definition;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
@ -17,6 +18,7 @@ import java.util.List;
* @author 芋道源码
*/
@TableName(value = "bpm_process_definition_ext", autoResultMap = true)
@KeySequence("bpm_process_definition_ext_seq") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)

View File

@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.framework.mybatis.core.type.JsonLongSetTypeHandler;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
@ -21,6 +22,7 @@ import java.util.Set;
* @author 芋道源码
*/
@TableName(value = "bpm_task_assign_rule", autoResultMap = true)
@KeySequence("bpm_task_assign_rule_seq") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@ -31,8 +33,9 @@ public class BpmTaskAssignRuleDO extends BaseDO {
/**
* {@link #processDefinitionId} 空串用于标识属于流程模型而不属于流程定义
* 不使用空串的原因Oracle 针对空串会处理成 null进而导致无法检索
*/
public static final String PROCESS_DEFINITION_ID_NULL = "";
public static final String PROCESS_DEFINITION_ID_NULL = "DEFAULT";
/**
* 编号
@ -64,7 +67,6 @@ public class BpmTaskAssignRuleDO extends BaseDO {
*
* 枚举 {@link BpmTaskAssignRuleTypeEnum}
*/
@TableField("`type`")
private Integer type;
/**
* 规则值数组一般关联指定表的编号

View File

@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.bpm.dal.dataobject.definition;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.framework.mybatis.core.type.JsonLongSetTypeHandler;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
@ -16,6 +17,7 @@ import java.util.Set;
* @author 芋道源码
*/
@TableName(value = "bpm_user_group", autoResultMap = true)
@KeySequence("bpm_user_group_seq") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)

View File

@ -1,10 +1,13 @@
package cn.iocoder.yudao.module.bpm.dal.dataobject.oa;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
import lombok.*;
import java.util.*;
import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
import java.util.Date;
/**
* OA 请假申请 DO
@ -15,6 +18,7 @@ import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
* @author 芋道源码
*/
@TableName("bpm_oa_leave")
@KeySequence("bpm_oa_leave_seq") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@ -37,8 +41,7 @@ public class BpmOALeaveDO extends BaseDO {
/**
* 请假类型
*/
@TableField("`type`")
private String type;
private Integer type;
/**
* 原因
*/

View File

@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.bpm.dal.dataobject.task;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
@ -21,6 +22,7 @@ import java.util.Map;
* @author 芋道源码
*/
@TableName(value = "bpm_process_instance_ext", autoResultMap = true)
@KeySequence("bpm_process_instance_ext_seq") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)

View File

@ -2,6 +2,8 @@ package cn.iocoder.yudao.module.bpm.dal.dataobject.task;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@ -17,6 +19,7 @@ import java.util.Date;
* @author 芋道源码
*/
@TableName(value = "bpm_task_ext", autoResultMap = true)
@KeySequence("bpm_task_ext_seq") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@ -60,7 +63,7 @@ public class BpmTaskExtDO extends BaseDO {
/**
* 审批建议
*/
private String comment;
private String reason;
/**
* 任务的结束时间
*

View File

@ -1,11 +1,11 @@
package cn.iocoder.yudao.module.bpm.dal.mysql.definition;
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormPageReqVO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormPageReqVO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
import org.apache.ibatis.annotations.Mapper;
/**
@ -17,9 +17,9 @@ import org.apache.ibatis.annotations.Mapper;
public interface BpmFormMapper extends BaseMapperX<BpmFormDO> {
default PageResult<BpmFormDO> selectPage(BpmFormPageReqVO reqVO) {
return selectPage(reqVO, new QueryWrapperX<BpmFormDO>()
.likeIfPresent("name", reqVO.getName())
.orderByDesc("id"));
return selectPage(reqVO, new LambdaQueryWrapperX<BpmFormDO>()
.likeIfPresent(BpmFormDO::getName, reqVO.getName())
.orderByDesc(BpmFormDO::getId));
}
}

View File

@ -1,8 +1,7 @@
package cn.iocoder.yudao.module.bpm.dal.mysql.definition;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.Collection;
@ -12,11 +11,11 @@ import java.util.List;
public interface BpmProcessDefinitionExtMapper extends BaseMapperX<BpmProcessDefinitionExtDO> {
default List<BpmProcessDefinitionExtDO> selectListByProcessDefinitionIds(Collection<String> processDefinitionIds) {
return selectList("process_definition_id", processDefinitionIds);
return selectList(BpmProcessDefinitionExtDO::getProcessDefinitionId, processDefinitionIds);
}
default BpmProcessDefinitionExtDO selectByProcessDefinitionId(String processDefinitionId) {
return selectOne("process_definition_id", processDefinitionId);
return selectOne(BpmProcessDefinitionExtDO::getProcessDefinitionId, processDefinitionId);
}
}

View File

@ -1,8 +1,8 @@
package cn.iocoder.yudao.module.bpm.dal.mysql.definition;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.lang.Nullable;
@ -13,23 +13,23 @@ public interface BpmTaskAssignRuleMapper extends BaseMapperX<BpmTaskAssignRuleDO
default List<BpmTaskAssignRuleDO> selectListByProcessDefinitionId(String processDefinitionId,
@Nullable String taskDefinitionKey) {
return selectList(new QueryWrapperX<BpmTaskAssignRuleDO>()
.eq("process_definition_id", processDefinitionId)
.eqIfPresent("task_definition_key", taskDefinitionKey));
return selectList(new LambdaQueryWrapperX<BpmTaskAssignRuleDO>()
.eq(BpmTaskAssignRuleDO::getProcessDefinitionId, processDefinitionId)
.eqIfPresent(BpmTaskAssignRuleDO::getTaskDefinitionKey, taskDefinitionKey));
}
default List<BpmTaskAssignRuleDO> selectListByModelId(String modelId) {
return selectList(new QueryWrapperX<BpmTaskAssignRuleDO>()
.eq("model_id", modelId)
.eq("process_definition_id", BpmTaskAssignRuleDO.PROCESS_DEFINITION_ID_NULL));
return selectList(new LambdaQueryWrapperX<BpmTaskAssignRuleDO>()
.eq(BpmTaskAssignRuleDO::getModelId, modelId)
.eq(BpmTaskAssignRuleDO::getProcessDefinitionId, BpmTaskAssignRuleDO.PROCESS_DEFINITION_ID_NULL));
}
default BpmTaskAssignRuleDO selectListByModelIdAndTaskDefinitionKey(String modelId,
String taskDefinitionKey) {
return selectOne(new QueryWrapperX<BpmTaskAssignRuleDO>()
.eq("model_id", modelId)
.eq("process_definition_id", BpmTaskAssignRuleDO.PROCESS_DEFINITION_ID_NULL)
.eq("task_definition_key", taskDefinitionKey));
return selectOne(new LambdaQueryWrapperX<BpmTaskAssignRuleDO>()
.eq(BpmTaskAssignRuleDO::getModelId, modelId)
.eq(BpmTaskAssignRuleDO::getProcessDefinitionId, BpmTaskAssignRuleDO.PROCESS_DEFINITION_ID_NULL)
.eq(BpmTaskAssignRuleDO::getTaskDefinitionKey, taskDefinitionKey));
}
}

View File

@ -1,35 +1,34 @@
package cn.iocoder.yudao.module.bpm.dal.mysql.task;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceMyPageReqVO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceMyPageReqVO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface BpmProcessInstanceExtMapper extends BaseMapperX<BpmProcessInstanceExtDO> {
default PageResult<BpmProcessInstanceExtDO> selectPage(Long userId, BpmProcessInstanceMyPageReqVO reqVO) {
return selectPage(reqVO, new QueryWrapperX<BpmProcessInstanceExtDO>()
.eqIfPresent("start_user_id", userId)
.likeIfPresent("name", reqVO.getName())
.eqIfPresent("process_definition_id", reqVO.getProcessDefinitionId())
.eqIfPresent("category", reqVO.getCategory())
.eqIfPresent("status", reqVO.getStatus())
.eqIfPresent("result", reqVO.getResult())
.betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
.orderByDesc("id"));
return selectPage(reqVO, new LambdaQueryWrapperX<BpmProcessInstanceExtDO>()
.eqIfPresent(BpmProcessInstanceExtDO::getStartUserId, userId)
.likeIfPresent(BpmProcessInstanceExtDO::getName, reqVO.getName())
.eqIfPresent(BpmProcessInstanceExtDO::getProcessDefinitionId, reqVO.getProcessDefinitionId())
.eqIfPresent(BpmProcessInstanceExtDO::getCategory, reqVO.getCategory())
.eqIfPresent(BpmProcessInstanceExtDO::getStatus, reqVO.getStatus())
.eqIfPresent(BpmProcessInstanceExtDO::getResult, reqVO.getResult())
.betweenIfPresent(BpmProcessInstanceExtDO::getCreateTime, reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
.orderByDesc(BpmProcessInstanceExtDO::getId));
}
default BpmProcessInstanceExtDO selectByProcessInstanceId(String processDefinitionId) {
return selectOne("process_instance_id", processDefinitionId);
return selectOne(BpmProcessInstanceExtDO::getProcessInstanceId, processDefinitionId);
}
default void updateByProcessInstanceId(BpmProcessInstanceExtDO updateObj) {
update(updateObj, new QueryWrapper<BpmProcessInstanceExtDO>()
.eq("process_instance_id", updateObj.getProcessInstanceId()));
update(updateObj, new LambdaQueryWrapperX<BpmProcessInstanceExtDO>()
.eq(BpmProcessInstanceExtDO::getProcessInstanceId, updateObj.getProcessInstanceId()));
}
}

View File

@ -1,7 +1,7 @@
package cn.iocoder.yudao.module.bpm.dal.mysql.task;
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.ibatis.annotations.Mapper;
@ -20,6 +20,6 @@ public interface BpmTaskExtMapper extends BaseMapperX<BpmTaskExtDO> {
}
default List<BpmTaskExtDO> selectListByProcessInstanceId(String processInstanceId) {
return selectList("process_instance_id", processInstanceId);
return selectList(BpmTaskExtDO::getProcessInstanceId, processInstanceId);
}
}

View File

@ -44,7 +44,7 @@ public class BpmMessageServiceImpl implements BpmMessageService {
public void sendMessageWhenProcessInstanceReject(BpmMessageSendWhenProcessInstanceRejectReqDTO reqDTO) {
Map<String, Object> templateParams = new HashMap<>();
templateParams.put("processInstanceName", reqDTO.getProcessInstanceName());
templateParams.put("comment", reqDTO.getComment());
templateParams.put("reason", reqDTO.getReason());
templateParams.put("detailUrl", getProcessInstanceDetailUrl(reqDTO.getProcessInstanceId()));
smsSendApi.sendSingleSmsToAdmin(BpmMessageConvert.INSTANCE.convert(reqDTO.getStartUserId(),
BpmMessageEnum.PROCESS_INSTANCE_REJECT.getSmsTemplateCode(), templateParams));

View File

@ -28,6 +28,6 @@ public class BpmMessageSendWhenProcessInstanceRejectReqDTO {
* 不通过理由
*/
@NotEmpty(message = "不通过理由不能为空")
private String comment;
private String reason;
}

View File

@ -116,10 +116,10 @@ public interface BpmProcessInstanceConvert {
return event;
}
default BpmMessageSendWhenProcessInstanceRejectReqDTO convert(ProcessInstance processInstance, String comment) {
default BpmMessageSendWhenProcessInstanceRejectReqDTO convert(ProcessInstance processInstance, String reason) {
BpmMessageSendWhenProcessInstanceRejectReqDTO reqDTO = new BpmMessageSendWhenProcessInstanceRejectReqDTO();
copyTo(processInstance, reqDTO);
reqDTO.setComment(comment);
reqDTO.setReason(reason);
return reqDTO;
}
@Mapping(source = "name", target = "processInstanceName")

View File

@ -158,8 +158,8 @@ public interface BpmProcessInstanceService {
* 更新 ProcessInstance 拓展记录为不通过
*
* @param id 流程编号
* @param comment 理由例如说审批不通过时需要传递该值
* @param reason 理由例如说审批不通过时需要传递该值
*/
void updateProcessInstanceExtReject(String id, String comment);
void updateProcessInstanceExtReject(String id, String reason);
}

View File

@ -285,11 +285,11 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
}
@Transactional(rollbackFor = Exception.class)
public void updateProcessInstanceExtReject(String id, String comment) {
public void updateProcessInstanceExtReject(String id, String reason) {
// 需要主动查询因为 instance 只有 id 属性
ProcessInstance processInstance = getProcessInstance(id);
// 删除流程实例以实现驳回任务时取消整个审批流程
deleteProcessInstance(id, StrUtil.format(BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.format(comment)));
deleteProcessInstance(id, StrUtil.format(BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.format(reason)));
// 更新 status + result
// 注意不能和上面的逻辑更换位置因为 deleteProcessInstance 会触发流程的取消进而调用 updateProcessInstanceExtCancel 方法
@ -300,7 +300,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO);
// 发送流程被不通过的消息
messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert(processInstance, comment));
messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert(processInstance, reason));
// 发送流程实例的状态事件
processInstanceResultEventPublisher.sendProcessInstanceResultEvent(

View File

@ -226,7 +226,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
taskService.complete(task.getId(), instance.getProcessVariables()); // TODO 芋艿variables 的选择
// 更新任务拓展表为通过
taskExtMapper.updateByTaskId(new BpmTaskExtDO().setTaskId(task.getId())
.setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()).setComment(reqVO.getComment()));
.setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()).setReason(reqVO.getReason()));
// TODO 芋艿添加评论
// taskService.addComment(task.getId(), task.getProcessInstanceId(), reqVO.getComment());
@ -250,11 +250,11 @@ public class BpmTaskServiceImpl implements BpmTaskService {
}
// 更新流程实例为不通过
processInstanceService.updateProcessInstanceExtReject(instance.getProcessInstanceId(), reqVO.getComment());
processInstanceService.updateProcessInstanceExtReject(instance.getProcessInstanceId(), reqVO.getReason());
// 更新任务拓展表为不通过
taskExtMapper.updateByTaskId(new BpmTaskExtDO().setTaskId(task.getId())
.setResult(BpmProcessInstanceResultEnum.REJECT.getResult()).setComment(reqVO.getComment()));
.setResult(BpmProcessInstanceResultEnum.REJECT.getResult()).setReason(reqVO.getReason()));
// TODO 芋艿添加评论
// taskService.addComment(task.getId(), task.getProcessInstanceId(), reqVO.getComment());

View File

@ -18,12 +18,10 @@ import org.flowable.task.api.Task;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
import java.util.List;
import java.util.Map;
import java.util.Optional;
/**
* 流程实例 Convert
@ -105,11 +103,11 @@ public interface BpmProcessInstanceConvert {
.setProcessInstanceName(instance.getName());
}
default BpmMessageSendWhenProcessInstanceRejectReqDTO convert2RejectReq(ProcessInstance instance, String comment) {
default BpmMessageSendWhenProcessInstanceRejectReqDTO convert2RejectReq(ProcessInstance instance, String reason) {
return new BpmMessageSendWhenProcessInstanceRejectReqDTO()
.setProcessInstanceName(instance.getName())
.setProcessInstanceId(instance.getId())
.setComment(comment)
.setReason(reason)
.setStartUserId(NumberUtils.parseLong(instance.getStartUserId()));
}

View File

@ -141,9 +141,9 @@ public interface BpmProcessInstanceService {
* 更新 ProcessInstance 拓展记录为不通过
*
* @param id 流程编号
* @param comment 理由例如说审批不通过时需要传递该值
* @param reason 理由例如说审批不通过时需要传递该值
*/
void updateProcessInstanceExtReject(String id, String comment);
void updateProcessInstanceExtReject(String id, String reason);
}

View File

@ -250,11 +250,11 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
}
@Transactional(rollbackFor = Exception.class)
public void updateProcessInstanceExtReject(String id, String comment) {
public void updateProcessInstanceExtReject(String id, String reason) {
// 需要主动查询因为 instance 只有 id 属性
ProcessInstance processInstance = getProcessInstance(id);
// 删除流程实例以实现驳回任务时取消整个审批流程
deleteProcessInstance(id, StrUtil.format(BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.format(comment)));
deleteProcessInstance(id, StrUtil.format(BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.format(reason)));
// 更新 status + result
// 注意不能和上面的逻辑更换位置因为 deleteProcessInstance 会触发流程的取消进而调用 updateProcessInstanceExtCancel 方法
@ -265,7 +265,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO);
// 发送流程被不通过的消息
messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert2RejectReq(processInstance, comment));
messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert2RejectReq(processInstance, reason));
// 发送流程实例的状态事件
processInstanceResultEventPublisher.sendProcessInstanceResultEvent(

View File

@ -182,7 +182,7 @@ public class BpmTaskServiceImpl implements BpmTaskService{
taskService.complete(task.getId(), instance.getProcessVariables());
// 更新任务拓展表为通过
taskExtMapper.updateByTaskId(new BpmTaskExtDO().setTaskId(task.getId())
.setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()).setComment(reqVO.getComment()));
.setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()).setReason(reqVO.getReason()));
}
@Override
@ -196,11 +196,11 @@ public class BpmTaskServiceImpl implements BpmTaskService{
}
// 更新流程实例为不通过
processInstanceService.updateProcessInstanceExtReject(instance.getProcessInstanceId(), reqVO.getComment());
processInstanceService.updateProcessInstanceExtReject(instance.getProcessInstanceId(), reqVO.getReason());
// 更新任务拓展表为不通过
taskExtMapper.updateByTaskId(new BpmTaskExtDO().setTaskId(task.getId())
.setResult(BpmProcessInstanceResultEnum.REJECT.getResult()).setComment(reqVO.getComment()));
.setResult(BpmProcessInstanceResultEnum.REJECT.getResult()).setReason(reqVO.getReason()));
}
@Override

View File

@ -13,7 +13,7 @@ public interface ErrorCodeConstants {
ErrorCode CONFIG_NOT_EXISTS = new ErrorCode(1001000001, "参数配置不存在");
ErrorCode CONFIG_KEY_DUPLICATE = new ErrorCode(1001000002, "参数配置 key 重复");
ErrorCode CONFIG_CAN_NOT_DELETE_SYSTEM_TYPE = new ErrorCode(1001000003, "不能删除类型为系统内置的参数配置");
ErrorCode CONFIG_GET_VALUE_ERROR_IF_SENSITIVE = new ErrorCode(1001000004, "不允许获取敏感配置到前端");
ErrorCode CONFIG_GET_VALUE_ERROR_IF_VISIBLE = new ErrorCode(1001000004, "获取参数配置失败,原因:不允许获取不可见配置");
// ========== 定时任务 1001001000 ==========
ErrorCode JOB_NOT_EXISTS = new ErrorCode(1001001000, "定时任务不存在");
@ -36,11 +36,12 @@ public interface ErrorCodeConstants {
ErrorCode CODEGEN_TABLE_EXISTS = new ErrorCode(1003001000, "表定义已经存在");
ErrorCode CODEGEN_IMPORT_TABLE_NULL = new ErrorCode(1003001001, "导入的表不存在");
ErrorCode CODEGEN_IMPORT_COLUMNS_NULL = new ErrorCode(1003001002, "导入的字段不存在");
ErrorCode CODEGEN_PARSE_SQL_ERROR = new ErrorCode(1003001003, "解析 SQL 失败,请检查");
ErrorCode CODEGEN_TABLE_NOT_EXISTS = new ErrorCode(1003001004, "表定义不存在");
ErrorCode CODEGEN_COLUMN_NOT_EXISTS = new ErrorCode(1003001005, "字段义不存在");
ErrorCode CODEGEN_SYNC_COLUMNS_NULL = new ErrorCode(1003001006, "同步的字段不存在");
ErrorCode CODEGEN_SYNC_NONE_CHANGE = new ErrorCode(1003001007, "同步失败,不存在改变");
ErrorCode CODEGEN_TABLE_INFO_TABLE_COMMENT_IS_NULL = new ErrorCode(1003001008, "数据库的表注释未填写");
ErrorCode CODEGEN_TABLE_INFO_COLUMN_COMMENT_IS_NULL = new ErrorCode(1003001009, "数据库的表字段({})注释未填写");
// ========== 字典类型测试1001005000 ==========
ErrorCode TEST_DEMO_NOT_EXISTS = new ErrorCode(1001005000, "测试示例不存在");
@ -49,4 +50,8 @@ public interface ErrorCodeConstants {
ErrorCode FILE_CONFIG_NOT_EXISTS = new ErrorCode(1001006000, "文件配置不存在");
ErrorCode FILE_CONFIG_DELETE_FAIL_MASTER = new ErrorCode(1001006001, "该文件配置不允许删除,原因:它是主配置,删除会导致无法上传文件");
// ========== 数据源配置 1001007000 ==========
ErrorCode DATA_SOURCE_CONFIG_NOT_EXISTS = new ErrorCode(1001007000, "数据源配置不存在");
ErrorCode DATA_SOURCE_CONFIG_NOT_OK = new ErrorCode(1001007001, "数据源配置不正确,无法进行连接");
}

View File

@ -47,6 +47,10 @@
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-mybatis</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId> <!-- 代码生成器,使用它解析表结构 -->
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
@ -79,6 +83,11 @@
</dependency>
<!-- 工具类相关 -->
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId> <!-- 加解密 -->
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-excel</artifactId>

View File

@ -4,19 +4,18 @@ import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ZipUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.CodegenCreateListReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.CodegenDetailRespVO;
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.CodegenPreviewRespVO;
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.CodegenUpdateReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.CodegenTablePageReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.CodegenTableRespVO;
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.SchemaTableRespVO;
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.DatabaseTableRespVO;
import cn.iocoder.yudao.module.infra.convert.codegen.CodegenConvert;
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaTableDO;
import cn.iocoder.yudao.module.infra.service.codegen.CodegenService;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
@ -33,7 +32,6 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@ -50,19 +48,16 @@ public class CodegenController {
@GetMapping("/db/table/list")
@ApiOperation(value = "获得数据库自带的表定义列表", notes = "会过滤掉已经导入 Codegen 的表")
@ApiImplicitParams({
@ApiImplicitParam(name = "tableName", value = "表名,模糊匹配", required = true, example = "yudao", dataTypeClass = String.class),
@ApiImplicitParam(name = "tableComment", value = "描述,模糊匹配", required = true, example = "芋道", dataTypeClass = String.class)
@ApiImplicitParam(name = "dataSourceConfigId", value = "数据源配置的编号", required = true, example = "1", dataTypeClass = Long.class),
@ApiImplicitParam(name = "name", value = "表名,模糊匹配", example = "yudao", dataTypeClass = String.class),
@ApiImplicitParam(name = "comment", value = "描述,模糊匹配", example = "芋道", dataTypeClass = String.class)
})
@PreAuthorize("@ss.hasPermission('infra:codegen:query')")
public CommonResult<List<SchemaTableRespVO>> getSchemaTableList(
@RequestParam(value = "tableName", required = false) String tableName,
@RequestParam(value = "tableComment", required = false) String tableComment) {
// 获得数据库自带的表定义列表
List<SchemaTableDO> schemaTables = codegenService.getSchemaTableList(tableName, tableComment);
// 移除在 Codegen 已经存在的
Set<String> existsTables = CollectionUtils.convertSet(codegenService.getCodeGenTableList(), CodegenTableDO::getTableName);
schemaTables.removeIf(table -> existsTables.contains(table.getTableName()));
return success(CodegenConvert.INSTANCE.convertList04(schemaTables));
public CommonResult<List<DatabaseTableRespVO>> getDatabaseTableList(
@RequestParam(value = "dataSourceConfigId") Long dataSourceConfigId,
@RequestParam(value = "name", required = false) String name,
@RequestParam(value = "comment", required = false) String comment) {
return success(codegenService.getDatabaseTableList(dataSourceConfigId, name, comment));
}
@GetMapping("/table/page")
@ -85,19 +80,10 @@ public class CodegenController {
}
@ApiOperation("基于数据库的表结构,创建代码生成器的表和字段定义")
@ApiImplicitParam(name = "tableNames", value = "表名数组", required = true, example = "sys_user", dataTypeClass = List.class)
@PostMapping("/create-list-from-db")
@PostMapping("/create-list")
@PreAuthorize("@ss.hasPermission('infra:codegen:create')")
public CommonResult<List<Long>> createCodegenListFromDB(@RequestParam("tableNames") List<String> tableNames) {
return success(codegenService.createCodegenListFromDB(getLoginUserId(), tableNames));
}
@ApiOperation("基于 SQL 建表语句,创建代码生成器的表和字段定义")
@ApiImplicitParam(name = "sql", value = "SQL 建表语句", required = true, example = "sql", dataTypeClass = String.class)
@PostMapping("/create-list-from-sql")
@PreAuthorize("@ss.hasPermission('infra:codegen:create')")
public CommonResult<Long> createCodegenListFromSQL(@RequestParam("sql") String sql) {
return success(codegenService.createCodegenListFromSQL(getLoginUserId(), sql));
public CommonResult<List<Long>> createCodegenList(@Valid @RequestBody CodegenCreateListReqVO reqVO) {
return success(codegenService.createCodegenList(getLoginUserId(), reqVO));
}
@ApiOperation("更新数据库的表和字段定义")
@ -117,19 +103,6 @@ public class CodegenController {
return success(true);
}
@ApiOperation("基于 SQL 建表语句,同步数据库的表和字段定义")
@PutMapping("/sync-from-sql")
@ApiImplicitParams({
@ApiImplicitParam(name = "tableId", value = "表编号", required = true, example = "1024", dataTypeClass = Long.class),
@ApiImplicitParam(name = "sql", value = "SQL 建表语句", required = true, example = "sql", dataTypeClass = String.class)
})
@PreAuthorize("@ss.hasPermission('infra:codegen:update')")
public CommonResult<Boolean> syncCodegenFromSQL(@RequestParam("tableId") Long tableId,
@RequestParam("sql") String sql) {
codegenService.syncCodegenFromSQL(tableId, sql);
return success(true);
}
@ApiOperation("删除数据库的表和字段定义")
@DeleteMapping("/delete")
@ApiImplicitParam(name = "tableId", value = "表编号", required = true, example = "1024", dataTypeClass = Long.class)

View File

@ -0,0 +1,22 @@
package cn.iocoder.yudao.module.infra.controller.admin.codegen.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
@ApiModel("管理后台 - 基于数据库的表结构,创建代码生成器的表和字段定义 Request VO")
@Data
public class CodegenCreateListReqVO {
@ApiModelProperty(value = "数据源配置的编号", required = true, example = "1")
@NotNull(message = "数据源配置的编号不能为空")
private Long dataSourceConfigId;
@ApiModelProperty(value = "表名数组", required = true, example = "[1, 2, 3]")
@NotNull(message = "表名数组不能为空")
private List<String> tableNames;
}

View File

@ -22,7 +22,7 @@ public class CodegenColumnBaseVO {
@ApiModelProperty(value = "字段类型", required = true, example = "int(11)")
@NotNull(message = "字段类型不能为空")
private String columnType;
private String dataType;
@ApiModelProperty(value = "字段描述", required = true, example = "年龄")
@NotNull(message = "字段描述不能为空")

View File

@ -12,10 +12,6 @@ import javax.validation.constraints.NotNull;
@Data
public class CodegenTableBaseVO {
@ApiModelProperty(value = "导入类型", required = true, example = "1", notes = "参见 CodegenImportTypeEnum 枚举")
@NotNull(message = "导入类型不能为空")
private Integer importType;
@ApiModelProperty(value = "生成场景", required = true, example = "1", notes = "参见 CodegenSceneEnum 枚举")
@NotNull(message = "导入类型不能为空")
private Integer scene;

View File

@ -17,6 +17,9 @@ public class CodegenTableRespVO extends CodegenTableBaseVO {
@ApiModelProperty(value = "编号", required = true, example = "1")
private Long id;
@ApiModelProperty(value = "主键编号", required = true, example = "1024")
private Integer dataSourceConfigId;
@ApiModelProperty(value = "创建时间", required = true)
private Date createTime;

View File

@ -0,0 +1,17 @@
package cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ApiModel("管理后台 - 数据库的表定义 Response VO")
@Data
public class DatabaseTableRespVO {
@ApiModelProperty(value = "表名称", required = true, example = "yuanma")
private String name;
@ApiModelProperty(value = "表描述", required = true, example = "芋道源码")
private String comment;
}

View File

@ -1,25 +0,0 @@
package cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
@ApiModel("管理后台 - 数据字典的表定义 Response VO")
@Data
public class SchemaTableRespVO {
@ApiModelProperty(value = "数据库", required = true, example = "yudao")
private String tableSchema;
@ApiModelProperty(value = "表名称", required = true, example = "yuanma")
private String tableName;
@ApiModelProperty(value = "表描述", required = true, example = "芋道源码")
private String tableComment;
@ApiModelProperty(value = "创建时间", required = true)
private Date createTime;
}

View File

@ -68,15 +68,15 @@ public class ConfigController {
}
@GetMapping(value = "/get-value-by-key")
@ApiOperation(value = "根据参数键名查询参数值", notes = "敏感配置,不允许返回给前端")
@ApiOperation(value = "根据参数键名查询参数值", notes = "不可见的配置,不允许返回给前端")
@ApiImplicitParam(name = "key", value = "参数键", required = true, example = "yunai.biz.username", dataTypeClass = String.class)
public CommonResult<String> getConfigKey(@RequestParam("key") String key) {
ConfigDO config = configService.getConfigByKey(key);
if (config == null) {
return null;
}
if (config.getSensitive()) {
throw ServiceExceptionUtil.exception(ErrorCodeConstants.CONFIG_GET_VALUE_ERROR_IF_SENSITIVE);
if (config.getVisible()) {
throw ServiceExceptionUtil.exception(ErrorCodeConstants.CONFIG_GET_VALUE_ERROR_IF_VISIBLE);
}
return success(config.getValue());
}

View File

@ -18,7 +18,7 @@ public class ConfigBaseVO {
@ApiModelProperty(value = "参数分组", required = true, example = "biz")
@NotEmpty(message = "参数分组不能为空")
@Size(max = 50, message = "参数名称不能超过50个字符")
private String group;
private String category;
@ApiModelProperty(value = "参数名称", required = true, example = "数据库名")
@NotBlank(message = "参数名称不能为空")
@ -32,7 +32,7 @@ public class ConfigBaseVO {
@ApiModelProperty(value = "是否敏感", required = true, example = "true")
@NotNull(message = "是否敏感不能为空")
private Boolean sensitive;
private Boolean visible;
@ApiModelProperty(value = "备注", example = "备注一下很帅气!")
private String remark;

View File

@ -18,7 +18,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
@ToString(callSuper = true)
public class ConfigPageReqVO extends PageParam {
@ApiModelProperty(value = "数名称", example = "模糊匹配")
@ApiModelProperty(value = "据源名称", example = "模糊匹配")
private String name;
@ApiModelProperty(value = "参数键名", example = "yunai.db.username", notes = "模糊匹配")

View File

@ -0,0 +1,73 @@
package cn.iocoder.yudao.module.infra.controller.admin.db;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigCreateReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigRespVO;
import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigUpdateReqVO;
import cn.iocoder.yudao.module.infra.convert.db.DataSourceConfigConvert;
import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO;
import cn.iocoder.yudao.module.infra.service.db.DataSourceConfigService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Api(tags = "管理后台 - 数据源配置")
@RestController
@RequestMapping("/infra/data-source-config")
@Validated
public class DataSourceConfigController {
@Resource
private DataSourceConfigService dataSourceConfigService;
@PostMapping("/create")
@ApiOperation("创建数据源配置")
@PreAuthorize("@ss.hasPermission('infra:data-source-config:create')")
public CommonResult<Long> createDataSourceConfig(@Valid @RequestBody DataSourceConfigCreateReqVO createReqVO) {
return success(dataSourceConfigService.createDataSourceConfig(createReqVO));
}
@PutMapping("/update")
@ApiOperation("更新数据源配置")
@PreAuthorize("@ss.hasPermission('infra:data-source-config:update')")
public CommonResult<Boolean> updateDataSourceConfig(@Valid @RequestBody DataSourceConfigUpdateReqVO updateReqVO) {
dataSourceConfigService.updateDataSourceConfig(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@ApiOperation("删除数据源配置")
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('infra:data-source-config:delete')")
public CommonResult<Boolean> deleteDataSourceConfig(@RequestParam("id") Long id) {
dataSourceConfigService.deleteDataSourceConfig(id);
return success(true);
}
@GetMapping("/get")
@ApiOperation("获得数据源配置")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('infra:data-source-config:query')")
public CommonResult<DataSourceConfigRespVO> getDataSourceConfig(@RequestParam("id") Long id) {
DataSourceConfigDO dataSourceConfig = dataSourceConfigService.getDataSourceConfig(id);
return success(DataSourceConfigConvert.INSTANCE.convert(dataSourceConfig));
}
@GetMapping("/list")
@ApiOperation("获得数据源配置列表")
@PreAuthorize("@ss.hasPermission('infra:data-source-config:query')")
public CommonResult<List<DataSourceConfigRespVO>> getDataSourceConfigList() {
List<DataSourceConfigDO> list = dataSourceConfigService.getDataSourceConfigList();
return success(DataSourceConfigConvert.INSTANCE.convertList(list));
}
}

View File

@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.infra.controller.admin.doc;
package cn.iocoder.yudao.module.infra.controller.admin.db;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
@ -30,7 +30,7 @@ import java.util.Arrays;
@Api(tags = "管理后台 - 数据库文档")
@RestController
@RequestMapping("/infra/db-doc")
public class DbDocController {
public class DatabaseDocController {
@Resource
private DynamicDataSourceProperties dynamicDataSourceProperties;

View File

@ -0,0 +1,27 @@
package cn.iocoder.yudao.module.infra.controller.admin.db.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
/**
* 数据源配置 Base VO提供给添加修改详细的子 VO 使用
* 如果子 VO 存在差异的字段请不要添加到这里影响 Swagger 文档生成
*/
@Data
public class DataSourceConfigBaseVO {
@ApiModelProperty(value = "数据源名称", required = true, example = "test")
@NotNull(message = "数据源名称不能为空")
private String name;
@ApiModelProperty(value = "数据源连接", required = true, example = "jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro")
@NotNull(message = "数据源连接不能为空")
private String url;
@ApiModelProperty(value = "用户名", required = true, example = "root")
@NotNull(message = "用户名不能为空")
private String username;
}

View File

@ -0,0 +1,18 @@
package cn.iocoder.yudao.module.infra.controller.admin.db.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
@ApiModel("管理后台 - 数据源配置创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DataSourceConfigCreateReqVO extends DataSourceConfigBaseVO {
@ApiModelProperty(value = "密码", required = true, example = "123456")
@NotNull(message = "密码不能为空")
private String password;
}

View File

@ -0,0 +1,19 @@
package cn.iocoder.yudao.module.infra.controller.admin.db.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
@ApiModel("管理后台 - 数据源配置 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DataSourceConfigRespVO extends DataSourceConfigBaseVO {
@ApiModelProperty(value = "主键编号", required = true, example = "1024")
private Integer id;
@ApiModelProperty(value = "创建时间", required = true)
private Date createTime;
}

View File

@ -0,0 +1,22 @@
package cn.iocoder.yudao.module.infra.controller.admin.db.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
@ApiModel("管理后台 - 数据源配置更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DataSourceConfigUpdateReqVO extends DataSourceConfigBaseVO {
@ApiModelProperty(value = "主键编号", required = true, example = "1024")
@NotNull(message = "主键编号不能为空")
private Long id;
@ApiModelProperty(value = "密码", required = true, example = "123456")
@NotNull(message = "密码不能为空")
private String password;
}

View File

@ -6,12 +6,14 @@ import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.CodegenPreviewR
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.CodegenUpdateReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.column.CodegenColumnRespVO;
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.CodegenTableRespVO;
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.SchemaTableRespVO;
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.DatabaseTableRespVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaColumnDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaTableDO;
import com.baomidou.mybatisplus.generator.config.po.TableField;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
import java.util.List;
@ -23,13 +25,27 @@ public interface CodegenConvert {
CodegenConvert INSTANCE = Mappers.getMapper(CodegenConvert.class);
// ========== InformationSchemaTableDO InformationSchemaColumnDO 相关 ==========
// ========== TableInfo 相关 ==========
CodegenTableDO convert(SchemaTableDO bean);
@Mappings({
@Mapping(source = "name", target = "tableName"),
@Mapping(source = "comment", target = "tableComment"),
})
CodegenTableDO convert(TableInfo bean);
List<CodegenColumnDO> convertList(List<SchemaColumnDO> list);
List<CodegenColumnDO> convertList(List<TableField> list);
CodegenTableRespVO convert(SchemaColumnDO bean);
@Mappings({
@Mapping(source = "name", target = "columnName"),
@Mapping(source = "type", target = "dataType"),
@Mapping(source = "comment", target = "columnComment"),
@Mapping(source = "metaInfo.nullable", target = "nullable"),
@Mapping(source = "keyFlag", target = "primaryKey"),
@Mapping(source = "keyIdentityFlag", target = "autoIncrement"),
@Mapping(source = "columnType.type", target = "javaType"),
@Mapping(source = "propertyName", target = "javaField"),
})
CodegenColumnDO convert(TableField bean);
// ========== CodegenTableDO 相关 ==========
@ -47,7 +63,7 @@ public interface CodegenConvert {
List<CodegenColumnDO> convertList03(List<CodegenUpdateReqVO.Column> columns);
List<SchemaTableRespVO> convertList04(List<SchemaTableDO> list);
List<DatabaseTableRespVO> convertList04(List<TableInfo> list);
// ========== 其它 ==========

View File

@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigRespVO;
import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigUpdateReqVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.config.ConfigDO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
import java.util.List;
@ -18,12 +19,15 @@ public interface ConfigConvert {
PageResult<ConfigRespVO> convertPage(PageResult<ConfigDO> page);
@Mapping(source = "configKey", target = "key")
ConfigRespVO convert(ConfigDO bean);
@Mapping(source = "key", target = "configKey")
ConfigDO convert(ConfigCreateReqVO bean);
ConfigDO convert(ConfigUpdateReqVO bean);
@Mapping(source = "configKey", target = "key")
List<ConfigExcelVO> convertList(List<ConfigDO> list);
}

View File

@ -0,0 +1,30 @@
package cn.iocoder.yudao.module.infra.convert.db;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import cn.iocoder.yudao.module.infra.controller.admin.db.vo.*;
import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO;
/**
* 数据源配置 Convert
*
* @author 芋道源码
*/
@Mapper
public interface DataSourceConfigConvert {
DataSourceConfigConvert INSTANCE = Mappers.getMapper(DataSourceConfigConvert.class);
DataSourceConfigDO convert(DataSourceConfigCreateReqVO bean);
DataSourceConfigDO convert(DataSourceConfigUpdateReqVO bean);
DataSourceConfigRespVO convert(DataSourceConfigDO bean);
List<DataSourceConfigRespVO> convertList(List<DataSourceConfigDO> list);
}

View File

@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.infra.dal.dataobject.codegen;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenColumnHtmlTypeEnum;
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenColumnListConditionEnum;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@ -15,6 +16,7 @@ import lombok.experimental.Accessors;
* @author 芋道源码
*/
@TableName(value = "infra_codegen_column", autoResultMap = true)
@KeySequence("infra_codegen_column_seq") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
@ -41,7 +43,7 @@ public class CodegenColumnDO extends BaseDO {
/**
* 字段类型
*/
private String columnType;
private String dataType;
/**
* 字段描述
*/
@ -74,7 +76,6 @@ public class CodegenColumnDO extends BaseDO {
/**
* Java 属性名
*/
// @NotBlank(message = "Java属性不能为空")
private String javaField;
/**
* 字典类型

View File

@ -1,8 +1,10 @@
package cn.iocoder.yudao.module.infra.dal.dataobject.codegen;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO;
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenSceneEnum;
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -14,6 +16,7 @@ import lombok.experimental.Accessors;
* @author 芋道源码
*/
@TableName(value = "infra_codegen_table", autoResultMap = true)
@KeySequence("infra_codegen_table_seq") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
@ -25,11 +28,11 @@ public class CodegenTableDO extends BaseDO {
private Long id;
/**
* 导入类型
* 数据源编号
*
* 枚举 {@link CodegenTemplateTypeEnum}
* 关联 {@link DataSourceConfigDO#getId()}
*/
private Integer importType;
private Long dataSourceConfigId;
/**
* 生成场景
*

View File

@ -1,54 +0,0 @@
package cn.iocoder.yudao.module.infra.dal.dataobject.codegen;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Builder;
import lombok.Data;
/**
* MySQL 数据库中的 column 字段定义
*
* @author 芋道源码
*/
@TableName(value = "information_schema.columns", autoResultMap = true)
@Data
@Builder
public class SchemaColumnDO {
/**
* 表名称
*/
private String tableName;
/**
* 字段名
*/
private String columnName;
/**
* 字段类型
*/
private String columnType;
/**
* 字段描述
*/
private String columnComment;
/**
* 是否允许为空
*/
@TableField("case when is_nullable = 'yes' then '1' else '0' end")
private Boolean nullable;
/**
* 是否主键
*/
@TableField("case when column_key = 'PRI' then '1' else '0' end")
private Boolean primaryKey;
/**
* 是否自增
*/
@TableField("case when extra = 'auto_increment' then '1' else '0' end")
private Boolean autoIncrement;
/**
* 排序字段
*/
private Integer ordinalPosition;
}

View File

@ -1,36 +0,0 @@
package cn.iocoder.yudao.module.infra.dal.dataobject.codegen;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Builder;
import lombok.Data;
import java.util.Date;
/**
* MySQL 数据库中的 table 表定义
*
* @author 芋道源码
*/
@TableName(value = "information_schema.tables", autoResultMap = true)
@Data
@Builder
public class SchemaTableDO {
/**
* 数据库
*/
private String tableSchema;
/**
* 表名称
*/
private String tableName;
/**
* 表描述
*/
private String tableComment;
/**
* 创建时间
*/
private Date createTime;
}

View File

@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.infra.dal.dataobject.config;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.module.infra.enums.config.ConfigTypeEnum;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@ -15,6 +15,7 @@ import lombok.ToString;
* @author 芋道源码
*/
@TableName("infra_config")
@KeySequence("infra_config_seq") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@ -26,19 +27,19 @@ public class ConfigDO extends BaseDO {
@TableId
private Long id;
/**
* 参数分
* 参数分
*/
@TableField("`group`")
private String group;
private String category;
/**
* 参数名称
*/
private String name;
/**
* 参数键名
*
* 支持多 DB 类型时无法直接使用 key + @TableField("config_key") 来实现转换原因是 "config_key" AS key 而存在报错
*/
@TableField("`key`")
private String key;
private String configKey;
/**
* 参数键值
*/
@ -48,15 +49,13 @@ public class ConfigDO extends BaseDO {
*
* 枚举 {@link ConfigTypeEnum}
*/
@TableField("`type`")
private Integer type;
/**
* 是否敏感
* 是否可见
*
* 对于敏感配置需要管理权限才能查看
* 不可见的参数一般是敏感参数前端不可获取
*/
@TableField("`sensitive`")
private Boolean sensitive;
private Boolean visible;
/**
* 备注
*/

View File

@ -0,0 +1,45 @@
package cn.iocoder.yudao.module.infra.dal.dataobject.db;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* 数据源配置
*
* @author 芋道源码
*/
@TableName("infra_data_source_config")
@KeySequence("infra_data_source_config_seq") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写
@Data
public class DataSourceConfigDO extends BaseDO {
/**
* 主键编号 - Master 数据源
*/
public static final Long ID_MASTER = 0L;
/**
* 主键编号
*/
private Long id;
/**
* 连接名
*/
private String name;
/**
* 数据源连接
*/
private String url;
/**
* 用户名
*/
private String username;
/**
* 密码
*/
private String password;
}

View File

@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.infra.dal.dataobject.file;
import cn.iocoder.yudao.framework.file.core.client.FileClientConfig;
import cn.iocoder.yudao.framework.file.core.enums.FileStorageEnum;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
@ -13,8 +14,9 @@ import lombok.*;
*
* @author 芋道源码
*/
@Data
@TableName(value = "infra_file_config", autoResultMap = true)
@KeySequence("infra_file_config_seq") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder

View File

@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.infra.dal.dataobject.file;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
@ -13,8 +14,9 @@ import lombok.*;
*
* @author 芋道源码
*/
@Data
@TableName("infra_file_content")
@KeySequence("infra_file_content_seq") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder

View File

@ -1,7 +1,7 @@
package cn.iocoder.yudao.module.infra.dal.dataobject.file;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
@ -13,8 +13,9 @@ import java.io.InputStream;
*
* @author 芋道源码
*/
@Data
@TableName("infra_file")
@KeySequence("infra_file_seq") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@ -45,7 +46,6 @@ public class FileDO extends BaseDO {
*
* 通过 {@link cn.hutool.core.io.FileTypeUtil#getType(InputStream)} 获取
*/
@TableField(value = "`type`")
private String type;
/**
* 文件大小

View File

@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.infra.dal.dataobject.job;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.module.infra.enums.job.JobStatusEnum;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
@ -12,6 +13,7 @@ import lombok.*;
* @author 芋道源码
*/
@TableName("infra_job")
@KeySequence("infra_job_seq") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)

View File

@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.infra.dal.dataobject.job;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
import cn.iocoder.yudao.module.infra.enums.job.JobLogStatusEnum;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
@ -14,6 +15,7 @@ import java.util.Date;
* @author 芋道源码
*/
@TableName("infra_job_log")
@KeySequence("infra_job_log_seq") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)

View File

@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.infra.dal.dataobject.logger;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
@ -15,6 +16,7 @@ import java.util.Date;
* @author 芋道源码
*/
@TableName("infra_api_access_log")
@KeySequence(value = "infra_api_access_log_seq")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)

View File

@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.infra.dal.dataobject.logger;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.module.infra.enums.logger.ApiErrorLogProcessStatusEnum;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
@ -21,6 +22,7 @@ import java.util.Date;
@Builder
@NoArgsConstructor
@AllArgsConstructor
@KeySequence(value = "infra_api_error_log_seq")
public class ApiErrorLogDO extends BaseDO {
/**

View File

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.infra.dal.dataobject.test;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
@ -11,6 +12,7 @@ import lombok.*;
* @author 芋道源码
*/
@TableName("infra_test_demo")
@KeySequence("infra_test_demo_seq") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)

View File

@ -1,8 +1,8 @@
package cn.iocoder.yudao.module.infra.dal.mysql.codegen;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@ -11,12 +11,14 @@ import java.util.List;
public interface CodegenColumnMapper extends BaseMapperX<CodegenColumnDO> {
default List<CodegenColumnDO> selectListByTableId(Long tableId) {
return selectList(new QueryWrapper<CodegenColumnDO>().eq("table_id", tableId)
.orderByAsc("ordinal_position"));
return selectList(new LambdaQueryWrapperX<CodegenColumnDO>()
.eq(CodegenColumnDO::getTableId, tableId)
.orderByAsc(CodegenColumnDO::getId));
}
default void deleteListByTableId(Long tableId) {
delete(new QueryWrapper<CodegenColumnDO>().eq("table_id", tableId));
delete(new LambdaQueryWrapperX<CodegenColumnDO>()
.eq(CodegenColumnDO::getTableId, tableId));
}
}

View File

@ -2,24 +2,30 @@ package cn.iocoder.yudao.module.infra.dal.mysql.codegen;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.CodegenTablePageReqVO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface CodegenTableMapper extends BaseMapperX<CodegenTableDO> {
default CodegenTableDO selectByTableName(String tableName) {
return selectOne(new QueryWrapper<CodegenTableDO>().eq("table_name", tableName));
default CodegenTableDO selectByTableNameAndDataSourceConfigId(String tableName, Long dataSourceConfigId) {
return selectOne(CodegenTableDO::getTableName, tableName,
CodegenTableDO::getDataSourceConfigId, dataSourceConfigId);
}
default PageResult<CodegenTableDO> selectPage(CodegenTablePageReqVO pageReqVO) {
return selectPage(pageReqVO, new QueryWrapperX<CodegenTableDO>()
.likeIfPresent("table_name", pageReqVO.getTableName())
.likeIfPresent("table_comment", pageReqVO.getTableComment())
.betweenIfPresent("create_time", pageReqVO.getBeginCreateTime(), pageReqVO.getEndCreateTime()));
return selectPage(pageReqVO, new LambdaQueryWrapperX<CodegenTableDO>()
.likeIfPresent(CodegenTableDO::getTableName, pageReqVO.getTableName())
.likeIfPresent(CodegenTableDO::getTableComment, pageReqVO.getTableComment())
.betweenIfPresent(CodegenTableDO::getCreateTime, pageReqVO.getBeginCreateTime(), pageReqVO.getEndCreateTime()));
}
default List<CodegenTableDO> selectListByDataSourceConfigId(Long dataSourceConfigId) {
return selectList(CodegenTableDO::getDataSourceConfigId, dataSourceConfigId);
}
}

View File

@ -1,19 +0,0 @@
package cn.iocoder.yudao.module.infra.dal.mysql.codegen;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaColumnDO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface SchemaColumnMapper extends BaseMapperX<SchemaColumnDO> {
default List<SchemaColumnDO> selectListByTableName(String tableSchema, String tableName) {
return selectList(new QueryWrapper<SchemaColumnDO>().eq("table_name", tableName)
.eq("table_schema", tableSchema)
.orderByAsc("ordinal_position"));
}
}

View File

@ -1,26 +0,0 @@
package cn.iocoder.yudao.module.infra.dal.mysql.codegen;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaTableDO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.ibatis.annotations.Mapper;
import java.util.Collection;
import java.util.List;
@Mapper
public interface SchemaTableMapper extends BaseMapperX<SchemaTableDO> {
default List<SchemaTableDO> selectList(Collection<String> tableSchemas, String tableName, String tableComment) {
return selectList(new QueryWrapperX<SchemaTableDO>().in("table_schema", tableSchemas)
.likeIfPresent("table_name", tableName)
.likeIfPresent("table_comment", tableComment));
}
default SchemaTableDO selectByTableSchemaAndTableName(String tableSchema, String tableName) {
return selectOne(new QueryWrapper<SchemaTableDO>().eq("table_schema",tableSchema)
.eq("table_name", tableName));
}
}

View File

@ -2,12 +2,10 @@ package cn.iocoder.yudao.module.infra.dal.mysql.config;
import cn.iocoder.yudao.framework.apollo.internals.ConfigFrameworkDAO;
import cn.iocoder.yudao.framework.apollo.internals.dto.ConfigRespDTO;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import javax.sql.DataSource;
import java.sql.ResultSet;
import java.util.Date;
import java.util.List;
@ -26,14 +24,18 @@ public class ConfigDAOImpl implements ConfigFrameworkDAO {
}
@Override
public boolean selectExistsByUpdateTimeAfter(Date maxUpdateTime) {
return jdbcTemplate.query("SELECT id FROM infra_config WHERE update_time > ? LIMIT 1",
ResultSet::next, maxUpdateTime);
public int selectCountByUpdateTimeGt(Date maxUpdateTime) {
return jdbcTemplate.queryForObject("SELECT COUNT(*) FROM infra_config WHERE update_time > ?",
Integer.class, maxUpdateTime);
}
@Override
public List<ConfigRespDTO> selectList() {
return jdbcTemplate.query("SELECT `key`, `value`, update_time, deleted FROM infra_config", new BeanPropertyRowMapper<>(ConfigRespDTO.class));
return jdbcTemplate.query("SELECT config_key, value, update_time, deleted FROM infra_config",
(rs, rowNum) -> new ConfigRespDTO().setKey(rs.getString("config_key"))
.setValue(rs.getString("value"))
.setUpdateTime(rs.getDate("update_time"))
.setDeleted(rs.getBoolean("deleted")));
}
}

View File

@ -2,11 +2,10 @@ package cn.iocoder.yudao.module.infra.dal.mysql.config;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigExportReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigPageReqVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.config.ConfigDO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@ -15,23 +14,23 @@ import java.util.List;
public interface ConfigMapper extends BaseMapperX<ConfigDO> {
default ConfigDO selectByKey(String key) {
return selectOne(new QueryWrapper<ConfigDO>().eq("`key`", key));
return selectOne(ConfigDO::getConfigKey, key);
}
default PageResult<ConfigDO> selectPage(ConfigPageReqVO reqVO) {
return selectPage(reqVO, new QueryWrapperX<ConfigDO>()
.likeIfPresent("name", reqVO.getName())
.likeIfPresent("`key`", reqVO.getKey())
.eqIfPresent("`type`", reqVO.getType())
.betweenIfPresent("create_time", reqVO.getBeginTime(), reqVO.getEndTime()));
return selectPage(reqVO, new LambdaQueryWrapperX<ConfigDO>()
.likeIfPresent(ConfigDO::getName, reqVO.getName())
.likeIfPresent(ConfigDO::getConfigKey, reqVO.getKey())
.eqIfPresent(ConfigDO::getType, reqVO.getType())
.betweenIfPresent(ConfigDO::getCreateTime, reqVO.getBeginTime(), reqVO.getEndTime()));
}
default List<ConfigDO> selectList(ConfigExportReqVO reqVO) {
return selectList(new QueryWrapperX<ConfigDO>()
.likeIfPresent("name", reqVO.getName())
.likeIfPresent("`key`", reqVO.getKey())
.eqIfPresent("`type`", reqVO.getType())
.betweenIfPresent("create_time", reqVO.getBeginTime(), reqVO.getEndTime()));
return selectList(new LambdaQueryWrapperX<ConfigDO>()
.likeIfPresent(ConfigDO::getName, reqVO.getName())
.likeIfPresent(ConfigDO::getConfigKey, reqVO.getKey())
.eqIfPresent(ConfigDO::getType, reqVO.getType())
.betweenIfPresent(ConfigDO::getCreateTime, reqVO.getBeginTime(), reqVO.getEndTime()));
}
}

View File

@ -0,0 +1,14 @@
package cn.iocoder.yudao.module.infra.dal.mysql.db;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO;
import org.apache.ibatis.annotations.Mapper;
/**
* 数据源配置 Mapper
*
* @author 芋道源码
*/
@Mapper
public interface DataSourceConfigMapper extends BaseMapperX<DataSourceConfigDO> {
}

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