Commit 0acea1ab by zhangdaiscott

JeecgBoot低代码平台 3.0版本发布—新里程牌开始,迎接VUE3版本到来!!

parent 9760185b
Jeecg-Boot 低代码开发平台
===============
当前最新版本: 2.4.6(发布日期:20210813
当前最新版本: 3.0(发布日期:2021-11-01
## 后端技术架构
- 基础框架:Spring Boot 2.3.5.RELEASE
- 持久层框架:Mybatis-plus 3.4.3.1
- 持久层框架:Mybatis-plus 3.4.1
- 安全框架:Apache Shiro 1.7.0,Jwt 3.11.0
......@@ -29,7 +29,7 @@ Jeecg-Boot 低代码开发平台
- 依赖管理:Maven
- 数据库:MySQL5.7+ & Oracle 11g & SqlServer & postgresql
- 数据库:MySQL5.7+ & Oracle 11g & SqlServer & postgresql & 国产等更多数据库
- 缓存:Redis
......@@ -43,7 +43,7 @@ Jeecg-Boot 低代码开发平台
- 常见问题: [http://jeecg.com/doc/qa](http://jeecg.com/doc/qa)
- QQ交流群 : ④774126647、③816531124、①284271917、②769925425
- QQ交流群 : ⑤860162132、④774126647(满)、③816531124(满)、②769925425(满)、①284271917(满)
## 专项文档
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -14,7 +14,7 @@ use `nacos`;
Target Server Version : 50727
File Encoding : 65001
Date: 13/08/2021 16:11:54
Date: 01/06/2021 15:44:04
*/
SET NAMES utf8mb4;
......@@ -30,8 +30,8 @@ CREATE TABLE `config_info` (
`group_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
`content` longtext CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT 'content',
`md5` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT 'md5',
`gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '修改时间',
`gmt_create` datetime(0) NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '创建时间',
`gmt_modified` datetime(0) NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '修改时间',
`src_user` text CHARACTER SET utf8 COLLATE utf8_bin NULL COMMENT 'source user',
`src_ip` varchar(20) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT 'source ip',
`app_name` varchar(128) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
......@@ -43,13 +43,13 @@ CREATE TABLE `config_info` (
`c_schema` text CHARACTER SET utf8 COLLATE utf8_bin NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `uk_configinfo_datagrouptenant`(`data_id`, `group_id`, `tenant_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 9 CHARACTER SET = utf8 COLLATE = utf8_bin COMMENT = 'config_info' ROW_FORMAT = Dynamic;
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_bin COMMENT = 'config_info' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of config_info
-- ----------------------------
INSERT INTO `config_info` VALUES (1, 'jeecg-dev.yaml', 'DEFAULT_GROUP', 'spring:\n datasource:\n druid:\n stat-view-servlet:\n enabled: true\n loginUsername: admin\n loginPassword: 123456\n allow:\n web-stat-filter:\n enabled: true\n dynamic:\n druid: # 全局druid参数,绝大部分值和默认保持一致。(现已支持的参数如下,不清楚含义不要乱设置)\n # 连接池的配置信息\n # 初始化大小,最小,最大\n initial-size: 5\n min-idle: 5\n maxActive: 20\n # 配置获取连接等待超时的时间\n maxWait: 60000\n # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒\n timeBetweenEvictionRunsMillis: 60000\n # 配置一个连接在池中最小生存的时间,单位是毫秒\n minEvictableIdleTimeMillis: 300000\n validationQuery: SELECT 1 FROM DUAL\n testWhileIdle: true\n testOnBorrow: false\n testOnReturn: false\n # 打开PSCache,并且指定每个连接上PSCache的大小\n poolPreparedStatements: true\n maxPoolPreparedStatementPerConnectionSize: 20\n # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,\'wall\'用于防火墙\n filters: stat,wall,slf4j\n # 通过connectProperties属性来打开mergeSql功能;慢SQL记录\n connectionProperties: druid.stat.mergeSql\\=true;druid.stat.slowSqlMillis\\=5000\n\n datasource:\n master:\n url: jdbc:mysql://jeecg-boot-mysql:3306/jeecg-boot?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai\n username: root\n password: root\n driver-class-name: com.mysql.cj.jdbc.Driver\n # 多数据源配置\n #multi-datasource1:\n #url: jdbc:mysql://localhost:3306/jeecg-boot2?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai\n #username: root\n #password: root\n #driver-class-name: com.mysql.cj.jdbc.Driver\n #redis 配置\n redis:\n database: 0\n host: jeecg-boot-redis\n lettuce:\n pool:\n max-active: 8 #最大连接数据库连接数,设 0 为没有限制\n max-idle: 8 #最大等待连接中的数量,设 0 为没有限制\n max-wait: -1ms #最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。\n min-idle: 0 #最小等待连接中的数量,设 0 为没有限制\n shutdown-timeout: 100ms\n password:\n port: 6379\n #rabbitmq配置\n rabbitmq:\n host: 127.0.0.1\n username: guest\n password: guest\n port: 5672\n publisher-confirms: true\n publisher-returns: true\n virtual-host: /\n listener:\n simple:\n acknowledge-mode: manual\n #消费者的最小数量\n concurrency: 1\n #消费者的最大数量\n max-concurrency: 1\n #是否支持重试\n retry:\n enabled: true\n#jeecg专用配置\nminidao :\n base-package: org.jeecg.modules.jmreport.*\njeecg :\n # 签名密钥串(前后端要一致,正式发布请自行修改)\n signatureSecret: dd05f1c54d63749eda95f9fa6d49v442a\n # 本地:local\\Minio:minio\\阿里云:alioss\n uploadType: local\n path :\n #文件上传根目录 设置\n upload: /opt/upFiles\n #webapp文件路径\n webapp: /opt/webapp\n shiro:\n excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/category/**,/visual/**,/map/**,/jmreport/bigscreen2/**\n #阿里云oss存储配置\n oss:\n endpoint: oss-cn-beijing.aliyuncs.com\n accessKey: ??\n secretKey: ??\n bucketName: jeecgdev\n staticDomain: ??\n # ElasticSearch 6设置\n elasticsearch:\n cluster-name: jeecg-ES\n cluster-nodes: 127.0.0.1:9200\n check-enabled: false\n # 表单设计器配置\n desform:\n # 主题颜色(仅支持 16进制颜色代码)\n theme-color: \"#1890ff\"\n # 文件、图片上传方式,可选项:qiniu(七牛云)、system(跟随系统配置)\n upload-type: system\n map:\n # 配置百度地图的AK,申请地址:https://lbs.baidu.com/apiconsole/key?application=key#/home\n baidu: ??\n # 在线预览文件服务器地址配置\n file-view-domain: 127.0.0.1:8012\n # minio文件上传\n minio:\n minio_url: http://minio.jeecg.com\n minio_name: ??\n minio_pass: ??\n bucketName: otatest\n #大屏报表参数设置\n jmreport:\n mode: dev\n #是否需要校验token\n is_verify_token: false\n #必须校验方法\n verify_methods: remove,delete,save,add,update\n #Wps在线文档\n wps:\n domain: https://wwo.wps.cn/office/\n appid: ??\n appsecret: ??\n #xxl-job配置\n xxljob:\n enabled: false\n adminAddresses: http://jeecg-boot-xxljob:9080/xxl-job-admin\n appname: ${spring.application.name}\n accessToken: \'\'\n logPath: logs/jeecg/job/jobhandler/\n logRetentionDays: 30\n #自定义路由配置 yml nacos database\n route:\n config:\n data-id: jeecg-gateway-router\n group: DEFAULT_GROUP\n data-type: database\n #分布式锁配置\n redisson:\n address: jeecg-boot-redis:6379\n password:\n type: STANDALONE\n enabled: true\n#Mybatis输出sql日志\nlogging:\n level:\n org.jeecg.modules.system.mapper : info\n#cas单点登录\ncas:\n prefixUrl: http://localhost:8888/cas\n#swagger\nknife4j:\n #开启生产环境屏蔽\n production: false\n basic:\n enable: false\n username: jeecg\n password: jeecg1314\n\n#第三方登录\njustauth:\n enabled: true\n type:\n GITHUB:\n client-id: ??\n client-secret: ??\n redirect-uri: http://sso.test.com:8080/jeecg-boot/thirdLogin/github/callback\n WECHAT_ENTERPRISE:\n client-id: ??\n client-secret: ??\n redirect-uri: http://sso.test.com:8080/jeecg-boot/thirdLogin/wechat_enterprise/callback\n agent-id: 1000002\n DINGTALK:\n client-id: ??\n client-secret: ??\n redirect-uri: http://sso.test.com:8080/jeecg-boot/thirdLogin/dingtalk/callback\n cache:\n type: default\n prefix: \'demo::\'\n timeout: 1h\n#第三方APP对接\nthird-app:\n enabled: false\n type:\n #企业微信\n WECHAT_ENTERPRISE:\n enabled: false\n #CORP_ID\n client-id: ??\n #SECRET\n client-secret: ??\n agent-id: ??\n #自建应用秘钥(新版企微需要配置)\n # agent-app-secret: ??\n #钉钉\n DINGTALK:\n enabled: false\n # appKey\n client-id: ??\n # appSecret\n client-secret: ??\n agent-id: ??', '8b05ed4ee8ecbc4e7a4d425190b60273', '2021-03-03 13:01:11', '2021-08-13 08:10:45', NULL, '0:0:0:0:0:0:0:1', '', '', '', '', '', 'yaml', '');
INSERT INTO `config_info` VALUES (2, 'jeecg.yaml', 'DEFAULT_GROUP', 'server:\n tomcat:\n max-swallow-size: -1\n error:\n include-exception: true\n include-stacktrace: ALWAYS\n include-message: ALWAYS\n compression:\n enabled: true\n min-response-size: 1024\n mime-types: application/javascript,application/json,application/xml,text/html,text/xml,text/plain,text/css,image/*\nmanagement:\n health:\n mail:\n enabled: false\n endpoints:\n web:\n exposure:\n include: \"*\" #暴露所有节点\n health:\n sensitive: true #关闭过滤敏感信息\n endpoint:\n health:\n show-details: ALWAYS #显示详细信息\nspring:\n servlet:\n multipart:\n max-file-size: 10MB\n max-request-size: 10MB\n mail:\n host: smtp.163.com\n username: jeecgos@163.com\n password: ??\n properties:\n mail:\n smtp:\n auth: true\n starttls:\n enable: true\n required: true\n ## quartz定时任务,采用数据库方式\n quartz:\n job-store-type: jdbc\n initialize-schema: embedded\n #设置自动启动,默认为 true\n auto-startup: false\n #启动时更新己存在的Job\n overwrite-existing-jobs: true\n properties:\n org:\n quartz:\n scheduler:\n instanceName: MyScheduler\n instanceId: AUTO\n jobStore:\n class: org.quartz.impl.jdbcjobstore.JobStoreTX\n driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate\n tablePrefix: QRTZ_\n isClustered: true\n misfireThreshold: 60000\n clusterCheckinInterval: 10000\n threadPool:\n class: org.quartz.simpl.SimpleThreadPool\n threadCount: 10\n threadPriority: 5\n threadsInheritContextClassLoaderOfInitializingThread: true\n #json 时间戳统一转换\n jackson:\n date-format: yyyy-MM-dd HH:mm:ss\n time-zone: GMT+8\n aop:\n proxy-target-class: true\n activiti:\n check-process-definitions: false\n #启用作业执行器\n async-executor-activate: false\n #启用异步执行器\n job-executor-activate: false\n jpa:\n open-in-view: false\n #配置freemarker\n freemarker:\n # 设置模板后缀名\n suffix: .ftl\n # 设置文档类型\n content-type: text/html\n # 设置页面编码格式\n charset: UTF-8\n # 设置页面缓存\n cache: false\n prefer-file-system-access: false\n # 设置ftl文件路径\n template-loader-path:\n - classpath:/templates\n # 设置静态文件路径,js,css等\n mvc:\n static-path-pattern: /**\n resource:\n static-locations: classpath:/static/,classpath:/public/\n autoconfigure:\n exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure\n#mybatis plus 设置\nmybatis-plus:\n mapper-locations: classpath*:org/jeecg/modules/**/xml/*Mapper.xml\n global-config:\n # 关闭MP3.0自带的banner\n banner: false\n db-config:\n #主键类型 0:\"数据库ID自增\",1:\"该类型为未设置主键类型\", 2:\"用户输入ID\",3:\"全局唯一ID (数字类型唯一ID)\", 4:\"全局唯一ID UUID\",5:\"字符串全局唯一ID (idWorker 的字符串表示)\";\n id-type: ASSIGN_ID\n # 默认数据库表下划线命名\n table-underline: true\n configuration:\n # 这个配置会将执行的sql打印出来,在开发或测试的时候可以用\n #log-impl: org.apache.ibatis.logging.stdout.StdOutImpl\n # 返回类型为Map,显示null对应的字段\n call-setters-on-nulls: true', '411f9c73fc519225add2f7c992279f6f', '2021-03-03 13:01:42', '2021-06-28 07:13:40', NULL, '0:0:0:0:0:0:0:1', '', '', '', '', '', 'yaml', '');
INSERT INTO `config_info` VALUES (1, 'jeecg-dev.yaml', 'DEFAULT_GROUP', 'spring:\n datasource:\n druid:\n stat-view-servlet:\n enabled: true\n loginUsername: admin\n loginPassword: 123456\n allow:\n web-stat-filter:\n enabled: true\n dynamic:\n druid: # 全局druid参数,绝大部分值和默认保持一致。(现已支持的参数如下,不清楚含义不要乱设置)\n # 连接池的配置信息\n # 初始化大小,最小,最大\n initial-size: 5\n min-idle: 5\n maxActive: 20\n # 配置获取连接等待超时的时间\n maxWait: 60000\n # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒\n timeBetweenEvictionRunsMillis: 60000\n # 配置一个连接在池中最小生存的时间,单位是毫秒\n minEvictableIdleTimeMillis: 300000\n validationQuery: SELECT 1 FROM DUAL\n testWhileIdle: true\n testOnBorrow: false\n testOnReturn: false\n # 打开PSCache,并且指定每个连接上PSCache的大小\n poolPreparedStatements: true\n maxPoolPreparedStatementPerConnectionSize: 20\n # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,\'wall\'用于防火墙\n filters: stat,wall,slf4j\n # 通过connectProperties属性来打开mergeSql功能;慢SQL记录\n connectionProperties: druid.stat.mergeSql\\=true;druid.stat.slowSqlMillis\\=5000\n\n datasource:\n master:\n url: jdbc:mysql://jeecg-boot-mysql:3306/jeecg-boot?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai\n username: root\n password: root\n driver-class-name: com.mysql.cj.jdbc.Driver\n # 多数据源配置\n #multi-datasource1:\n #url: jdbc:mysql://localhost:3306/jeecg-boot2?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai\n #username: root\n #password: root\n #driver-class-name: com.mysql.cj.jdbc.Driver\n #redis 配置\n redis:\n database: 0\n host: jeecg-boot-redis\n lettuce:\n pool:\n max-active: 8 #最大连接数据库连接数,设 0 为没有限制\n max-idle: 8 #最大等待连接中的数量,设 0 为没有限制\n max-wait: -1ms #最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。\n min-idle: 0 #最小等待连接中的数量,设 0 为没有限制\n shutdown-timeout: 100ms\n password:\n port: 6379\n #rabbitmq配置\n rabbitmq:\n host: 127.0.0.1\n username: guest\n password: guest\n port: 5672\n publisher-confirms: true\n publisher-returns: true\n virtual-host: /\n listener:\n simple:\n acknowledge-mode: manual\n #消费者的最小数量\n concurrency: 1\n #消费者的最大数量\n max-concurrency: 1\n #是否支持重试\n retry:\n enabled: true\n#jeecg专用配置\nminidao :\n base-package: org.jeecg.modules.jmreport.*\n #DB类型(mysql | postgresql | oracle | sqlserver| other)\n db-type: mysql\njeecg :\n # 本地:local\\Minio:minio\\阿里云:alioss\n uploadType: local\n path :\n #文件上传根目录 设置\n upload: D://opt//upFiles\n #webapp文件路径\n webapp: D://opt//webapp\n shiro:\n excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/category/**,/visual/**,/map/**,/jmreport/bigscreen2/**\n #阿里云oss存储配置\n oss:\n endpoint: oss-cn-beijing.aliyuncs.com\n accessKey: ??\n secretKey: ??\n bucketName: jeecgdev\n staticDomain: ??\n # ElasticSearch 6设置\n elasticsearch:\n cluster-name: jeecg-ES\n cluster-nodes: 127.0.0.1:9200\n check-enabled: false\n # 表单设计器配置\n desform:\n # 主题颜色(仅支持 16进制颜色代码)\n theme-color: \"#1890ff\"\n # 文件、图片上传方式,可选项:qiniu(七牛云)、system(跟随系统配置)\n upload-type: system\n map:\n # 配置百度地图的AK,申请地址:https://lbs.baidu.com/apiconsole/key?application=key#/home\n baidu: ??\n # 在线预览文件服务器地址配置\n file-view-domain: 127.0.0.1:8012\n # minio文件上传\n minio:\n minio_url: http://minio.jeecg.com\n minio_name: ??\n minio_pass: ??\n bucketName: otatest\n #大屏报表参数设置\n jmreport:\n mode: dev\n #是否需要校验token\n is_verify_token: false\n #必须校验方法\n verify_methods: remove,delete,save,add,update\n #Wps在线文档\n wps:\n domain: https://wwo.wps.cn/office/\n appid: ??\n appsecret: ??\n #xxl-job配置\n xxljob:\n enabled: true\n adminAddresses: http://jeecg-boot-xxljob:9080/xxl-job-admin\n appname: ${spring.application.name}\n accessToken: \'\'\n logPath: logs/jeecg/job/jobhandler/\n logRetentionDays: 30\n #自定义路由配置 yml nacos database\n route:\n config:\n data-id: jeecg-gateway-router\n group: DEFAULT_GROUP\n data-type: database\n #分布式锁配置\n redisson:\n address: jeecg-boot-redis:6379\n password:\n type: STANDALONE\n enabled: true\n#Mybatis输出sql日志\nlogging:\n level:\n org.jeecg.modules.system.mapper : info\n#cas单点登录\ncas:\n prefixUrl: http://localhost:8888/cas\n#swagger\nknife4j:\n production: false\n basic:\n enable: false\n username: jeecg\n password: jeecg1314\n\n#第三方登录\njustauth:\n enabled: true\n type:\n GITHUB:\n client-id: ??\n client-secret: ??\n redirect-uri: http://sso.test.com:8080/jeecg-boot/thirdLogin/github/callback\n WECHAT_ENTERPRISE:\n client-id: ??\n client-secret: ??\n redirect-uri: http://sso.test.com:8080/jeecg-boot/thirdLogin/wechat_enterprise/callback\n agent-id: 1000002\n DINGTALK:\n client-id: ??\n client-secret: ??\n redirect-uri: http://sso.test.com:8080/jeecg-boot/thirdLogin/dingtalk/callback\n cache:\n type: default\n prefix: \'demo::\'\n timeout: 1h\n#第三方APP对接\nthird-app:\n enabled: false\n type:\n #企业微信\n WECHAT_ENTERPRISE:\n enabled: false\n #CORP_ID\n client-id: ??\n #SECRET\n client-secret: ??\n agent-id: ??\n #自建应用秘钥(新版企微需要配置)\n # agent-app-secret: ??\n #钉钉\n DINGTALK:\n enabled: false\n # appKey\n client-id: ??\n # appSecret\n client-secret: ??\n agent-id: ??', '9140ac47638475ac08b332fffa0ca3ee', '2021-03-03 13:01:11', '2021-06-01 07:43:23', NULL, '0:0:0:0:0:0:0:1', '', '', '', '', '', 'yaml', '');
INSERT INTO `config_info` VALUES (2, 'jeecg.yaml', 'DEFAULT_GROUP', 'server:\r\n tomcat:\r\n max-swallow-size: -1\r\n error:\r\n include-exception: true\r\n include-stacktrace: ALWAYS\r\n include-message: ALWAYS\r\n compression:\r\n enabled: true\r\n min-response-size: 1024\r\n mime-types: application/javascript,application/json,application/xml,text/html,text/xml,text/plain,text/css,image/*\r\nmanagement:\r\n health:\r\n mail:\r\n enabled: false\r\n endpoints:\r\n web:\r\n exposure:\r\n include: \"*\" #暴露所有节点\r\n health:\r\n sensitive: true #关闭过滤敏感信息\r\n endpoint:\r\n health:\r\n show-details: ALWAYS #显示详细信息\r\nspring:\r\n servlet:\r\n multipart:\r\n max-file-size: 10MB\r\n max-request-size: 10MB\r\n mail:\r\n host: smtp.163.com\r\n username: jeecgos@163.com\r\n password: ??\r\n properties:\r\n mail:\r\n smtp:\r\n auth: true\r\n starttls:\r\n enable: true\r\n required: true\r\n ## quartz定时任务,采用数据库方式\r\n quartz:\r\n job-store-type: jdbc\r\n initialize-schema: embedded\r\n #设置自动启动,默认为 true\r\n auto-startup: true\r\n #启动时更新己存在的Job\r\n overwrite-existing-jobs: true\r\n properties:\r\n org:\r\n quartz:\r\n scheduler:\r\n instanceName: MyScheduler\r\n instanceId: AUTO\r\n jobStore:\r\n class: org.quartz.impl.jdbcjobstore.JobStoreTX\r\n driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate\r\n tablePrefix: QRTZ_\r\n isClustered: true\r\n misfireThreshold: 60000\r\n clusterCheckinInterval: 10000\r\n threadPool:\r\n class: org.quartz.simpl.SimpleThreadPool\r\n threadCount: 10\r\n threadPriority: 5\r\n threadsInheritContextClassLoaderOfInitializingThread: true\r\n #json 时间戳统一转换\r\n jackson:\r\n date-format: yyyy-MM-dd HH:mm:ss\r\n time-zone: GMT+8\r\n aop:\r\n proxy-target-class: true\r\n activiti:\r\n check-process-definitions: false\r\n #启用作业执行器\r\n async-executor-activate: false\r\n #启用异步执行器\r\n job-executor-activate: false\r\n jpa:\r\n open-in-view: false\r\n #配置freemarker\r\n freemarker:\r\n # 设置模板后缀名\r\n suffix: .ftl\r\n # 设置文档类型\r\n content-type: text/html\r\n # 设置页面编码格式\r\n charset: UTF-8\r\n # 设置页面缓存\r\n cache: false\r\n prefer-file-system-access: false\r\n # 设置ftl文件路径\r\n template-loader-path:\r\n - classpath:/templates\r\n # 设置静态文件路径,js,css等\r\n mvc:\r\n static-path-pattern: /**\r\n resource:\r\n static-locations: classpath:/static/,classpath:/public/\r\n autoconfigure:\r\n exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure\r\n#mybatis plus 设置\r\nmybatis-plus:\r\n mapper-locations: classpath*:org/jeecg/modules/**/xml/*Mapper.xml\r\n global-config:\r\n # 关闭MP3.0自带的banner\r\n banner: false\r\n db-config:\r\n #主键类型 0:\"数据库ID自增\",1:\"该类型为未设置主键类型\", 2:\"用户输入ID\",3:\"全局唯一ID (数字类型唯一ID)\", 4:\"全局唯一ID UUID\",5:\"字符串全局唯一ID (idWorker 的字符串表示)\";\r\n id-type: ASSIGN_ID\r\n # 默认数据库表下划线命名\r\n table-underline: true\r\n configuration:\r\n # 这个配置会将执行的sql打印出来,在开发或测试的时候可以用\r\n #log-impl: org.apache.ibatis.logging.stdout.StdOutImpl\r\n # 返回类型为Map,显示null对应的字段\r\n call-setters-on-nulls: true', 'd695ddf9b45ff9f8e009803c93650263', '2021-03-03 13:01:42', '2021-03-03 13:01:42', NULL, '172.17.0.1', '', '', NULL, NULL, NULL, 'yaml', NULL);
INSERT INTO `config_info` VALUES (3, 'jeecg-gateway-router.json', 'DEFAULT_GROUP', '[{\r\n \"id\": \"jeecg-system\",\r\n \"order\": 0,\r\n \"predicates\": [{\r\n \"name\": \"Path\",\r\n \"args\": {\r\n \"_genkey_0\": \"/sys/**\",\r\n \"_genkey_1\": \"/eoa/**\",\r\n \"_genkey_2\": \"/joa/**\",\r\n \"_genkey_3\": \"/jmreport/**\",\r\n \"_genkey_4\": \"/bigscreen/**\",\r\n \"_genkey_5\": \"/desform/**\",\r\n \"_genkey_6\": \"/online/**\",\r\n \"_genkey_8\": \"/act/**\",\r\n \"_genkey_9\": \"/plug-in/**\",\r\n \"_genkey_10\": \"/generic/**\",\r\n \"_genkey_11\": \"/v1/**\"\r\n }\r\n }],\r\n \"filters\": [],\r\n \"uri\": \"lb://jeecg-system\"\r\n}, {\r\n \"id\": \"jeecg-demo\",\r\n \"order\": 1,\r\n \"predicates\": [{\r\n \"name\": \"Path\",\r\n \"args\": {\r\n \"_genkey_0\": \"/mock/**\",\r\n \"_genkey_1\": \"/test/**\",\r\n \"_genkey_2\": \"/bigscreen/template1/**\",\r\n \"_genkey_3\": \"/bigscreen/template2/**\"\r\n }\r\n }],\r\n \"filters\": [],\r\n \"uri\": \"lb://jeecg-demo\"\r\n}, {\r\n \"id\": \"jeecg-system-websocket\",\r\n \"order\": 2,\r\n \"predicates\": [{\r\n \"name\": \"Path\",\r\n \"args\": {\r\n \"_genkey_0\": \"/websocket/**\",\r\n \"_genkey_1\": \"/eoaSocket/**\",\r\n \"_genkey_2\": \"/newsWebsocket/**\"\r\n }\r\n }],\r\n \"filters\": [],\r\n \"uri\": \"lb:ws://jeecg-system\"\r\n}, {\r\n \"id\": \"jeecg-demo-websocket\",\r\n \"order\": 3,\r\n \"predicates\": [{\r\n \"name\": \"Path\",\r\n \"args\": {\r\n \"_genkey_0\": \"/vxeSocket/**\"\r\n }\r\n }],\r\n \"filters\": [],\r\n \"uri\": \"lb:ws://jeecg-demo\"\r\n}]', '82f4033ef6a51ce2ab6ce505be1b729a', '2021-03-03 13:02:14', '2021-03-03 13:02:14', NULL, '172.17.0.1', '', '', NULL, NULL, NULL, 'json', NULL);
-- ----------------------------
......@@ -62,7 +62,7 @@ CREATE TABLE `config_info_aggr` (
`group_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT 'group_id',
`datum_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT 'datum_id',
`content` longtext CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '内容',
`gmt_modified` datetime NOT NULL COMMENT '修改时间',
`gmt_modified` datetime(0) NOT NULL COMMENT '修改时间',
`app_name` varchar(128) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
`tenant_id` varchar(128) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT '' COMMENT '租户字段',
PRIMARY KEY (`id`) USING BTREE,
......@@ -81,8 +81,8 @@ CREATE TABLE `config_info_beta` (
`content` longtext CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT 'content',
`beta_ips` varchar(1024) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT 'betaIps',
`md5` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT 'md5',
`gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '修改时间',
`gmt_create` datetime(0) NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '创建时间',
`gmt_modified` datetime(0) NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '修改时间',
`src_user` text CHARACTER SET utf8 COLLATE utf8_bin NULL COMMENT 'source user',
`src_ip` varchar(20) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT 'source ip',
`tenant_id` varchar(128) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT '' COMMENT '租户字段',
......@@ -103,8 +103,8 @@ CREATE TABLE `config_info_tag` (
`app_name` varchar(128) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT 'app_name',
`content` longtext CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT 'content',
`md5` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT 'md5',
`gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '修改时间',
`gmt_create` datetime(0) NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '创建时间',
`gmt_modified` datetime(0) NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '修改时间',
`src_user` text CHARACTER SET utf8 COLLATE utf8_bin NULL COMMENT 'source user',
`src_ip` varchar(20) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT 'source ip',
PRIMARY KEY (`id`) USING BTREE,
......@@ -141,8 +141,8 @@ CREATE TABLE `group_capacity` (
`max_aggr_count` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '聚合子配置最大个数,,0表示使用默认值',
`max_aggr_size` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',
`max_history_count` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '最大变更历史数量',
`gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '修改时间',
`gmt_create` datetime(0) NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '创建时间',
`gmt_modified` datetime(0) NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '修改时间',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `uk_group_id`(`group_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_bin COMMENT = '集群、各Group容量信息表' ROW_FORMAT = Dynamic;
......@@ -159,8 +159,8 @@ CREATE TABLE `his_config_info` (
`app_name` varchar(128) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT 'app_name',
`content` longtext CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
`md5` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
`gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00',
`gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00',
`gmt_create` datetime(0) NOT NULL DEFAULT '2010-05-05 00:00:00',
`gmt_modified` datetime(0) NOT NULL DEFAULT '2010-05-05 00:00:00',
`src_user` text CHARACTER SET utf8 COLLATE utf8_bin NULL,
`src_ip` varchar(20) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
`op_type` char(10) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
......@@ -169,16 +169,12 @@ CREATE TABLE `his_config_info` (
INDEX `idx_gmt_create`(`gmt_create`) USING BTREE,
INDEX `idx_gmt_modified`(`gmt_modified`) USING BTREE,
INDEX `idx_did`(`data_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 26 CHARACTER SET = utf8 COLLATE = utf8_bin COMMENT = '多租户改造' ROW_FORMAT = Dynamic;
) ENGINE = InnoDB AUTO_INCREMENT = 14 CHARACTER SET = utf8 COLLATE = utf8_bin COMMENT = '多租户改造' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of his_config_info
-- ----------------------------
INSERT INTO `his_config_info` VALUES (1, 21, 'jeecg-dev.yaml', 'DEFAULT_GROUP', '', 'spring:\n datasource:\n druid:\n stat-view-servlet:\n enabled: true\n loginUsername: admin\n loginPassword: 123456\n allow:\n web-stat-filter:\n enabled: true\n dynamic:\n druid: # 全局druid参数,绝大部分值和默认保持一致。(现已支持的参数如下,不清楚含义不要乱设置)\n # 连接池的配置信息\n # 初始化大小,最小,最大\n initial-size: 5\n min-idle: 5\n maxActive: 20\n # 配置获取连接等待超时的时间\n maxWait: 60000\n # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒\n timeBetweenEvictionRunsMillis: 60000\n # 配置一个连接在池中最小生存的时间,单位是毫秒\n minEvictableIdleTimeMillis: 300000\n validationQuery: SELECT 1 FROM DUAL\n testWhileIdle: true\n testOnBorrow: false\n testOnReturn: false\n # 打开PSCache,并且指定每个连接上PSCache的大小\n poolPreparedStatements: true\n maxPoolPreparedStatementPerConnectionSize: 20\n # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,\'wall\'用于防火墙\n filters: stat,wall,slf4j\n # 通过connectProperties属性来打开mergeSql功能;慢SQL记录\n connectionProperties: druid.stat.mergeSql\\=true;druid.stat.slowSqlMillis\\=5000\n\n datasource:\n master:\n url: jdbc:mysql://jeecg-boot-mysql:3306/jeecgboot?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai\n username: root\n password: root\n driver-class-name: com.mysql.cj.jdbc.Driver\n # 多数据源配置\n #multi-datasource1:\n #url: jdbc:mysql://localhost:3306/jeecg-boot2?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai\n #username: root\n #password: root\n #driver-class-name: com.mysql.cj.jdbc.Driver\n #redis 配置\n redis:\n database: 0\n host: jeecg-boot-redis\n lettuce:\n pool:\n max-active: 8 #最大连接数据库连接数,设 0 为没有限制\n max-idle: 8 #最大等待连接中的数量,设 0 为没有限制\n max-wait: -1ms #最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。\n min-idle: 0 #最小等待连接中的数量,设 0 为没有限制\n shutdown-timeout: 100ms\n password:\n port: 6379\n #rabbitmq配置\n rabbitmq:\n host: 127.0.0.1\n username: guest\n password: guest\n port: 5672\n publisher-confirms: true\n publisher-returns: true\n virtual-host: /\n listener:\n simple:\n acknowledge-mode: manual\n #消费者的最小数量\n concurrency: 1\n #消费者的最大数量\n max-concurrency: 1\n #是否支持重试\n retry:\n enabled: true\n#jeecg专用配置\nminidao :\n base-package: org.jeecg.modules.jmreport.*\n #DB类型(mysql | postgresql | oracle | sqlserver| other)\n db-type: mysql\njeecg :\n # 签名密钥串(前后端要一致,正式发布请自行修改)\n signatureSecret: dd05f1c54d63749eda95f9fa6d49v442a\n # 本地:local\\Minio:minio\\阿里云:alioss\n uploadType: local\n path :\n #文件上传根目录 设置\n upload: D://opt//upFiles\n #webapp文件路径\n webapp: D://opt//webapp\n shiro:\n excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/category/**,/visual/**,/map/**,/jmreport/bigscreen2/**\n #阿里云oss存储配置\n oss:\n endpoint: oss-cn-beijing.aliyuncs.com\n accessKey: ??\n secretKey: ??\n bucketName: jeecgdev\n staticDomain: ??\n # ElasticSearch 6设置\n elasticsearch:\n cluster-name: jeecg-ES\n cluster-nodes: 127.0.0.1:9200\n check-enabled: false\n # 表单设计器配置\n desform:\n # 主题颜色(仅支持 16进制颜色代码)\n theme-color: \"#1890ff\"\n # 文件、图片上传方式,可选项:qiniu(七牛云)、system(跟随系统配置)\n upload-type: system\n map:\n # 配置百度地图的AK,申请地址:https://lbs.baidu.com/apiconsole/key?application=key#/home\n baidu: ??\n # 在线预览文件服务器地址配置\n file-view-domain: 127.0.0.1:8012\n # minio文件上传\n minio:\n minio_url: http://minio.jeecg.com\n minio_name: ??\n minio_pass: ??\n bucketName: otatest\n #大屏报表参数设置\n jmreport:\n mode: dev\n #是否需要校验token\n is_verify_token: false\n #必须校验方法\n verify_methods: remove,delete,save,add,update\n #Wps在线文档\n wps:\n domain: https://wwo.wps.cn/office/\n appid: ??\n appsecret: ??\n #xxl-job配置\n xxljob:\n enabled: false\n adminAddresses: http://jeecg-boot-xxljob:9080/xxl-job-admin\n appname: ${spring.application.name}\n accessToken: \'\'\n logPath: logs/jeecg/job/jobhandler/\n logRetentionDays: 30\n #自定义路由配置 yml nacos database\n route:\n config:\n data-id: jeecg-gateway-router\n group: DEFAULT_GROUP\n data-type: database\n #分布式锁配置\n redisson:\n address: jeecg-boot-redis:6379\n password:\n type: STANDALONE\n enabled: true\n#Mybatis输出sql日志\nlogging:\n level:\n org.jeecg.modules.system.mapper : info\n#cas单点登录\ncas:\n prefixUrl: http://localhost:8888/cas\n#swagger\nknife4j:\n production: false\n basic:\n enable: false\n username: jeecg\n password: jeecg1314\n\n#第三方登录\njustauth:\n enabled: true\n type:\n GITHUB:\n client-id: ??\n client-secret: ??\n redirect-uri: http://sso.test.com:8080/jeecg-boot/thirdLogin/github/callback\n WECHAT_ENTERPRISE:\n client-id: ??\n client-secret: ??\n redirect-uri: http://sso.test.com:8080/jeecg-boot/thirdLogin/wechat_enterprise/callback\n agent-id: 1000002\n DINGTALK:\n client-id: ??\n client-secret: ??\n redirect-uri: http://sso.test.com:8080/jeecg-boot/thirdLogin/dingtalk/callback\n cache:\n type: default\n prefix: \'demo::\'\n timeout: 1h\n#第三方APP对接\nthird-app:\n enabled: false\n type:\n #企业微信\n WECHAT_ENTERPRISE:\n enabled: false\n #CORP_ID\n client-id: ??\n #SECRET\n client-secret: ??\n agent-id: ??\n #自建应用秘钥(新版企微需要配置)\n # agent-app-secret: ??\n #钉钉\n DINGTALK:\n enabled: false\n # appKey\n client-id: ??\n # appSecret\n client-secret: ??\n agent-id: ??', '9e643a8b6e81b13a2110aa246c88644c', '2010-05-05 00:00:00', '2021-08-13 07:39:53', NULL, '0:0:0:0:0:0:0:1', 'U', '');
INSERT INTO `his_config_info` VALUES (1, 22, 'jeecg-dev.yaml', 'DEFAULT_GROUP', '', 'spring:\n datasource:\n druid:\n stat-view-servlet:\n enabled: true\n loginUsername: admin\n loginPassword: 123456\n allow:\n web-stat-filter:\n enabled: true\n dynamic:\n druid: # 全局druid参数,绝大部分值和默认保持一致。(现已支持的参数如下,不清楚含义不要乱设置)\n # 连接池的配置信息\n # 初始化大小,最小,最大\n initial-size: 5\n min-idle: 5\n maxActive: 20\n # 配置获取连接等待超时的时间\n maxWait: 60000\n # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒\n timeBetweenEvictionRunsMillis: 60000\n # 配置一个连接在池中最小生存的时间,单位是毫秒\n minEvictableIdleTimeMillis: 300000\n validationQuery: SELECT 1 FROM DUAL\n testWhileIdle: true\n testOnBorrow: false\n testOnReturn: false\n # 打开PSCache,并且指定每个连接上PSCache的大小\n poolPreparedStatements: true\n maxPoolPreparedStatementPerConnectionSize: 20\n # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,\'wall\'用于防火墙\n filters: stat,wall,slf4j\n # 通过connectProperties属性来打开mergeSql功能;慢SQL记录\n connectionProperties: druid.stat.mergeSql\\=true;druid.stat.slowSqlMillis\\=5000\n\n datasource:\n master:\n url: jdbc:mysql://jeecg-boot-mysql:3306/jeecgboot?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai\n username: root\n password: root\n driver-class-name: com.mysql.cj.jdbc.Driver\n # 多数据源配置\n #multi-datasource1:\n #url: jdbc:mysql://localhost:3306/jeecg-boot2?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai\n #username: root\n #password: root\n #driver-class-name: com.mysql.cj.jdbc.Driver\n #redis 配置\n redis:\n database: 0\n host: jeecg-boot-redis\n lettuce:\n pool:\n max-active: 8 #最大连接数据库连接数,设 0 为没有限制\n max-idle: 8 #最大等待连接中的数量,设 0 为没有限制\n max-wait: -1ms #最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。\n min-idle: 0 #最小等待连接中的数量,设 0 为没有限制\n shutdown-timeout: 100ms\n password:\n port: 6379\n #rabbitmq配置\n rabbitmq:\n host: 127.0.0.1\n username: guest\n password: guest\n port: 5672\n publisher-confirms: true\n publisher-returns: true\n virtual-host: /\n listener:\n simple:\n acknowledge-mode: manual\n #消费者的最小数量\n concurrency: 1\n #消费者的最大数量\n max-concurrency: 1\n #是否支持重试\n retry:\n enabled: true\n#jeecg专用配置\nminidao :\n base-package: org.jeecg.modules.jmreport.*\njeecg :\n # 签名密钥串(前后端要一致,正式发布请自行修改)\n signatureSecret: dd05f1c54d63749eda95f9fa6d49v442a\n # 本地:local\\Minio:minio\\阿里云:alioss\n uploadType: local\n path :\n #文件上传根目录 设置\n upload: /opt/upFiles\n #webapp文件路径\n webapp: /opt/webapp\n shiro:\n excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/category/**,/visual/**,/map/**,/jmreport/bigscreen2/**\n #阿里云oss存储配置\n oss:\n endpoint: oss-cn-beijing.aliyuncs.com\n accessKey: ??\n secretKey: ??\n bucketName: jeecgdev\n staticDomain: ??\n # ElasticSearch 6设置\n elasticsearch:\n cluster-name: jeecg-ES\n cluster-nodes: 127.0.0.1:9200\n check-enabled: false\n # 表单设计器配置\n desform:\n # 主题颜色(仅支持 16进制颜色代码)\n theme-color: \"#1890ff\"\n # 文件、图片上传方式,可选项:qiniu(七牛云)、system(跟随系统配置)\n upload-type: system\n map:\n # 配置百度地图的AK,申请地址:https://lbs.baidu.com/apiconsole/key?application=key#/home\n baidu: ??\n # 在线预览文件服务器地址配置\n file-view-domain: 127.0.0.1:8012\n # minio文件上传\n minio:\n minio_url: http://minio.jeecg.com\n minio_name: ??\n minio_pass: ??\n bucketName: otatest\n #大屏报表参数设置\n jmreport:\n mode: dev\n #是否需要校验token\n is_verify_token: false\n #必须校验方法\n verify_methods: remove,delete,save,add,update\n #Wps在线文档\n wps:\n domain: https://wwo.wps.cn/office/\n appid: ??\n appsecret: ??\n #xxl-job配置\n xxljob:\n enabled: false\n adminAddresses: http://jeecg-boot-xxljob:9080/xxl-job-admin\n appname: ${spring.application.name}\n accessToken: \'\'\n logPath: logs/jeecg/job/jobhandler/\n logRetentionDays: 30\n #自定义路由配置 yml nacos database\n route:\n config:\n data-id: jeecg-gateway-router\n group: DEFAULT_GROUP\n data-type: database\n #分布式锁配置\n redisson:\n address: jeecg-boot-redis:6379\n password:\n type: STANDALONE\n enabled: true\n#Mybatis输出sql日志\nlogging:\n level:\n org.jeecg.modules.system.mapper : info\n#cas单点登录\ncas:\n prefixUrl: http://localhost:8888/cas\n#swagger\nknife4j:\n production: false\n basic:\n enable: false\n username: jeecg\n password: jeecg1314\n\n#第三方登录\njustauth:\n enabled: true\n type:\n GITHUB:\n client-id: ??\n client-secret: ??\n redirect-uri: http://sso.test.com:8080/jeecg-boot/thirdLogin/github/callback\n WECHAT_ENTERPRISE:\n client-id: ??\n client-secret: ??\n redirect-uri: http://sso.test.com:8080/jeecg-boot/thirdLogin/wechat_enterprise/callback\n agent-id: 1000002\n DINGTALK:\n client-id: ??\n client-secret: ??\n redirect-uri: http://sso.test.com:8080/jeecg-boot/thirdLogin/dingtalk/callback\n cache:\n type: default\n prefix: \'demo::\'\n timeout: 1h\n#第三方APP对接\nthird-app:\n enabled: false\n type:\n #企业微信\n WECHAT_ENTERPRISE:\n enabled: false\n #CORP_ID\n client-id: ??\n #SECRET\n client-secret: ??\n agent-id: ??\n #自建应用秘钥(新版企微需要配置)\n # agent-app-secret: ??\n #钉钉\n DINGTALK:\n enabled: false\n # appKey\n client-id: ??\n # appSecret\n client-secret: ??\n agent-id: ??', 'ec0dc24293c54ab9425c12c0fe294bcb', '2010-05-05 00:00:00', '2021-08-13 07:50:14', NULL, '0:0:0:0:0:0:0:1', 'U', '');
INSERT INTO `his_config_info` VALUES (1, 23, 'jeecg-dev.yaml', 'DEFAULT_GROUP', '', 'spring:\n datasource:\n druid:\n stat-view-servlet:\n enabled: true\n loginUsername: admin\n loginPassword: 123456\n allow:\n web-stat-filter:\n enabled: true\n dynamic:\n druid: # 全局druid参数,绝大部分值和默认保持一致。(现已支持的参数如下,不清楚含义不要乱设置)\n # 连接池的配置信息\n # 初始化大小,最小,最大\n initial-size: 5\n min-idle: 5\n maxActive: 20\n # 配置获取连接等待超时的时间\n maxWait: 60000\n # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒\n timeBetweenEvictionRunsMillis: 60000\n # 配置一个连接在池中最小生存的时间,单位是毫秒\n minEvictableIdleTimeMillis: 300000\n validationQuery: SELECT 1 FROM DUAL\n testWhileIdle: true\n testOnBorrow: false\n testOnReturn: false\n # 打开PSCache,并且指定每个连接上PSCache的大小\n poolPreparedStatements: true\n maxPoolPreparedStatementPerConnectionSize: 20\n # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,\'wall\'用于防火墙\n filters: stat,wall,slf4j\n # 通过connectProperties属性来打开mergeSql功能;慢SQL记录\n connectionProperties: druid.stat.mergeSql\\=true;druid.stat.slowSqlMillis\\=5000\n\n datasource:\n master:\n url: jdbc:mysql://jeecg-boot-mysql:3306/jeecg-boot-os-re?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai\n username: root\n password: root\n driver-class-name: com.mysql.cj.jdbc.Driver\n # 多数据源配置\n #multi-datasource1:\n #url: jdbc:mysql://localhost:3306/jeecg-boot2?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai\n #username: root\n #password: root\n #driver-class-name: com.mysql.cj.jdbc.Driver\n #redis 配置\n redis:\n database: 0\n host: jeecg-boot-redis\n lettuce:\n pool:\n max-active: 8 #最大连接数据库连接数,设 0 为没有限制\n max-idle: 8 #最大等待连接中的数量,设 0 为没有限制\n max-wait: -1ms #最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。\n min-idle: 0 #最小等待连接中的数量,设 0 为没有限制\n shutdown-timeout: 100ms\n password:\n port: 6379\n #rabbitmq配置\n rabbitmq:\n host: 127.0.0.1\n username: guest\n password: guest\n port: 5672\n publisher-confirms: true\n publisher-returns: true\n virtual-host: /\n listener:\n simple:\n acknowledge-mode: manual\n #消费者的最小数量\n concurrency: 1\n #消费者的最大数量\n max-concurrency: 1\n #是否支持重试\n retry:\n enabled: true\n#jeecg专用配置\nminidao :\n base-package: org.jeecg.modules.jmreport.*\njeecg :\n # 签名密钥串(前后端要一致,正式发布请自行修改)\n signatureSecret: dd05f1c54d63749eda95f9fa6d49v442a\n # 本地:local\\Minio:minio\\阿里云:alioss\n uploadType: local\n path :\n #文件上传根目录 设置\n upload: /opt/upFiles\n #webapp文件路径\n webapp: /opt/webapp\n shiro:\n excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/category/**,/visual/**,/map/**,/jmreport/bigscreen2/**\n #阿里云oss存储配置\n oss:\n endpoint: oss-cn-beijing.aliyuncs.com\n accessKey: ??\n secretKey: ??\n bucketName: jeecgdev\n staticDomain: ??\n # ElasticSearch 6设置\n elasticsearch:\n cluster-name: jeecg-ES\n cluster-nodes: 127.0.0.1:9200\n check-enabled: false\n # 表单设计器配置\n desform:\n # 主题颜色(仅支持 16进制颜色代码)\n theme-color: \"#1890ff\"\n # 文件、图片上传方式,可选项:qiniu(七牛云)、system(跟随系统配置)\n upload-type: system\n map:\n # 配置百度地图的AK,申请地址:https://lbs.baidu.com/apiconsole/key?application=key#/home\n baidu: ??\n # 在线预览文件服务器地址配置\n file-view-domain: 127.0.0.1:8012\n # minio文件上传\n minio:\n minio_url: http://minio.jeecg.com\n minio_name: ??\n minio_pass: ??\n bucketName: otatest\n #大屏报表参数设置\n jmreport:\n mode: dev\n #是否需要校验token\n is_verify_token: false\n #必须校验方法\n verify_methods: remove,delete,save,add,update\n #Wps在线文档\n wps:\n domain: https://wwo.wps.cn/office/\n appid: ??\n appsecret: ??\n #xxl-job配置\n xxljob:\n enabled: false\n adminAddresses: http://jeecg-boot-xxljob:9080/xxl-job-admin\n appname: ${spring.application.name}\n accessToken: \'\'\n logPath: logs/jeecg/job/jobhandler/\n logRetentionDays: 30\n #自定义路由配置 yml nacos database\n route:\n config:\n data-id: jeecg-gateway-router\n group: DEFAULT_GROUP\n data-type: database\n #分布式锁配置\n redisson:\n address: jeecg-boot-redis:6379\n password:\n type: STANDALONE\n enabled: true\n#Mybatis输出sql日志\nlogging:\n level:\n org.jeecg.modules.system.mapper : info\n#cas单点登录\ncas:\n prefixUrl: http://localhost:8888/cas\n#swagger\nknife4j:\n production: false\n basic:\n enable: false\n username: jeecg\n password: jeecg1314\n\n#第三方登录\njustauth:\n enabled: true\n type:\n GITHUB:\n client-id: ??\n client-secret: ??\n redirect-uri: http://sso.test.com:8080/jeecg-boot/thirdLogin/github/callback\n WECHAT_ENTERPRISE:\n client-id: ??\n client-secret: ??\n redirect-uri: http://sso.test.com:8080/jeecg-boot/thirdLogin/wechat_enterprise/callback\n agent-id: 1000002\n DINGTALK:\n client-id: ??\n client-secret: ??\n redirect-uri: http://sso.test.com:8080/jeecg-boot/thirdLogin/dingtalk/callback\n cache:\n type: default\n prefix: \'demo::\'\n timeout: 1h\n#第三方APP对接\nthird-app:\n enabled: false\n type:\n #企业微信\n WECHAT_ENTERPRISE:\n enabled: false\n #CORP_ID\n client-id: ??\n #SECRET\n client-secret: ??\n agent-id: ??\n #自建应用秘钥(新版企微需要配置)\n # agent-app-secret: ??\n #钉钉\n DINGTALK:\n enabled: false\n # appKey\n client-id: ??\n # appSecret\n client-secret: ??\n agent-id: ??', '34dbe2392c2247c0d5943aaa1f29a75e', '2010-05-05 00:00:00', '2021-08-13 07:51:44', NULL, '0:0:0:0:0:0:0:1', 'U', '');
INSERT INTO `his_config_info` VALUES (1, 24, 'jeecg-dev.yaml', 'DEFAULT_GROUP', '', 'spring:\n datasource:\n druid:\n stat-view-servlet:\n enabled: true\n loginUsername: admin\n loginPassword: 123456\n allow:\n web-stat-filter:\n enabled: true\n dynamic:\n druid: # 全局druid参数,绝大部分值和默认保持一致。(现已支持的参数如下,不清楚含义不要乱设置)\n # 连接池的配置信息\n # 初始化大小,最小,最大\n initial-size: 5\n min-idle: 5\n maxActive: 20\n # 配置获取连接等待超时的时间\n maxWait: 60000\n # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒\n timeBetweenEvictionRunsMillis: 60000\n # 配置一个连接在池中最小生存的时间,单位是毫秒\n minEvictableIdleTimeMillis: 300000\n validationQuery: SELECT 1 FROM DUAL\n testWhileIdle: true\n testOnBorrow: false\n testOnReturn: false\n # 打开PSCache,并且指定每个连接上PSCache的大小\n poolPreparedStatements: true\n maxPoolPreparedStatementPerConnectionSize: 20\n # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,\'wall\'用于防火墙\n filters: stat,wall,slf4j\n # 通过connectProperties属性来打开mergeSql功能;慢SQL记录\n connectionProperties: druid.stat.mergeSql\\=true;druid.stat.slowSqlMillis\\=5000\n\n datasource:\n master:\n url: jdbc:mysql://jeecg-boot-mysql:3306/jeecg-boot-os-re?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai\n username: root\n password: root\n driver-class-name: com.mysql.cj.jdbc.Driver\n # 多数据源配置\n #multi-datasource1:\n #url: jdbc:mysql://localhost:3306/jeecg-boot2?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai\n #username: root\n #password: root\n #driver-class-name: com.mysql.cj.jdbc.Driver\n #redis 配置\n redis:\n database: 0\n host: jeecg-boot-redis\n lettuce:\n pool:\n max-active: 8 #最大连接数据库连接数,设 0 为没有限制\n max-idle: 8 #最大等待连接中的数量,设 0 为没有限制\n max-wait: -1ms #最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。\n min-idle: 0 #最小等待连接中的数量,设 0 为没有限制\n shutdown-timeout: 100ms\n password:\n port: 6379\n #rabbitmq配置\n rabbitmq:\n host: 127.0.0.1\n username: guest\n password: guest\n port: 5672\n publisher-confirms: true\n publisher-returns: true\n virtual-host: /\n listener:\n simple:\n acknowledge-mode: manual\n #消费者的最小数量\n concurrency: 1\n #消费者的最大数量\n max-concurrency: 1\n #是否支持重试\n retry:\n enabled: true\n#jeecg专用配置\nminidao :\n base-package: org.jeecg.modules.jmreport.*\njeecg :\n # 签名密钥串(前后端要一致,正式发布请自行修改)\n signatureSecret: dd05f1c54d63749eda95f9fa6d49v442a\n # 本地:local\\Minio:minio\\阿里云:alioss\n uploadType: local\n path :\n #文件上传根目录 设置\n upload: /opt/upFiles\n #webapp文件路径\n webapp: /opt/webapp\n shiro:\n excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/category/**,/visual/**,/map/**,/jmreport/bigscreen2/**\n #阿里云oss存储配置\n oss:\n endpoint: oss-cn-beijing.aliyuncs.com\n accessKey: ??\n secretKey: ??\n bucketName: jeecgdev\n staticDomain: ??\n # ElasticSearch 6设置\n elasticsearch:\n cluster-name: jeecg-ES\n cluster-nodes: 127.0.0.1:9200\n check-enabled: false\n # 表单设计器配置\n desform:\n # 主题颜色(仅支持 16进制颜色代码)\n theme-color: \"#1890ff\"\n # 文件、图片上传方式,可选项:qiniu(七牛云)、system(跟随系统配置)\n upload-type: system\n map:\n # 配置百度地图的AK,申请地址:https://lbs.baidu.com/apiconsole/key?application=key#/home\n baidu: ??\n # 在线预览文件服务器地址配置\n file-view-domain: 127.0.0.1:8012\n # minio文件上传\n minio:\n minio_url: http://minio.jeecg.com\n minio_name: ??\n minio_pass: ??\n bucketName: otatest\n #大屏报表参数设置\n jmreport:\n mode: dev\n #是否需要校验token\n is_verify_token: false\n #必须校验方法\n verify_methods: remove,delete,save,add,update\n #Wps在线文档\n wps:\n domain: https://wwo.wps.cn/office/\n appid: ??\n appsecret: ??\n #xxl-job配置\n xxljob:\n enabled: false\n adminAddresses: http://jeecg-boot-xxljob:9080/xxl-job-admin\n appname: ${spring.application.name}\n accessToken: \'\'\n logPath: logs/jeecg/job/jobhandler/\n logRetentionDays: 30\n #自定义路由配置 yml nacos database\n route:\n config:\n data-id: jeecg-gateway-router\n group: DEFAULT_GROUP\n data-type: database\n #分布式锁配置\n redisson:\n address: jeecg-boot-redis:6379\n password:\n type: STANDALONE\n enabled: true\n#Mybatis输出sql日志\nlogging:\n level:\n org.jeecg.modules.system.mapper : info\n#cas单点登录\ncas:\n prefixUrl: http://localhost:8888/cas\n#swagger\nknife4j:\n #开启增强配置\n enable: true\n #开启生产环境屏蔽\n production: false\n basic:\n enable: false\n username: jeecg\n password: jeecg1314\n\n#第三方登录\njustauth:\n enabled: true\n type:\n GITHUB:\n client-id: ??\n client-secret: ??\n redirect-uri: http://sso.test.com:8080/jeecg-boot/thirdLogin/github/callback\n WECHAT_ENTERPRISE:\n client-id: ??\n client-secret: ??\n redirect-uri: http://sso.test.com:8080/jeecg-boot/thirdLogin/wechat_enterprise/callback\n agent-id: 1000002\n DINGTALK:\n client-id: ??\n client-secret: ??\n redirect-uri: http://sso.test.com:8080/jeecg-boot/thirdLogin/dingtalk/callback\n cache:\n type: default\n prefix: \'demo::\'\n timeout: 1h\n#第三方APP对接\nthird-app:\n enabled: false\n type:\n #企业微信\n WECHAT_ENTERPRISE:\n enabled: false\n #CORP_ID\n client-id: ??\n #SECRET\n client-secret: ??\n agent-id: ??\n #自建应用秘钥(新版企微需要配置)\n # agent-app-secret: ??\n #钉钉\n DINGTALK:\n enabled: false\n # appKey\n client-id: ??\n # appSecret\n client-secret: ??\n agent-id: ??', 'b34338a768d1532725632f01503d54b6', '2010-05-05 00:00:00', '2021-08-13 08:01:44', NULL, '0:0:0:0:0:0:0:1', 'U', '');
INSERT INTO `his_config_info` VALUES (1, 25, 'jeecg-dev.yaml', 'DEFAULT_GROUP', '', 'spring:\n datasource:\n druid:\n stat-view-servlet:\n enabled: true\n loginUsername: admin\n loginPassword: 123456\n allow:\n web-stat-filter:\n enabled: true\n dynamic:\n druid: # 全局druid参数,绝大部分值和默认保持一致。(现已支持的参数如下,不清楚含义不要乱设置)\n # 连接池的配置信息\n # 初始化大小,最小,最大\n initial-size: 5\n min-idle: 5\n maxActive: 20\n # 配置获取连接等待超时的时间\n maxWait: 60000\n # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒\n timeBetweenEvictionRunsMillis: 60000\n # 配置一个连接在池中最小生存的时间,单位是毫秒\n minEvictableIdleTimeMillis: 300000\n validationQuery: SELECT 1 FROM DUAL\n testWhileIdle: true\n testOnBorrow: false\n testOnReturn: false\n # 打开PSCache,并且指定每个连接上PSCache的大小\n poolPreparedStatements: true\n maxPoolPreparedStatementPerConnectionSize: 20\n # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,\'wall\'用于防火墙\n filters: stat,wall,slf4j\n # 通过connectProperties属性来打开mergeSql功能;慢SQL记录\n connectionProperties: druid.stat.mergeSql\\=true;druid.stat.slowSqlMillis\\=5000\n\n datasource:\n master:\n url: jdbc:mysql://jeecg-boot-mysql:3306/jeecg-boot?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai\n username: root\n password: root\n driver-class-name: com.mysql.cj.jdbc.Driver\n # 多数据源配置\n #multi-datasource1:\n #url: jdbc:mysql://localhost:3306/jeecg-boot2?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai\n #username: root\n #password: root\n #driver-class-name: com.mysql.cj.jdbc.Driver\n #redis 配置\n redis:\n database: 0\n host: jeecg-boot-redis\n lettuce:\n pool:\n max-active: 8 #最大连接数据库连接数,设 0 为没有限制\n max-idle: 8 #最大等待连接中的数量,设 0 为没有限制\n max-wait: -1ms #最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。\n min-idle: 0 #最小等待连接中的数量,设 0 为没有限制\n shutdown-timeout: 100ms\n password:\n port: 6379\n #rabbitmq配置\n rabbitmq:\n host: 127.0.0.1\n username: guest\n password: guest\n port: 5672\n publisher-confirms: true\n publisher-returns: true\n virtual-host: /\n listener:\n simple:\n acknowledge-mode: manual\n #消费者的最小数量\n concurrency: 1\n #消费者的最大数量\n max-concurrency: 1\n #是否支持重试\n retry:\n enabled: true\n#jeecg专用配置\nminidao :\n base-package: org.jeecg.modules.jmreport.*\njeecg :\n # 签名密钥串(前后端要一致,正式发布请自行修改)\n signatureSecret: dd05f1c54d63749eda95f9fa6d49v442a\n # 本地:local\\Minio:minio\\阿里云:alioss\n uploadType: local\n path :\n #文件上传根目录 设置\n upload: /opt/upFiles\n #webapp文件路径\n webapp: /opt/webapp\n shiro:\n excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/category/**,/visual/**,/map/**,/jmreport/bigscreen2/**\n #阿里云oss存储配置\n oss:\n endpoint: oss-cn-beijing.aliyuncs.com\n accessKey: ??\n secretKey: ??\n bucketName: jeecgdev\n staticDomain: ??\n # ElasticSearch 6设置\n elasticsearch:\n cluster-name: jeecg-ES\n cluster-nodes: 127.0.0.1:9200\n check-enabled: false\n # 表单设计器配置\n desform:\n # 主题颜色(仅支持 16进制颜色代码)\n theme-color: \"#1890ff\"\n # 文件、图片上传方式,可选项:qiniu(七牛云)、system(跟随系统配置)\n upload-type: system\n map:\n # 配置百度地图的AK,申请地址:https://lbs.baidu.com/apiconsole/key?application=key#/home\n baidu: ??\n # 在线预览文件服务器地址配置\n file-view-domain: 127.0.0.1:8012\n # minio文件上传\n minio:\n minio_url: http://minio.jeecg.com\n minio_name: ??\n minio_pass: ??\n bucketName: otatest\n #大屏报表参数设置\n jmreport:\n mode: dev\n #是否需要校验token\n is_verify_token: false\n #必须校验方法\n verify_methods: remove,delete,save,add,update\n #Wps在线文档\n wps:\n domain: https://wwo.wps.cn/office/\n appid: ??\n appsecret: ??\n #xxl-job配置\n xxljob:\n enabled: false\n adminAddresses: http://jeecg-boot-xxljob:9080/xxl-job-admin\n appname: ${spring.application.name}\n accessToken: \'\'\n logPath: logs/jeecg/job/jobhandler/\n logRetentionDays: 30\n #自定义路由配置 yml nacos database\n route:\n config:\n data-id: jeecg-gateway-router\n group: DEFAULT_GROUP\n data-type: database\n #分布式锁配置\n redisson:\n address: jeecg-boot-redis:6379\n password:\n type: STANDALONE\n enabled: true\n#Mybatis输出sql日志\nlogging:\n level:\n org.jeecg.modules.system.mapper : info\n#cas单点登录\ncas:\n prefixUrl: http://localhost:8888/cas\n#swagger\nknife4j:\n #开启增强配置\n enable: true\n #开启生产环境屏蔽\n production: false\n basic:\n enable: false\n username: jeecg\n password: jeecg1314\n\n#第三方登录\njustauth:\n enabled: true\n type:\n GITHUB:\n client-id: ??\n client-secret: ??\n redirect-uri: http://sso.test.com:8080/jeecg-boot/thirdLogin/github/callback\n WECHAT_ENTERPRISE:\n client-id: ??\n client-secret: ??\n redirect-uri: http://sso.test.com:8080/jeecg-boot/thirdLogin/wechat_enterprise/callback\n agent-id: 1000002\n DINGTALK:\n client-id: ??\n client-secret: ??\n redirect-uri: http://sso.test.com:8080/jeecg-boot/thirdLogin/dingtalk/callback\n cache:\n type: default\n prefix: \'demo::\'\n timeout: 1h\n#第三方APP对接\nthird-app:\n enabled: false\n type:\n #企业微信\n WECHAT_ENTERPRISE:\n enabled: false\n #CORP_ID\n client-id: ??\n #SECRET\n client-secret: ??\n agent-id: ??\n #自建应用秘钥(新版企微需要配置)\n # agent-app-secret: ??\n #钉钉\n DINGTALK:\n enabled: false\n # appKey\n client-id: ??\n # appSecret\n client-secret: ??\n agent-id: ??', '65c8059128208176715ed89ef93ac9c8', '2010-05-05 00:00:00', '2021-08-13 08:10:45', NULL, '0:0:0:0:0:0:0:1', 'U', '');
INSERT INTO `his_config_info` VALUES (1, 13, 'jeecg-dev.yaml', 'DEFAULT_GROUP', '', 'spring:\n datasource:\n druid:\n stat-view-servlet:\n enabled: true\n loginUsername: admin\n loginPassword: 123456\n allow:\n web-stat-filter:\n enabled: true\n dynamic:\n druid: # 全局druid参数,绝大部分值和默认保持一致。(现已支持的参数如下,不清楚含义不要乱设置)\n # 连接池的配置信息\n # 初始化大小,最小,最大\n initial-size: 5\n min-idle: 5\n maxActive: 20\n # 配置获取连接等待超时的时间\n maxWait: 60000\n # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒\n timeBetweenEvictionRunsMillis: 60000\n # 配置一个连接在池中最小生存的时间,单位是毫秒\n minEvictableIdleTimeMillis: 300000\n validationQuery: SELECT 1 FROM DUAL\n testWhileIdle: true\n testOnBorrow: false\n testOnReturn: false\n # 打开PSCache,并且指定每个连接上PSCache的大小\n poolPreparedStatements: true\n maxPoolPreparedStatementPerConnectionSize: 20\n # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,\'wall\'用于防火墙\n filters: stat,wall,slf4j\n # 通过connectProperties属性来打开mergeSql功能;慢SQL记录\n connectionProperties: druid.stat.mergeSql\\=true;druid.stat.slowSqlMillis\\=5000\n\n datasource:\n master:\n url: jdbc:mysql://jeecg-boot-mysql:3306/jeecg-boot?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai\n username: root\n password: root\n driver-class-name: com.mysql.cj.jdbc.Driver\n # 多数据源配置\n #multi-datasource1:\n #url: jdbc:mysql://localhost:3306/jeecg-boot2?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai\n #username: root\n #password: root\n #driver-class-name: com.mysql.cj.jdbc.Driver\n #redis 配置\n redis:\n database: 0\n host: jeecg-boot-redis\n lettuce:\n pool:\n max-active: 8 #最大连接数据库连接数,设 0 为没有限制\n max-idle: 8 #最大等待连接中的数量,设 0 为没有限制\n max-wait: -1ms #最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。\n min-idle: 0 #最小等待连接中的数量,设 0 为没有限制\n shutdown-timeout: 100ms\n password:\n port: 6379\n #rabbitmq配置\n rabbitmq:\n host: 127.0.0.1\n username: guest\n password: guest\n port: 5672\n publisher-confirms: true\n publisher-returns: true\n virtual-host: /\n listener:\n simple:\n acknowledge-mode: manual\n #消费者的最小数量\n concurrency: 1\n #消费者的最大数量\n max-concurrency: 1\n #是否支持重试\n retry:\n enabled: true\n#jeecg专用配置\nminidao :\n base-package: org.jeecg.modules.jmreport.*\n db-type: mysql\njeecg :\n # 本地:local\\Minio:minio\\阿里云:alioss\n uploadType: local\n path :\n #文件上传根目录 设置\n upload: D://opt//upFiles\n #webapp文件路径\n webapp: D://opt//webapp\n shiro:\n excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/category/**,/visual/**,/map/**,/jmreport/bigscreen2/**\n #阿里云oss存储配置\n oss:\n endpoint: oss-cn-beijing.aliyuncs.com\n accessKey: ??\n secretKey: ??\n bucketName: jeecgos\n staticDomain: ??\n # ElasticSearch 6设置\n elasticsearch:\n cluster-name: jeecg-ES\n cluster-nodes: 127.0.0.1:9200\n check-enabled: false\n # 表单设计器配置\n desform:\n # 主题颜色(仅支持 16进制颜色代码)\n theme-color: \"#1890ff\"\n # 文件、图片上传方式,可选项:qiniu(七牛云)、system(跟随系统配置)\n upload-type: system\n # 在线预览文件服务器地址配置\n file-view-domain: 127.0.0.1:8012\n # minio文件上传\n minio:\n minio_url: http://minio.jeecg.com\n minio_name: ??\n minio_pass: ??\n bucketName: otatest\n #大屏报表参数设置\n jmreport:\n mode: dev\n #是否需要校验token\n is_verify_token: false\n #必须校验方法\n verify_methods: remove,delete,save,add,update\n #Wps在线文档\n wps:\n domain: https://wwo.wps.cn/office/\n appid: ??\n appsecret: ??\n #xxl-job配置\n xxljob:\n enabled: true\n adminAddresses: http://jeecg-boot-xxljob:9080/xxl-job-admin\n appname: ${spring.application.name}\n accessToken: \'\'\n logPath: logs/jeecg/job/jobhandler/\n logRetentionDays: 30\n #自定义路由配置 yml nacos database\n route:\n config:\n data-id: jeecg-gateway-router\n group: DEFAULT_GROUP\n data-type: database\n #分布式锁配置\n redisson:\n address: jeecg-boot-redis:6379\n password:\n type: STANDALONE\n enabled: true\n#Mybatis输出sql日志\nlogging:\n level:\n org.jeecg.modules.system.mapper : info\n#cas单点登录\ncas:\n prefixUrl: http://localhost:8888/cas\n#swagger\nknife4j:\n production: false\n basic:\n enable: false\n username: jeecg\n password: jeecg1314\n\n#第三方登录\njustauth:\n enabled: true\n type:\n GITHUB:\n client-id: ??\n client-secret: ??\n redirect-uri: http://sso.test.com:8080/jeecg-boot/thirdLogin/github/callback\n WECHAT_ENTERPRISE:\n client-id: ??\n client-secret: ??\n redirect-uri: http://sso.test.com:8080/jeecg-boot/thirdLogin/wechat_enterprise/callback\n agent-id: 1000002\n DINGTALK:\n client-id: ??\n client-secret: ??\n redirect-uri: http://sso.test.com:8080/jeecg-boot/thirdLogin/dingtalk/callback\n cache:\n type: default\n prefix: \'demo::\'\n timeout: 1h', '1b5d012493d038197e1dc1291efb1610', '2010-05-05 00:00:00', '2021-06-01 07:43:23', NULL, '0:0:0:0:0:0:0:1', 'U', '');
-- ----------------------------
-- Table structure for permissions
......@@ -219,8 +215,8 @@ CREATE TABLE `tenant_capacity` (
`max_aggr_count` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '聚合子配置最大个数',
`max_aggr_size` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',
`max_history_count` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '最大变更历史数量',
`gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '修改时间',
`gmt_create` datetime(0) NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '创建时间',
`gmt_modified` datetime(0) NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '修改时间',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `uk_tenant_id`(`tenant_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_bin COMMENT = '租户容量信息表' ROW_FORMAT = Dynamic;
......
-- 平台基础模块
ALTER TABLE `sys_third_account`
ADD UNIQUE INDEX `uniq_sys_third_account_third_type_third_user_id` (`third_type`, `third_user_id`) USING BTREE ;
INSERT INTO `sys_permission`(`id`, `parent_id`, `name`, `url`, `component`, `component_name`, `redirect`, `menu_type`, `perms`, `perms_type`, `sort_no`, `always_show`, `icon`, `is_route`, `is_leaf`, `keep_alive`, `hidden`, `description`, `status`, `del_flag`, `rule_flag`, `create_by`, `create_time`, `update_by`, `update_time`, `internal_or_external`) VALUES ('1404684556047024130', '08e6b9dc3c04489c8e1ff2ce6f105aa4', '在线用户', '/isystem/online', 'system/SysUserOnlineList', NULL, NULL, 1, NULL, '1', NULL, 0, NULL, 1, 1, 0, 0, NULL, '1', 0, 0, 'admin', '2021-06-15 14:17:51', NULL, NULL, 0);
DELETE FROM sys_depart WHERE id = '743ba9dbdc114af8953a11022ef3096a';
alter table sys_quartz_job engine = InnoDB;
UPDATE `sys_dict_item` SET `item_value` = '6' WHERE `item_text` = 'MYSQL5.7';
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1414837074500976641', '1209733563293962241', 'Postgresql', '6', '', '5', '1', 'admin', '2021-07-13 14:40:20', 'admin', '2021-07-15 13:44:15');
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1415547541091504129', '1209733563293962241', 'MarialDB', '5', '', '6', '1', 'admin', '2021-07-15 13:43:28', 'admin', '2021-07-15 13:44:23');
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1418050323111399425', '1209733563293962241', 'Derby', '13', '', '13', '1', 'admin', '2021-07-22 11:28:38', NULL, NULL);
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1418050209823248385', '1209733563293962241', 'Hsqldb', '12', '', '12', '1', 'admin', '2021-07-22 11:28:11', 'admin', '2021-07-22 11:28:27');
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1418050149475602434', '1209733563293962241', 'DB2', '11', '', '11', '1', 'admin', '2021-07-22 11:27:56', NULL, NULL);
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1418050110669901826', '1209733563293962241', 'SQLite', '10', '', '10', '1', 'admin', '2021-07-22 11:27:47', NULL, NULL);
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1418050075555188737', '1209733563293962241', '神通', '9', '', '9', '1', 'admin', '2021-07-22 11:27:39', NULL, NULL);
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1418050017053036545', '1209733563293962241', '人大金仓', '8', '', '8', '1', 'admin', '2021-07-22 11:27:25', NULL, NULL);
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1418049969003089922', '1209733563293962241', '达梦', '7', '', '7', '1', 'admin', '2021-07-22 11:27:13', 'admin', '2021-07-22 11:27:30');
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1418117316707590146', '1209733563293962241', 'H2', '14', '', '14', '1', 'admin', '2021-07-22 15:54:50', NULL, NULL);
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1418491604048449537', '1209733563293962241', '其他数据库', '15', '', 15, 1, 'admin', '2021-07-23 16:42:07', NULL, NULL);
ALTER TABLE demo ADD COLUMN tenant_id int(10) NULL DEFAULT 0;
-- Online模块
ALTER TABLE `onl_cgform_head`
ADD COLUMN `ext_config_json` varchar(1000) NULL COMMENT '扩展JSON' AFTER `physic_id`;
ALTER TABLE `onl_cgreport_head`
ADD COLUMN `low_app_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '关联的应用ID' AFTER `content`;
-- 积木报表模块
UPDATE `jimu_report` SET `json_str` = '{\"loopBlockList\":[],\"area\":{\"sri\":16,\"sci\":5,\"eri\":16,\"eci\":5,\"width\":147,\"height\":25},\"excel_config_id\":\"1347373863746539520\",\"printConfig\":{\"paper\":\"A4\",\"width\":210,\"height\":297,\"definition\":1,\"isBackend\":false,\"marginX\":10,\"marginY\":10,\"layout\":\"portrait\"},\"rows\":{\"0\":{\"cells\":{\"0\":{\"text\":\"\"},\"1\":{\"text\":\"\"}}},\"1\":{\"cells\":{\"0\":{\"text\":\"\"}}},\"3\":{\"cells\":{\"2\":{\"text\":\"\",\"rendered\":\"\"}}},\"5\":{\"cells\":{},\"height\":29},\"6\":{\"cells\":{\"2\":{\"text\":\"\",\"style\":2}},\"height\":34},\"7\":{\"cells\":{\"2\":{\"merge\":[0,4],\"text\":\"实习证明\",\"style\":2}},\"height\":41},\"8\":{\"cells\":{\"1\":{\"text\":\"\",\"style\":3},\"2\":{\"text\":\"\"}}},\"9\":{\"cells\":{\"1\":{\"text\":\"\",\"style\":3},\"2\":{\"text\":\"\",\"style\":3},\"3\":{\"text\":\"\"}},\"isDrag\":true,\"height\":33},\"10\":{\"cells\":{\"2\":{\"text\":\"${tt.name}\",\"style\":11},\"3\":{\"text\":\"同学在我公司与 2020年4月1日 至 2020年5月1日 实习。\",\"style\":19,\"merge\":[0,3],\"height\":34}},\"height\":34},\"11\":{\"cells\":{},\"height\":28},\"12\":{\"cells\":{\"1\":{\"text\":\"\",\"style\":6},\"2\":{\"style\":13,\"text\":\"${tt.pingjia}\",\"merge\":[3,4],\"height\":129}},\"height\":36},\"13\":{\"cells\":{},\"height\":29},\"14\":{\"cells\":{},\"height\":33},\"15\":{\"cells\":{},\"height\":31},\"16\":{\"cells\":{}},\"17\":{\"cells\":{\"1\":{\"text\":\"\"},\"2\":{\"text\":\"特此证明!\",\"style\":12}}},\"20\":{\"cells\":{\"2\":{\"text\":\"\"},\"3\":{\"text\":\"\",\"style\":3},\"4\":{\"text\":\"\"}}},\"21\":{\"cells\":{\"4\":{\"text\":\"\"}}},\"22\":{\"cells\":{\"3\":{\"text\":\"\",\"style\":3},\"4\":{\"text\":\"证明人:\",\"style\":11},\"5\":{\"text\":\"${tt.lingdao}\",\"style\":12}}},\"23\":{\"cells\":{\"4\":{\"text\":\"\"},\"5\":{\"text\":\"${tt.shijian}\",\"style\":15}}},\"len\":100},\"dbexps\":[],\"dicts\":[],\"freeze\":\"A1\",\"dataRectWidth\":576,\"displayConfig\":{},\"background\":{\"path\":\"https://static.jeecg.com/designreport/images/11_1611283832037.png\",\"repeat\":\"no-repeat\",\"width\":\"\",\"height\":\"\"},\"name\":\"sheet1\",\"autofilter\":{},\"styles\":[{\"align\":\"center\"},{\"align\":\"center\",\"font\":{\"size\":14}},{\"align\":\"center\",\"font\":{\"size\":16}},{\"align\":\"right\"},{\"align\":\"left\"},{\"align\":\"left\",\"valign\":\"top\"},{\"align\":\"left\",\"valign\":\"top\",\"textwrap\":true},{\"font\":{\"size\":16}},{\"align\":\"left\",\"valign\":\"top\",\"textwrap\":false},{\"textwrap\":false},{\"textwrap\":true},{\"align\":\"right\",\"font\":{\"size\":12}},{\"font\":{\"size\":12}},{\"align\":\"left\",\"valign\":\"top\",\"textwrap\":true,\"font\":{\"size\":12}},{\"textwrap\":true,\"font\":{\"size\":12}},{\"align\":\"left\",\"font\":{\"size\":12}},{\"font\":{\"size\":12},\"border\":{\"bottom\":[\"thin\",\"#000\"],\"top\":[\"thin\",\"#000\"],\"left\":[\"thin\",\"#000\"],\"right\":[\"thin\",\"#000\"]}},{\"font\":{\"size\":14}},{\"font\":{\"size\":10}},{\"textwrap\":false,\"font\":{\"size\":12}}],\"validations\":[],\"cols\":{\"0\":{\"width\":69},\"1\":{\"width\":41},\"4\":{\"width\":119},\"5\":{\"width\":147},\"6\":{\"width\":31},\"len\":50},\"merges\":[\"C8:G8\",\"D11:G11\",\"C13:G16\"]}' WHERE `id` = '1347373863746539520';
update jimu_report_data_source set connect_times = 0;
ALTER TABLE `jimu_report_data_source`
MODIFY COLUMN `connect_times` int(1) UNSIGNED NULL DEFAULT 0 COMMENT '连接失败次数' AFTER `update_time`;
ALTER TABLE `jimu_report_db_param`
MODIFY COLUMN `param_value` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '参数默认值' AFTER `param_txt`;
DELETE FROM jimu_report_map
WHERE
id IN (SELECT id FROM (SELECT id FROM jimu_report_map WHERE NAME IN ( SELECT NAME FROM jimu_report_map GROUP BY NAME HAVING count(NAME) > 1)) T)
AND id NOT IN (SELECT id FROM ( SELECT min(id) id FROM jimu_report_map GROUP BY NAME HAVING count(NAME) > 1) M);
ALTER TABLE `jimu_report_map`
ADD UNIQUE INDEX `uniq_jmreport_map_name`(`name`);
update jimu_report set VIEW_COUNT = 0 WHERE VIEW_COUNT is null or VIEW_COUNT = '';
ALTER TABLE `jimu_report`
MODIFY COLUMN `view_count` bigint(15) NULL DEFAULT 0 COMMENT '浏览次数' AFTER `template`;
ALTER TABLE `jimu_report_db`
ADD INDEX `idx_jimu_report_id`(`jimu_report_id`);
ALTER TABLE `jimu_report_db`
ADD INDEX `idx_db_source_id`(`db_source`);
ALTER TABLE `jimu_report_db_field`
ADD INDEX `idx_dbfield_order_num`(`order_num`);
ALTER TABLE `jimu_report`
ADD INDEX `uniq_jmreport_createby`(`create_by`);
ALTER TABLE `jimu_report`
ADD INDEX `uniq_jmreport_delflag`(`del_flag`);
ALTER TABLE `jimu_report_link`
ADD INDEX `uniq_link_reportid`(`report_id`);
ALTER TABLE `jimu_report`
MODIFY COLUMN `json_str` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT 'json字符串' AFTER `type`;
ALTER TABLE `jimu_report_link`
ADD COLUMN `expression` varchar(255) NULL COMMENT '表达式' AFTER `link_chart_id`;
-- 执行下面段可能会报错,说明此部分升级过了,忽略即可
ALTER TABLE `jimu_report_db_param`
ADD COLUMN `search_flag` int(1) NULL COMMENT '查询标识0否1是 默认0' AFTER `update_time`;
update jimu_report_db_param set search_flag = 0;
create table jimu_dict like sys_dict;
insert into jimu_dict select * from sys_dict;
create table jimu_dict_item like sys_dict_item;
insert into jimu_dict_item select * from sys_dict_item;
ALTER TABLE `jimu_report_db_param`
ADD COLUMN `widget_type` varchar(50) NULL COMMENT '查询控件类型' AFTER `search_flag`,
ADD COLUMN `search_mode` int(1) NULL COMMENT '查询模式1简单2范围' AFTER `widget_type`,
ADD COLUMN `dict_code` varchar(255) NULL COMMENT '字典' AFTER `search_mode`;
-- 字段长度不规范,导致转库错误Specified key was too long; max key length is 767 bytes
-- 字段长度不规范,导致转库错误Specified key was too long; max key length is 767 bytes
ALTER TABLE `rep_demo_dxtj`
MODIFY COLUMN `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键' FIRST;
ALTER TABLE `sys_third_account`
MODIFY COLUMN `third_type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '登录来源' AFTER `third_user_id`;
-- 数据源字典sql整理
DELETE FROM `sys_dict_item` WHERE dict_id ='1209733563293962241';
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1209733775114702850', '1209733563293962241', 'MySQL5.5', '1', '', 1, 1, 'admin', '2019-12-25 15:13:02', NULL, NULL);
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1334440962954936321', '1209733563293962241', 'MYSQL5.7+', '4', '', 2, 1, 'admin', '2020-12-03 18:16:02', 'admin', '2021-07-15 13:44:29');
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1209733839933476865', '1209733563293962241', 'Oracle', '2', '', 3, 1, 'admin', '2019-12-25 15:13:18', 'admin', '2021-07-15 13:44:08');
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1209733903020003330', '1209733563293962241', 'SQLServer', '3', '', 4, 1, 'admin', '2019-12-25 15:13:33', 'admin', '2021-07-15 13:44:11');
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1414837074500976641', '1209733563293962241', 'postgresql', '6', '', 5, 1, 'admin', '2021-07-13 14:40:20', 'admin', '2021-07-15 13:44:15');
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1415547541091504129', '1209733563293962241', 'marialDB', '5', '', 6, 1, 'admin', '2021-07-15 13:43:28', 'admin', '2021-07-15 13:44:23');
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1418049969003089922', '1209733563293962241', '达梦', '7', '', 7, 1, 'admin', '2021-07-22 11:27:13', 'admin', '2021-07-22 11:27:30');
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1418050017053036545', '1209733563293962241', '人大金仓', '8', '', 8, 1, 'admin', '2021-07-22 11:27:25', NULL, NULL);
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1418050075555188737', '1209733563293962241', '神通', '9', '', 9, 1, 'admin', '2021-07-22 11:27:39', NULL, NULL);
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1418050110669901826', '1209733563293962241', 'SQLite', '10', '', 10, 1, 'admin', '2021-07-22 11:27:47', NULL, NULL);
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1418050149475602434', '1209733563293962241', 'DB2', '11', '', 11, 1, 'admin', '2021-07-22 11:27:56', NULL, NULL);
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1418050209823248385', '1209733563293962241', 'Hsqldb', '12', '', 12, 1, 'admin', '2021-07-22 11:28:11', 'admin', '2021-07-22 11:28:27');
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1418050323111399425', '1209733563293962241', 'Derby', '13', '', 13, 1, 'admin', '2021-07-22 11:28:38', NULL, NULL);
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1418117316707590146', '1209733563293962241', 'H2', '14', '', 14, 1, 'admin', '2021-07-22 15:54:50', NULL, NULL);
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1418491604048449537', '1209733563293962241', '其他数据库', '15', '', 15, 1, 'admin', '2021-07-23 16:42:07', NULL, NULL);
-- 新增 hideTab 字段
ALTER TABLE `sys_permission`
ADD COLUMN `hide_tab` int(2) NULL COMMENT '是否隐藏tab: 0否,1是' AFTER `hidden`;
-- 【online表单】新增 low_app_id 字段
ALTER TABLE `onl_cgform_head`
ADD COLUMN `low_app_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '关联的应用ID' AFTER `des_form_code`;
-- online老数据,存在字符串类型key值不一致的情况,String改为string
UPDATE onl_cgform_field SET db_type = 'string' where binary db_type = 'String';
-- 积木报表升级
ALTER TABLE `jimu_report`
MODIFY COLUMN `view_count` bigint(15) NULL DEFAULT 0 COMMENT '浏览次数' AFTER `template`;
ALTER TABLE `jimu_report`
MODIFY COLUMN `json_str` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT 'json字符串' AFTER `type`;
ALTER TABLE `jimu_report_db_field`
ADD COLUMN `search_format` varchar(50) NULL COMMENT '查询时间格式化表达式' AFTER `search_value`;
ALTER TABLE `jimu_report_db_param`
ADD COLUMN `search_format` varchar(50) NULL COMMENT '查询时间格式化表达式' AFTER `dict_code`;
UPDATE jimu_report SET json_str=replace(json_str,'"subtotal":"totalField"','"funcname":"SUM"');
ALTER TABLE `jimu_report`
ADD COLUMN `css_str` text NULL COMMENT 'css增强' AFTER `view_count`,
ADD COLUMN `js_str` text NULL COMMENT 'js增强' AFTER `css_str`;
ALTER TABLE `jimu_report_link`
CHANGE COLUMN `expression` `requirement` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '条件' AFTER `link_chart_id`;
ALTER TABLE `jimu_report_db_field`
ADD COLUMN `ext_json` text NULL COMMENT '参数配置' AFTER `search_format`;
ALTER TABLE `jimu_report_db_param`
ADD COLUMN `ext_json` text NULL COMMENT '参数配置' AFTER `search_format`;
ALTER TABLE `jimu_report_db`
MODIFY COLUMN `is_list` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '是否是列表0否1是 默认0' AFTER `api_method`;
......@@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-boot-base-api</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>2.4.6</version>
<version>3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
......
......@@ -8,10 +8,10 @@ import java.util.SortedMap;
import javax.servlet.http.HttpServletRequest;
import org.jeecg.common.config.mqtoken.UserTokenContext;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.PathMatcherUtil;
import org.jeecg.common.config.mqtoken.UserTokenContext;
import org.jeecg.config.sign.interceptor.SignAuthConfiguration;
import org.jeecg.config.sign.util.HttpUtils;
import org.jeecg.config.sign.util.SignUtil;
......
......@@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-boot-base-api</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>2.4.6</version>
<version>3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
......
......@@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-boot-base</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>2.4.6</version>
<version>3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-base</artifactId>
<version>2.4.6</version>
<version>3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
......@@ -114,7 +114,7 @@
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>hibernate-re</artifactId>
<version>2.4.6-beta1</version>
<version>3.0.0-beta</version>
</dependency>
<!-- 数据库驱动 -->
......
package org.jeecg.common.api;
import org.jeecg.common.api.vo.OaWpsModel;
/**
* @Description: WPS通用接口
* @Author: wangshuai
* @Date:20200709
* @Version:V1.0
*/
public interface IWpsBaseAPI {
/*根据模板id获取模板信息*/
OaWpsModel getById(String id);
/*根据文件路径下载文件*/
void downloadOosFiles(String objectName, String basePath,String fileName);
/*WPS 设置数据存储,用于逻辑判断*/
void context(String type,String text);
/*删除WPS模板相关信息*/
void deleteById(String id);
}
package org.jeecg.common.api.desform;
import org.jeecg.common.system.vo.DictModel;
import java.util.List;
import java.util.Map;
/**
* 表单设计器【System】翻译API接口
*
* @author sunjianlei
*/
public interface ISysTranslateAPI {
/**
* 查询分类字典翻译
*/
List<String> categoryLoadDictItem(String ids);
/**
* 根据字典code加载字典text
*
* @param dictCode 顺序:tableName,text,code
* @param keys 要查询的key
* @return
*/
List<String> dictLoadDictItem(String dictCode, String keys);
/**
* 获取字典数据
*
* @param dictCode 顺序:tableName,text,code
* @param dictCode 要查询的key
* @return
*/
List<DictModel> dictGetDictItems(String dictCode);
/**
* 【JSearchSelectTag下拉搜索组件专用接口】
* 大数据量的字典表 走异步加载 即前端输入内容过滤数据
*
* @param dictCode 字典code格式:table,text,code
* @return
*/
List<DictModel> dictLoadDict(String dictCode, String keyword, Integer pageSize);
}
package org.jeecg.common.api.vo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
/**
* @Description: 文档
* @Author: jeecg-boot
* @Date: 2020-06-09
* @Version: V1.0
*/
@Data
@TableName("oa_wps_file")
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
@ApiModel(value = "oa_wps_file对象", description = "文档")
public class OaWpsModel implements Serializable {
private static final long serialVersionUID = 1L;
/**
* id
*/
@TableId(type = IdType.ASSIGN_ID)
@ApiModelProperty(value = "id")
private String id;
/**
* name
*/
@Excel(name = "name", width = 15)
@ApiModelProperty(value = "name")
private String name;
/**
* version
*/
@Excel(name = "version", width = 15)
@ApiModelProperty(value = "version")
private Integer version;
/**
* size
*/
@Excel(name = "size", width = 15)
@ApiModelProperty(value = "size")
private Integer size;
/**
* downloadUrl
*/
@Excel(name = "downloadUrl", width = 15)
@ApiModelProperty(value = "downloadUrl")
private String downloadUrl;
/**
* deleted
*/
@Excel(name = "deleted", width = 15)
@ApiModelProperty(value = "deleted")
private String deleted;
/**
* canDelete
*/
@Excel(name = "canDelete", width = 15)
@ApiModelProperty(value = "canDelete")
private String canDelete;
/**
* 创建人
*/
@ApiModelProperty(value = "创建人")
private String createBy;
/**
* 创建时间
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
@ApiModelProperty(value = "创建时间")
private Date createTime;
/**
* 更新人
*/
@ApiModelProperty(value = "更新人")
private String updateBy;
/**
* 更新时间
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
@ApiModelProperty(value = "更新时间")
private Date updateTime;
/**
* 组织机构编码
*/
@ApiModelProperty(value = "组织机构编码")
private String sysOrgCode;
@TableField(exist = false)
private String userId;
}
......@@ -30,7 +30,7 @@ public class Result<T> implements Serializable {
* 返回处理消息
*/
@ApiModelProperty(value = "返回处理消息")
private String message = "操作成功!";
private String message = "";
/**
* 返回代码
......@@ -51,7 +51,16 @@ public class Result<T> implements Serializable {
private long timestamp = System.currentTimeMillis();
public Result() {
}
/**
* 兼容VUE3版token失效不跳转登录页面
* @param code
* @param message
*/
public Result(Integer code,String message) {
this.code = code;
this.message = message;
}
public Result<T> success(String message) {
......@@ -66,7 +75,6 @@ public class Result<T> implements Serializable {
Result<Object> r = new Result<Object>();
r.setSuccess(true);
r.setCode(CommonConstant.SC_OK_200);
r.setMessage("成功");
return r;
}
......@@ -92,7 +100,6 @@ public class Result<T> implements Serializable {
Result<T> r = new Result<T>();
r.setSuccess(true);
r.setCode(CommonConstant.SC_OK_200);
r.setMessage("成功");
return r;
}
......
......@@ -25,6 +25,7 @@ import org.springframework.util.StringUtils;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
......@@ -261,7 +262,10 @@ public class DictAspect {
for (DictModel dict : texts) {
String redisKey = String.format("sys:cache:dictTable::SimpleKey [%s,%s]", dictCode, dict.getValue());
try {
redisTemplate.opsForValue().set(redisKey, dict.getText());
// update-begin-author:taoyan date:20211012 for: 字典表翻译注解缓存未更新 issues/3061
// 保留5分钟
redisTemplate.opsForValue().set(redisKey, dict.getText(), 300, TimeUnit.SECONDS);
// update-end-author:taoyan date:20211012 for: 字典表翻译注解缓存未更新 issues/3061
} catch (Exception e) {
log.warn(e.getMessage(), e);
}
......
......@@ -292,6 +292,7 @@ public interface CommonConstant {
public final static String X_ACCESS_TOKEN = "X-Access-Token";
public final static String X_SIGN = "X-Sign";
public final static String X_TIMESTAMP = "X-TIMESTAMP";
public final static String TOKEN_IS_INVALID_MSG = "Token失效,请重新登录!";
/**
* 多租户 请求头
......
......@@ -10,6 +10,8 @@ public interface DataBaseConstant {
public static final String DB_TYPE_POSTGRESQL = "POSTGRESQL";
public static final String DB_TYPE_SQLSERVER = "SQLSERVER";
public static final String DB_TYPE_MARIADB = "MARIADB";
public static final String DB_TYPE_DB2 = "DB2";
public static final String DB_TYPE_HSQL = "HSQL";
// // 数据库类型,对应 database_type 字典
// public static final String DB_TYPE_MYSQL_NUM = "1";
......
package org.jeecg.common.exception;
public class JeecgBoot401Exception extends RuntimeException {
private static final long serialVersionUID = 1L;
public JeecgBoot401Exception(String message){
super(message);
}
public JeecgBoot401Exception(Throwable cause)
{
super(cause);
}
public JeecgBoot401Exception(String message, Throwable cause)
{
super(message,cause);
}
}
......@@ -7,8 +7,10 @@ import org.jeecg.common.api.vo.Result;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.redis.connection.PoolException;
import org.springframework.http.HttpStatus;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.servlet.NoHandlerFoundException;
......@@ -29,11 +31,21 @@ public class JeecgBootExceptionHandler {
* 处理自定义异常
*/
@ExceptionHandler(JeecgBootException.class)
public Result<?> handleRRException(JeecgBootException e){
public Result<?> handleJeecgBootException(JeecgBootException e){
log.error(e.getMessage(), e);
return Result.error(e.getMessage());
}
/**
* 处理自定义异常
*/
@ExceptionHandler(JeecgBoot401Exception.class)
@ResponseStatus(HttpStatus.UNAUTHORIZED)
public Result<?> handleJeecgBoot401Exception(JeecgBoot401Exception e){
log.error(e.getMessage(), e);
return new Result(401,e.getMessage());
}
@ExceptionHandler(NoHandlerFoundException.class)
public Result<?> handlerNoFoundException(Exception e) {
log.error(e.getMessage(), e);
......
......@@ -37,8 +37,9 @@ import java.util.stream.Collectors;
*/
@Slf4j
public class JeecgController<T, S extends IService<T>> {
//issues/2933 JeecgController注入service时改用protected修饰,能避免重复引用service
@Autowired
S service;
protected S service;
@Value("${jeecg.path.upload}")
private String upLoadPath;
......
......@@ -99,7 +99,7 @@ public class QueryGenerator {
* <br>正确示例:QueryWrapper<JeecgDemo> queryWrapper = new QueryWrapper<JeecgDemo>();
* <br>3.也可以不使用这个方法直接调用 {@link #initQueryWrapper}直接获取实例
*/
public static void installMplus(QueryWrapper<?> queryWrapper,Object searchObj,Map<String, String[]> parameterMap) {
private static void installMplus(QueryWrapper<?> queryWrapper,Object searchObj,Map<String, String[]> parameterMap) {
/*
* 注意:权限查询由前端配置数据规则 当一个人有多个所属部门时候 可以在规则配置包含条件 orgCode 包含 #{sys_org_code}
......@@ -216,7 +216,7 @@ public class QueryGenerator {
}
//多字段排序 TODO 需要修改前端
public static void doMultiFieldsOrder(QueryWrapper<?> queryWrapper,Map<String, String[]> parameterMap) {
private static void doMultiFieldsOrder(QueryWrapper<?> queryWrapper,Map<String, String[]> parameterMap) {
String column=null,order=null;
if(parameterMap!=null&& parameterMap.containsKey(ORDER_COLUMN)) {
column = parameterMap.get(ORDER_COLUMN)[0];
......@@ -258,7 +258,7 @@ public class QueryGenerator {
* @param parameterMap 参数对象
* @param fieldColumnMap 实体字段和数据库列对应的map
*/
public static void doSuperQuery(QueryWrapper<?> queryWrapper,Map<String, String[]> parameterMap, Map<String,String> fieldColumnMap) {
private static void doSuperQuery(QueryWrapper<?> queryWrapper,Map<String, String[]> parameterMap, Map<String,String> fieldColumnMap) {
if(parameterMap!=null&& parameterMap.containsKey(SUPER_QUERY_PARAMS)){
String superQueryParams = parameterMap.get(SUPER_QUERY_PARAMS)[0];
String superQueryMatchType = parameterMap.get(SUPER_QUERY_MATCH_TYPE) != null ? parameterMap.get(SUPER_QUERY_MATCH_TYPE)[0] : MatchTypeEnum.AND.getValue();
......@@ -347,7 +347,7 @@ public class QueryGenerator {
* @param value
* @return
*/
private static QueryRuleEnum convert2Rule(Object value) {
public static QueryRuleEnum convert2Rule(Object value) {
// 避免空数据
// update-begin-author:taoyan date:20210629 for: 查询条件输入空格导致return null后续判断导致抛出null异常
if (value == null) {
......@@ -595,7 +595,7 @@ public class QueryGenerator {
/**
* 获取请求对应的数据权限规则
* 获取请求对应的数据权限规则 TODO 相同列权限多个 有问题
* @return
*/
public static Map<String, SysPermissionDataRuleModel> getRuleMap() {
......@@ -616,30 +616,6 @@ public class QueryGenerator {
return ruleMap;
}
/**
* 获取请求对应的数据权限规则
* @return
*/
public static Map<String, SysPermissionDataRuleModel> getRuleMap(List<SysPermissionDataRuleModel> list) {
Map<String, SysPermissionDataRuleModel> ruleMap = new HashMap<String, SysPermissionDataRuleModel>();
if(list==null){
list =JeecgDataAutorUtils.loadDataSearchConditon();
}
if(list != null&&list.size()>0){
if(list.get(0)==null){
return ruleMap;
}
for (SysPermissionDataRuleModel rule : list) {
String column = rule.getRuleColumn();
if(QueryRuleEnum.SQL_RULES.getValue().equals(rule.getRuleConditions())) {
column = SQL_RULES_COLUMN+rule.getId();
}
ruleMap.put(column, rule);
}
}
return ruleMap;
}
private static void addRuleToQueryWrapper(SysPermissionDataRuleModel dataRule, String name, Class propertyType, QueryWrapper<?> queryWrapper) {
QueryRuleEnum rule = QueryRuleEnum.getByValue(dataRule.getRuleConditions());
if(rule.equals(QueryRuleEnum.IN) && ! propertyType.equals(String.class)) {
......@@ -761,7 +737,7 @@ public class QueryGenerator {
* @param dataBaseType
* @return
*/
public static String getSingleSqlByRule(QueryRuleEnum rule,String field,Object value,boolean isString, String dataBaseType) {
private static String getSingleSqlByRule(QueryRuleEnum rule,String field,Object value,boolean isString, String dataBaseType) {
String res = "";
switch (rule) {
case GT:
......@@ -813,7 +789,7 @@ public class QueryGenerator {
* @param isString
* @return
*/
public static String getSingleSqlByRule(QueryRuleEnum rule,String field,Object value,boolean isString) {
private static String getSingleSqlByRule(QueryRuleEnum rule,String field,Object value,boolean isString) {
return getSingleSqlByRule(rule, field, value, isString, null);
}
......
......@@ -5,13 +5,19 @@ import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Joiner;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.DataBaseConstant;
import org.jeecg.common.exception.JeecgBootException;
......@@ -32,6 +38,28 @@ public class JwtUtil {
public static final long EXPIRE_TIME = 30 * 60 * 1000;
/**
*
* @param response
* @param code
* @param errorMsg
*/
public static void responseError(ServletResponse response, Integer code, String errorMsg) {
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
Result jsonResult = new Result(code, errorMsg);
OutputStream os = null;
try {
os = httpServletResponse.getOutputStream();
httpServletResponse.setCharacterEncoding("UTF-8");
httpServletResponse.setStatus(401);
os.write(new ObjectMapper().writeValueAsString(jsonResult).getBytes("UTF-8"));
os.flush();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 校验token是否正确
*
* @param token 密钥
......
package org.jeecg.common.util;
import java.io.*;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.sql.DataSource;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.toolkit.JdbcUtils;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.DataBaseConstant;
import org.jeecg.common.util.filter.FileTypeFilter;
import org.jeecg.common.util.oss.OssBootUtil;
import org.jeecgframework.poi.util.PoiPublicUtil;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.toolkit.JdbcUtils;
import lombok.extern.slf4j.Slf4j;
import javax.sql.DataSource;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Slf4j
public class CommonUtils {
......@@ -208,6 +212,42 @@ public class CommonUtils {
}
/**
* 根据数据源key获取DataSourceProperty
* @param sourceKey
* @return
*/
public static DataSourceProperty getDataSourceProperty(String sourceKey){
DynamicDataSourceProperties prop = SpringContextUtils.getApplicationContext().getBean(DynamicDataSourceProperties.class);
Map<String, DataSourceProperty> map = prop.getDatasource();
DataSourceProperty db = (DataSourceProperty)map.get(sourceKey);
return db;
}
/**
* 根据sourceKey 获取数据源连接
* @param sourceKey
* @return
* @throws SQLException
*/
public static Connection getDataSourceConnect(String sourceKey) throws SQLException {
if (oConvertUtils.isEmpty(sourceKey)) {
sourceKey = "master";
}
DynamicDataSourceProperties prop = SpringContextUtils.getApplicationContext().getBean(DynamicDataSourceProperties.class);
Map<String, DataSourceProperty> map = prop.getDatasource();
DataSourceProperty db = (DataSourceProperty)map.get(sourceKey);
if(db==null){
return null;
}
DriverManagerDataSource ds = new DriverManagerDataSource ();
ds.setDriverClassName(db.getDriverClassName());
ds.setUrl(db.getUrl());
ds.setUsername(db.getUsername());
ds.setPassword(db.getPassword());
return ds.getConnection();
}
/**
* 获取数据库类型
* @param dataSource
* @return
......
......@@ -38,7 +38,7 @@ public class ImportExcelUtil {
}
}
public static List<String> importDateSave(List<Object> list, Class serviceClass,List<String> errorMessage,String errorFlag) {
public static List<String> importDateSave(List<?> list, Class serviceClass, List<String> errorMessage, String errorFlag) {
IService bean =(IService) SpringContextUtils.getBean(serviceClass);
for (int i = 0; i < list.size(); i++) {
try {
......
package org.jeecg.common.util;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jeecg.common.constant.ServiceNameConstants;
import org.springframework.beans.BeansException;
......@@ -38,6 +39,12 @@ public class SpringContextUtils implements ApplicationContextAware {
public static HttpServletRequest getHttpServletRequest() {
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
}
/**
* 获取HttpServletResponse
*/
public static HttpServletResponse getHttpServletResponse() {
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
}
/**
* 获取项目根路径 basePath
......
......@@ -2,9 +2,9 @@ package org.jeecg.common.util;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.jeecg.common.api.CommonAPI;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.exception.JeecgBoot401Exception;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser;
......@@ -40,27 +40,57 @@ public class TokenUtils {
String token = getTokenByRequest(request);
if (StringUtils.isBlank(token)) {
throw new AuthenticationException("Token不能为空!");
throw new JeecgBoot401Exception("Token不能为空!");
}
// 解密获得username,用于和数据库进行对比
String username = JwtUtil.getUsername(token);
if (username == null) {
throw new AuthenticationException("Token非法无效!");
throw new JeecgBoot401Exception("Token非法无效!");
}
// 查询用户信息
LoginUser user = commonAPI.getUserByName(username);
if (user == null) {
throw new AuthenticationException("用户不存在!");
throw new JeecgBoot401Exception("用户不存在!");
}
// 判断用户状态
if (user.getStatus() != 1) {
throw new AuthenticationException("账号已锁定,请联系管理员!");
throw new JeecgBoot401Exception("账号已锁定,请联系管理员!");
}
// 校验token是否超时失效 & 或者账号密码是否错误
if (!jwtTokenRefresh(token, username, user.getPassword(), redisUtil)) {
throw new AuthenticationException("Token失效,请重新登录");
throw new JeecgBoot401Exception("Token失效,请重新登录");
}
return true;
}
/**
* 验证Token
*/
public static boolean verifyToken(String token, CommonAPI commonAPI, RedisUtil redisUtil) {
if (StringUtils.isBlank(token)) {
throw new JeecgBoot401Exception("token不能为空!");
}
// 解密获得username,用于和数据库进行对比
String username = JwtUtil.getUsername(token);
if (username == null) {
throw new JeecgBoot401Exception("token非法无效!");
}
// 查询用户信息
LoginUser user = commonAPI.getUserByName(username);
if (user == null) {
throw new JeecgBoot401Exception("用户不存在!");
}
// 判断用户状态
if (user.getStatus() != 1) {
throw new JeecgBoot401Exception("账号已被锁定,请联系管理员!");
}
// 校验token是否超时失效 & 或者账号密码是否错误
if (!jwtTokenRefresh(token, username, user.getPassword(), redisUtil)) {
throw new JeecgBoot401Exception(CommonConstant.TOKEN_IS_INVALID_MSG);
}
return true;
}
......@@ -95,34 +125,4 @@ public class TokenUtils {
return false;
}
/**
* 验证Token
*/
public static boolean verifyToken(String token, CommonAPI commonAPI, RedisUtil redisUtil) {
if (StringUtils.isBlank(token)) {
throw new AuthenticationException("token不能为空!");
}
// 解密获得username,用于和数据库进行对比
String username = JwtUtil.getUsername(token);
if (username == null) {
throw new AuthenticationException("token非法无效!");
}
// 查询用户信息
LoginUser user = commonAPI.getUserByName(username);
if (user == null) {
throw new AuthenticationException("用户不存在!");
}
// 判断用户状态
if (user.getStatus() != 1) {
throw new AuthenticationException("账号已被锁定,请联系管理员!");
}
// 校验token是否超时失效 & 或者账号密码是否错误
if (!jwtTokenRefresh(token, username, user.getPassword(), redisUtil)) {
throw new AuthenticationException("Token失效,请重新登录!");
}
return true;
}
}
package org.jeecg.common.util.dynamic.db;
import com.baomidou.mybatisplus.annotation.DbType;
import org.jeecg.common.constant.DataBaseConstant;
import java.util.HashMap;
import java.util.Map;
/**
* 数据库类型判断
......@@ -8,6 +12,34 @@ import com.baomidou.mybatisplus.annotation.DbType;
*/
public class DbTypeUtils {
public static Map<String, String> dialectMap = new HashMap<String, String>();
static{
dialectMap.put("mysql", "org.hibernate.dialect.MySQL5InnoDBDialect");
dialectMap.put("mariadb", "org.hibernate.dialect.MariaDBDialect");// 1 --
dialectMap.put("oracle", "org.hibernate.dialect.OracleDialect");//1
dialectMap.put("oracle12c", "org.hibernate.dialect.OracleDialect"); // TODO 没找到不确定
dialectMap.put("db2", "org.hibernate.dialect.DB2390Dialect"); // 1xx
dialectMap.put("h2", "org.hibernate.dialect.HSQLDialect");// H2数据库
dialectMap.put("hsql", "org.hibernate.dialect.HSQLDialect");// HSQL数据库 1
dialectMap.put("sqlite", "org.jeecg.modules.online.config.dialect.SQLiteDialect"); //SQLite数据库 应用平台mobile
dialectMap.put("postgresql", "org.hibernate.dialect.PostgreSQLDialect"); //1 --
dialectMap.put("sqlserver2005", "org.hibernate.dialect.SQLServer2005Dialect");
dialectMap.put("sqlserver", "org.hibernate.dialect.SQLServerDialect"); //1
dialectMap.put("dm", "org.hibernate.dialect.OracleDialect");//达梦数据库 [国产] 1--
dialectMap.put("xugu", "org.hibernate.dialect.HSQLDialect"); //虚谷数据库
dialectMap.put("kingbasees", "org.hibernate.dialect.PostgreSQLDialect"); //人大金仓 [国产] 1
dialectMap.put("phoenix", "org.hibernate.dialect.HSQLDialect"); // Phoenix HBase数据库
dialectMap.put("zenith", "org.hibernate.dialect.PostgreSQLDialect"); // Gauss 数据库
dialectMap.put("clickhouse", "org.hibernate.dialect.MySQLDialect"); //阿里云PolarDB
dialectMap.put("gbase", "org.hibernate.dialect.PostgreSQLDialect"); // 南大通用数据库 TODO 没找到不确定
dialectMap.put("oscar", "org.hibernate.dialect.PostgreSQLDialect"); //神通数据库 [国产] TODO 没找到不确定
dialectMap.put("sybase", "org.hibernate.dialect.SybaseDialect"); //Sybase ASE 数据库
dialectMap.put("oceanbase", "org.hibernate.dialect.PostgreSQLDialect"); //OceanBase 数据库 TODO 没找到不确定
dialectMap.put("Firebird", "org.hibernate.dialect.FirebirdDialect");
dialectMap.put("highgo", "org.hibernate.dialect.HSQLDialect"); //瀚高数据库
dialectMap.put("other", "org.hibernate.dialect.PostgreSQLDialect");
}
public static boolean dbTypeIsMySQL(DbType dbType) {
return dbTypeIf(dbType, DbType.MYSQL, DbType.MARIADB, DbType.CLICK_HOUSE, DbType.SQLITE);
}
......@@ -24,6 +56,37 @@ public class DbTypeUtils {
return dbTypeIf(dbType, DbType.POSTGRE_SQL, DbType.KINGBASE_ES, DbType.GAUSS);
}
/**
* 根据枚举类 获取数据库类型的字符串
* @param dbType
* @return
*/
public static String getDbTypeString(DbType dbType){
if(DbType.DB2.equals(dbType)){
return DataBaseConstant.DB_TYPE_DB2;
}else if(DbType.HSQL.equals(dbType)){
return DataBaseConstant.DB_TYPE_HSQL;
}else if(dbTypeIsOracle(dbType)){
return DataBaseConstant.DB_TYPE_ORACLE;
}else if(dbTypeIsSQLServer(dbType)){
return DataBaseConstant.DB_TYPE_SQLSERVER;
}else if(dbTypeIsPostgre(dbType)){
return DataBaseConstant.DB_TYPE_POSTGRESQL;
}
return DataBaseConstant.DB_TYPE_MYSQL;
}
/**
* 根据枚举类 获取数据库方言字符串
* @param dbType
* @return
*/
public static String getDbDialect(DbType dbType){
return dialectMap.get(dbType.getDb());
}
/**
* 判断数据库类型
*/
......
......@@ -112,6 +112,16 @@ public class DynamicDBUtil {
}
/**
* 根据数据源获取NamedParameterJdbcTemplate
* @param dbKey
* @return
*/
private static NamedParameterJdbcTemplate getNamedParameterJdbcTemplate(String dbKey) {
DruidDataSource dataSource = getDbSourceByDbKey(dbKey);
return new NamedParameterJdbcTemplate(dataSource);
}
/**
* Executes the SQL statement in this <code>PreparedStatement</code> object,
* which must be an SQL Data Manipulation Language (DML) statement, such as <code>INSERT</code>, <code>UPDATE</code> or
* <code>DELETE</code>; or an SQL statement that returns nothing,
......@@ -222,6 +232,31 @@ public class DynamicDBUtil {
}
/**
* 查询数量
* @param dbKey
* @param sql
* @param param
* @return
*/
public static Map<String, Object> queryCount(String dbKey, String sql, Map<String, Object> param){
NamedParameterJdbcTemplate npJdbcTemplate = getNamedParameterJdbcTemplate(dbKey);
return npJdbcTemplate.queryForMap(sql, param);
}
/**
* 查询列表数据
* @param dbKey
* @param sql
* @param param
* @return
*/
public static List<Map<String, Object>> findListByNamedParam(final String dbKey, String sql, Map<String, Object> param) {
NamedParameterJdbcTemplate npJdbcTemplate = getNamedParameterJdbcTemplate(dbKey);
List<Map<String, Object>> list = npJdbcTemplate.queryForList(sql, param);
return list;
}
/**
* 支持miniDao语法操作的查询
*
* @param dbKey 数据源标识
......
package org.jeecg.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 加载项目配置
*/
@Component("jeeccgBaseConfig")
@ConfigurationProperties(prefix = "jeecg")
public class JeeccgBaseConfig {
/**
* 是否启用安全模式
*/
private Boolean safeMode = false;
public Boolean getSafeMode() {
return safeMode;
}
public void setSafeMode(Boolean safeMode) {
this.safeMode = safeMode;
}
}
......@@ -35,6 +35,11 @@ public class MybatisPlusSaasConfig {
static {
tenantTable.add("demo");
// //角色、菜单、部门
// tenantTable.add("sys_role");
// tenantTable.add("sys_permission");
// tenantTable.add("sys_depart");
}
......
......@@ -118,8 +118,12 @@ public class ShiroConfig {
filterChainDefinitionMap.put("/jmreport/**", "anon");
filterChainDefinitionMap.put("/**/*.js.map", "anon");
filterChainDefinitionMap.put("/**/*.css.map", "anon");
//大屏模板例子
filterChainDefinitionMap.put("/test/bigScreen/**", "anon");
//测试示例
filterChainDefinitionMap.put("/test/bigScreen/**", "anon"); //大屏模板例子
//filterChainDefinitionMap.put("/test/jeecgDemo/rabbitMqClientTest/**", "anon"); //MQ测试
//filterChainDefinitionMap.put("/test/jeecgDemo/html", "anon"); //模板页面
//filterChainDefinitionMap.put("/test/jeecgDemo/redis/**", "anon"); //redis测试
//websocket排除
filterChainDefinitionMap.put("/websocket/**", "anon");//系统通知和公告
......
package org.jeecg.config.shiro;
import cn.hutool.crypto.SecureUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
......@@ -11,7 +10,6 @@ import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.jeecg.common.api.CommonAPI;
import org.jeecg.common.constant.CacheConstant;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser;
......@@ -97,7 +95,14 @@ public class ShiroRealm extends AuthorizingRealm {
throw new AuthenticationException("token为空!");
}
// 校验token有效性
LoginUser loginUser = this.checkUserTokenIsEffect(token);
LoginUser loginUser = null;
try {
loginUser = this.checkUserTokenIsEffect(token);
} catch (AuthenticationException e) {
JwtUtil.responseError(SpringContextUtils.getHttpServletResponse(),401,e.getMessage());
e.printStackTrace();
return null;
}
return new SimpleAuthenticationInfo(loginUser, token, getName());
}
......@@ -125,7 +130,7 @@ public class ShiroRealm extends AuthorizingRealm {
}
// 校验token是否超时失效 & 或者账号密码是否错误
if (!jwtTokenRefresh(token, username, loginUser.getPassword())) {
throw new AuthenticationException("Token失效,请重新登录!");
throw new AuthenticationException(CommonConstant.TOKEN_IS_INVALID_MSG);
}
//update-begin-author:taoyan date:20210609 for:校验用户的tenant_id和前端传过来的是否一致
String userTenantIds = loginUser.getRelTenantIds();
......
package org.jeecg.config.shiro.filters;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.config.mybatis.TenantContext;
import org.jeecg.config.shiro.JwtToken;
......@@ -48,7 +48,9 @@ public class JwtFilter extends BasicHttpAuthenticationFilter {
executeLogin(request, response);
return true;
} catch (Exception e) {
throw new AuthenticationException("Token失效,请重新登录", e);
JwtUtil.responseError(response,401,CommonConstant.TOKEN_IS_INVALID_MSG);
return false;
//throw new AuthenticationException("Token失效,请重新登录", e);
}
}
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-base</artifactId>
<version>2.4.6</version>
<version>3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<description>公共模块</description>
......
package org.jeecg.common.config.mqtoken;
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* 存放token到上下文供队列调用feign使用
......
......@@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-boot-parent</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>2.4.6</version>
<version>3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
......
......@@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-boot-parent</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>2.4.6</version>
<version>3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
......
package org.jeecg.modules.demo.mock;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.jeecg.common.api.vo.Result;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.swing.filechooser.FileSystemView;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
......@@ -8,20 +17,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.swing.filechooser.FileSystemView;
import org.apache.commons.io.IOUtils;
import org.jeecg.common.api.vo.Result;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import lombok.extern.slf4j.Slf4j;
@RestController
@RequestMapping("/mock/api")
@Slf4j
......@@ -42,8 +37,9 @@ public class MockController {
}
@GetMapping(value = "/asynTreeList")
public String asynTreeList(String id) {
return readJson(JSON_PATH + "/asyn_tree_list_" + id + ".json");
public Result asynTreeList(String id) {
String json = readJson(JSON_PATH + "/asyn_tree_list_" + id + ".json");
return Result.OK(JSON.parseArray(json));
}
@GetMapping(value = "/user")
......
{
"status": 200,
"success": true,
"message": "ok",
"result": [
[
{
"id": 1,
"name": "首页",
......@@ -24,6 +20,4 @@
"orderNum": 3,
"hasChildren": true
}
],
"timestamp": 1554950583837
}
\ No newline at end of file
]
\ No newline at end of file
{
"status": 200,
"success": true,
"message": "ok",
"result": [
[
{
"id": 11,
"name": "首页",
......@@ -24,6 +20,4 @@
"orderNum": 3,
"hasChildren": true
}
],
"timestamp": 1554950583837
}
\ No newline at end of file
]
\ No newline at end of file
{
"status": 200,
"success": true,
"message": "ok",
"result": [
[
{
"id": 21,
"name": "弹框选择Demo",
......@@ -24,6 +20,4 @@
"orderNum": 3,
"hasChildren": false
}
],
"timestamp": 1554950583837
}
\ No newline at end of file
]
\ No newline at end of file
{
"status": 200,
"success": true,
"message": "ok",
"result": [
[
{
"id": 31,
"name": "性能监控",
......@@ -24,6 +20,4 @@
"orderNum": 3,
"hasChildren": false
}
],
"timestamp": 1554950583837
}
\ No newline at end of file
]
\ No newline at end of file
{
"status": 200,
"success": true,
"message": "ok",
"result": [
[
{
"id": 311,
"name": "Redis监控",
......@@ -24,6 +20,4 @@
"orderNum": 3,
"hasChildren": false
}
],
"timestamp": 1554950583837
}
\ No newline at end of file
]
\ No newline at end of file
package org.jeecg.modules.demo.test.controller;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
......@@ -282,4 +283,38 @@ public class JeecgDemoController extends JeecgController<JeecgDemo, IJeecgDemoSe
return Result.OK(pageList);
}
/*----------------------------------------外部获取权限示例------------------------------------*/
/**
* online api增强 列表
* @param params
* @return
*/
@PostMapping("/enhanceJavaListHttp")
public Result enhanceJavaListHttp(@RequestBody JSONObject params) {
log.info(" =========================================================== ");
log.info("params: " + params.toJSONString());
log.info("params.tableName: " + params.getString("tableName"));
log.info("params.json: " + params.getJSONObject("json").toJSONString());
JSONArray dataList = params.getJSONArray("dataList");
log.info("params.dataList: " + dataList.toJSONString());
log.info(" =========================================================== ");
return Result.OK(dataList);
}
/**
* online api增强 表单
* @param params
* @return
*/
@PostMapping("/enhanceJavaFormHttp")
public Result enhanceJavaFormHttp(@RequestBody JSONObject params) {
log.info(" =========================================================== ");
log.info("params: " + params.toJSONString());
log.info("params.tableName: " + params.getString("tableName"));
log.info("params.json: " + params.getJSONObject("json").toJSONString());
log.info(" =========================================================== ");
return Result.OK("1");
}
}
......@@ -28,10 +28,6 @@ import lombok.experimental.Accessors;
@TableName("demo")
public class JeecgDemo extends JeecgEntity implements Serializable {
private static final long serialVersionUID = 1L;
/** 部门编码 */
@Excel(name="部门编码",width=25)
@ApiModelProperty(value = "部门编码")
private java.lang.String sysOrgCode;
/** 姓名 */
@Excel(name="姓名",width=25)
@ApiModelProperty(value = "姓名")
......@@ -75,7 +71,10 @@ public class JeecgDemo extends JeecgEntity implements Serializable {
/** 个人简介 */
@ApiModelProperty(value = "个人简介")
private java.lang.String content;
@ApiModelProperty(value = "租户ID")
private java.lang.Integer tenantId;
/** 部门编码 */
@Excel(name="部门编码",width=25)
@ApiModelProperty(value = "部门编码")
private java.lang.String sysOrgCode;
}
......@@ -10,6 +10,6 @@ WORKDIR /jeecg-boot
EXPOSE 8080
ADD ./target/jeecg-boot-module-system-2.4.6.jar ./
ADD ./target/jeecg-boot-module-system-3.0.jar ./
CMD sleep 60;java -Djava.security.egd=file:/dev/./urandom -jar jeecg-boot-module-system-2.4.6.jar
\ No newline at end of file
CMD sleep 60;java -Djava.security.egd=file:/dev/./urandom -jar jeecg-boot-module-system-3.0.jar
\ No newline at end of file
......@@ -4,7 +4,7 @@
<parent>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-parent</artifactId>
<version>2.4.6</version>
<version>3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
......@@ -54,7 +54,7 @@
<dependency>
<groupId>org.jeecgframework.jimureport</groupId>
<artifactId>jimureport-spring-boot-starter</artifactId>
<version>1.3.78</version>
<version>1.4.0</version>
</dependency>
......@@ -62,7 +62,7 @@
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-module-demo</artifactId>
<version>2.4.6</version>
<version>3.0</version>
</dependency>
</dependencies>
......
package org.jeecg;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.Context;
import org.apache.tomcat.util.scan.StandardJarScanner;
import org.jeecg.common.util.oConvertUtils;
import org.springframework.boot.SpringApplication;
//import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;
import java.net.InetAddress;
......
......@@ -80,8 +80,12 @@ public class WebSocket {
Session session = sessionPool.get(userId);
if (session != null && session.isOpen()) {
try {
//update-begin-author:taoyan date:20211012 for: websocket报错 https://gitee.com/jeecg/jeecg-boot/issues/I4C0MU
synchronized (session){
log.info("【websocket消息】 单点消息:" + message);
session.getAsyncRemote().sendText(message);
session.getBasicRemote().sendText(message);
}
//update-end-author:taoyan date:20211012 for: websocket报错 https://gitee.com/jeecg/jeecg-boot/issues/I4C0MU
} catch (Exception e) {
e.printStackTrace();
}
......
......@@ -2,10 +2,6 @@ package org.jeecg.modules.oss.controller;
import javax.servlet.http.HttpServletRequest;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.query.QueryGenerator;
......@@ -13,14 +9,18 @@ import org.jeecg.modules.oss.entity.OSSFile;
import org.jeecg.modules.oss.service.IOSSFileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
/**
* 云存储示例 DEMO
*/
@Slf4j
@Controller
@RequestMapping("/sys/oss/file")
......
......@@ -89,7 +89,7 @@ public class QuartzJobController {
* @return
*/
//@RequiresRoles("admin")
@RequestMapping(value = "/edit", method = RequestMethod.PUT)
@RequestMapping(value = "/edit", method ={RequestMethod.PUT, RequestMethod.POST})
public Result<?> eidt(@RequestBody QuartzJob quartzJob) {
try {
quartzJobService.editAndScheduleJob(quartzJob);
......@@ -228,8 +228,13 @@ public class QuartzJobController {
params.setHeadRows(1);
params.setNeedSave(true);
try {
List<Object> listQuartzJobs = ExcelImportUtil.importExcel(file.getInputStream(), QuartzJob.class, params);
List<QuartzJob> listQuartzJobs = ExcelImportUtil.importExcel(file.getInputStream(), QuartzJob.class, params);
//add-begin-author:taoyan date:20210909 for:导入定时任务,并不会被启动和调度,需要手动点击启动,才会加入调度任务中 #2986
for(QuartzJob job: listQuartzJobs){
job.setStatus(CommonConstant.STATUS_DISABLE);
}
List<String> list = ImportExcelUtil.importDateSave(listQuartzJobs, IQuartzJobService.class, errorMessage,CommonConstant.SQL_INDEX_UNIQ_JOB_CLASS_NAME);
//add-end-author:taoyan date:20210909 for:导入定时任务,并不会被启动和调度,需要手动点击启动,才会加入调度任务中 #2986
errorLines+=list.size();
successLines+=(listQuartzJobs.size()-errorLines);
} catch (Exception e) {
......
......@@ -118,6 +118,30 @@ public class LoginController {
return result;
}
/**
* 【vue3专用】获取用户信息
*/
@GetMapping("/user/getUserInfo")
public Result<JSONObject> getUserInfo(HttpServletRequest request){
Result<JSONObject> result = new Result<JSONObject>();
String username = JwtUtil.getUserNameByToken(request);
if(oConvertUtils.isNotEmpty(username)) {
// 根据用户名查询用户信息
SysUser sysUser = sysUserService.getUserByName(username);
//用户登录信息
Result<JSONObject> resultObj=userInfo(sysUser, result);
JSONObject jsonObject=resultObj.getResult();
JSONObject obj=new JSONObject();
obj.put("userInfo",jsonObject.get("userInfo"));
obj.put("sysAllDictItems", sysDictService.queryAllDictItems());
result.setResult(obj);
result.success("");
}
return result;
}
/**
* 退出登录
* @param request
......
package org.jeecg.modules.system.controller;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.modules.system.entity.SysUser;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* vue3前端临时接口
*/
@RestController
@RequestMapping("/")
@Slf4j
public class MockVue3Controller {
}
......@@ -140,7 +140,7 @@ public class SysAnnouncementController {
* @param sysAnnouncement
* @return
*/
@RequestMapping(value = "/edit", method = RequestMethod.PUT)
@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST})
public Result<SysAnnouncement> eidt(@RequestBody SysAnnouncement sysAnnouncement) {
Result<SysAnnouncement> result = new Result<SysAnnouncement>();
SysAnnouncement sysAnnouncementEntity = sysAnnouncementService.getById(sysAnnouncement.getId());
......@@ -314,7 +314,7 @@ public class SysAnnouncementController {
* @return
*/
@RequestMapping(value = "/listByUser", method = RequestMethod.GET)
public Result<Map<String,Object>> listByUser() {
public Result<Map<String, Object>> listByUser(@RequestParam(required = false, defaultValue = "5") Integer pageSize) {
Result<Map<String,Object>> result = new Result<Map<String,Object>>();
LoginUser sysUser = (LoginUser)SecurityUtils.getSubject().getPrincipal();
String userId = sysUser.getId();
......@@ -347,9 +347,9 @@ public class SysAnnouncementController {
}
}
// 2.查询用户未读的系统消息
Page<SysAnnouncement> anntMsgList = new Page<SysAnnouncement>(0,5);
Page<SysAnnouncement> anntMsgList = new Page<SysAnnouncement>(0, pageSize);
anntMsgList = sysAnnouncementService.querySysCementPageByUserId(anntMsgList,userId,"1");//通知公告消息
Page<SysAnnouncement> sysMsgList = new Page<SysAnnouncement>(0,5);
Page<SysAnnouncement> sysMsgList = new Page<SysAnnouncement>(0, pageSize);
sysMsgList = sysAnnouncementService.querySysCementPageByUserId(sysMsgList,userId,"2");//系统消息
Map<String,Object> sysMsgMap = new HashMap<String, Object>();
sysMsgMap.put("sysMsgList", sysMsgList.getRecords());
......
......@@ -8,8 +8,10 @@ import javax.servlet.http.HttpServletRequest;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.WebsocketConst;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.message.websocket.WebSocket;
import org.jeecg.modules.system.entity.SysAnnouncementSend;
import org.jeecg.modules.system.model.AnnouncementSendModel;
import org.jeecg.modules.system.service.ISysAnnouncementSendService;
......@@ -45,6 +47,8 @@ import lombok.extern.slf4j.Slf4j;
public class SysAnnouncementSendController {
@Autowired
private ISysAnnouncementSendService sysAnnouncementSendService;
@Autowired
private WebSocket webSocket;
/**
* 分页列表查询
......@@ -235,6 +239,9 @@ public class SysAnnouncementSendController {
updateWrapper.last("where user_id ='"+userId+"'");
SysAnnouncementSend announcementSend = new SysAnnouncementSend();
sysAnnouncementSendService.update(announcementSend, updateWrapper);
JSONObject socketParams = new JSONObject();
socketParams.put(WebsocketConst.MSG_CMD, WebsocketConst.CMD_TOPIC);
webSocket.sendMessage(socketParams.toJSONString());
result.setSuccess(true);
result.setMessage("全部已读");
return result;
......
......@@ -111,7 +111,7 @@ public class SysCategoryController {
* @param sysCategory
* @return
*/
@PutMapping(value = "/edit")
@RequestMapping(value = "/edit", method = { RequestMethod.PUT,RequestMethod.POST })
public Result<SysCategory> edit(@RequestBody SysCategory sysCategory) {
Result<SysCategory> result = new Result<SysCategory>();
SysCategory sysCategoryEntity = sysCategoryService.getById(sysCategory.getId());
......
......@@ -128,7 +128,7 @@ public class SysDataSourceController extends JeecgController<SysDataSource, ISys
*/
@AutoLog(value = "多数据源管理-编辑")
@ApiOperation(value = "多数据源管理-编辑", notes = "多数据源管理-编辑")
@PutMapping(value = "/edit")
@RequestMapping(value = "/edit", method ={RequestMethod.PUT, RequestMethod.POST})
public Result<?> edit(@RequestBody SysDataSource sysDataSource) {
try {
SysDataSource d = sysDataSourceService.getById(sysDataSource.getId());
......
......@@ -97,7 +97,7 @@ public class SysDepartController {
* @return
*/
@RequestMapping(value = "/queryTreeList", method = RequestMethod.GET)
public Result<List<SysDepartTreeModel>> queryTreeList() {
public Result<List<SysDepartTreeModel>> queryTreeList(@RequestParam(name = "ids", required = false) String ids) {
Result<List<SysDepartTreeModel>> result = new Result<>();
try {
// 从内存中读取
......@@ -105,8 +105,13 @@ public class SysDepartController {
// if (CollectionUtils.isEmpty(list)) {
// list = sysDepartService.queryTreeList();
// }
if(oConvertUtils.isNotEmpty(ids)){
List<SysDepartTreeModel> departList = sysDepartService.queryTreeList(ids);
result.setResult(departList);
}else{
List<SysDepartTreeModel> list = sysDepartService.queryTreeList();
result.setResult(list);
}
result.setSuccess(true);
} catch (Exception e) {
log.error(e.getMessage(),e);
......@@ -116,14 +121,15 @@ public class SysDepartController {
/**
* 异步查询部门list
*
* @param parentId 父节点 异步加载时传递
* @param ids 前端回显是传递
* @return
*/
@RequestMapping(value = "/queryDepartTreeSync", method = RequestMethod.GET)
public Result<List<SysDepartTreeModel>> queryDepartTreeSync(@RequestParam(name = "pid", required = false) String parentId) {
public Result<List<SysDepartTreeModel>> queryDepartTreeSync(@RequestParam(name = "pid", required = false) String parentId,@RequestParam(name = "ids", required = false) String ids) {
Result<List<SysDepartTreeModel>> result = new Result<>();
try {
List<SysDepartTreeModel> list = sysDepartService.queryTreeListByPid(parentId);
List<SysDepartTreeModel> list = sysDepartService.queryTreeListByPid(parentId,ids);
result.setResult(list);
result.setSuccess(true);
} catch (Exception e) {
......
......@@ -359,7 +359,7 @@ public class SysDictController {
* @return
*/
//@RequiresRoles({"admin"})
@RequestMapping(value = "/edit", method = RequestMethod.PUT)
@RequestMapping(value = "/edit", method = { RequestMethod.PUT,RequestMethod.POST })
public Result<SysDict> edit(@RequestBody SysDict sysDict) {
Result<SysDict> result = new Result<SysDict>();
SysDict sysdict = sysDictService.getById(sysDict.getId());
......
......@@ -93,7 +93,7 @@ public class SysDictItemController {
* @return
*/
//@RequiresRoles({"admin"})
@RequestMapping(value = "/edit", method = RequestMethod.PUT)
@RequestMapping(value = "/edit", method = { RequestMethod.PUT,RequestMethod.POST })
@CacheEvict(value={CacheConstant.SYS_DICT_CACHE, CacheConstant.SYS_ENABLE_DICT_CACHE}, allEntries=true)
public Result<SysDictItem> edit(@RequestBody SysDictItem sysDictItem) {
Result<SysDictItem> result = new Result<SysDictItem>();
......
......@@ -14,16 +14,13 @@ import org.jeecg.common.constant.enums.RoleIndexConfigEnum;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.MD5Util;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.system.entity.SysDepartPermission;
import org.jeecg.modules.system.entity.SysPermission;
import org.jeecg.modules.system.entity.SysPermissionDataRule;
import org.jeecg.modules.system.entity.SysRolePermission;
import org.jeecg.config.JeeccgBaseConfig;
import org.jeecg.modules.system.entity.*;
import org.jeecg.modules.system.model.SysPermissionTree;
import org.jeecg.modules.system.model.TreeModel;
import org.jeecg.modules.system.service.*;
import org.jeecg.modules.system.util.PermissionDataUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import java.util.*;
......@@ -56,12 +53,9 @@ public class SysPermissionController {
@Autowired
private ISysUserService sysUserService;
/**
* 系统安全模式(true开启,false关闭)
*/
@Value(value = "${jeecg.safeMode:false}")
private Boolean sysSafeMode;
@Autowired
private JeeccgBaseConfig jeeccgBaseConfig;
/**
* 加载数据节点
......@@ -238,6 +232,9 @@ public class SysPermissionController {
JSONObject json = new JSONObject();
JSONArray menujsonArray = new JSONArray();
this.getPermissionJsonArray(menujsonArray, metaList, null);
//一级菜单下的子菜单全部是隐藏路由,则一级菜单不显示
this.handleFirstLevelMenuHidden(menujsonArray);
JSONArray authjsonArray = new JSONArray();
this.getAuthJsonArray(authjsonArray, metaList);
//查询所有的权限
......@@ -254,9 +251,37 @@ public class SysPermissionController {
json.put("auth", authjsonArray);
//全部权限配置集合(按钮权限,访问权限)
json.put("allAuth", allauthjsonArray);
json.put("sysSafeMode", sysSafeMode);
json.put("sysSafeMode", jeeccgBaseConfig.getSafeMode());
result.setResult(json);
result.success("查询成功");
} catch (Exception e) {
result.error500("查询失败:" + e.getMessage());
log.error(e.getMessage(), e);
}
return result;
}
/**
* 【vue3专用】查询用户拥有的按钮/表单访问权限
* @return
*/
@RequestMapping(value = "/getPermCode", method = RequestMethod.GET)
public Result<?> getPermCode() {
Result<List<String>> result = new Result<List<String>>();
try {
//直接获取当前用户
LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
//获取当前用户的权限集合
List<SysPermission> metaList = sysPermissionService.queryByUser(loginUser.getUsername());
//按钮权限(用户拥有的权限集合)
List<String> authList = metaList.stream()
.filter((permission) -> permission.getMenuType().equals(CommonConstant.MENU_TYPE_2)
&& CommonConstant.STATUS_1.equals(permission.getStatus())
)
.collect(() -> new ArrayList<String>(),
(list, permission) -> list.add(permission.getPerms()),
(list1, list2) -> list1.addAll(list2)
);
result.setResult(authList);
} catch (Exception e) {
result.error500("查询失败:" + e.getMessage());
log.error(e.getMessage(), e);
......@@ -380,7 +405,7 @@ public class SysPermissionController {
}
/**
* 异步加载数据节点
* 异步加载数据节点 [接口是废的,没有用到]
*
* @return
*/
......@@ -483,6 +508,31 @@ public class SysPermissionController {
}
/**
* 一级菜单的子菜单全部是隐藏路由,则一级菜单不显示
* @param jsonArray
*/
private void handleFirstLevelMenuHidden(JSONArray jsonArray) {
jsonArray = jsonArray.stream().map(obj -> {
JSONObject returnObj = new JSONObject();
JSONObject jsonObj = (JSONObject)obj;
if(jsonObj.containsKey("children")){
JSONArray childrens = jsonObj.getJSONArray("children");
childrens = childrens.stream().filter(arrObj -> !"true".equals(((JSONObject) arrObj).getString("hidden"))).collect(Collectors.toCollection(JSONArray::new));
if(childrens==null || childrens.size()==0){
jsonObj.put("hidden",true);
//vue3版本兼容代码
JSONObject meta = new JSONObject();
meta.put("hideMenu",true);
jsonObj.put("meta", meta);
}
}
return returnObj;
}).collect(Collectors.toCollection(JSONArray::new));
}
/**
* 获取权限JSON数组
* @param jsonArray
* @param allList
......@@ -605,16 +655,18 @@ public class SysPermissionController {
json.put("name", urlToRouteName(permission.getUrl()));
}
JSONObject meta = new JSONObject();
// 是否隐藏路由,默认都是显示的
if (permission.isHidden()) {
json.put("hidden", true);
//vue3版本兼容代码
meta.put("hideMenu",true);
}
// 聚合路由
if (permission.isAlwaysShow()) {
json.put("alwaysShow", true);
}
json.put("component", permission.getComponent());
JSONObject meta = new JSONObject();
// 由用户设置是否缓存页面 用布尔值
if (permission.isKeepAlive()) {
meta.put("keepAlive", true);
......@@ -654,6 +706,11 @@ public class SysPermissionController {
if (isWWWHttpUrl(permission.getUrl())) {
meta.put("url", permission.getUrl());
}
// update-begin--Author:sunjianlei Date:20210918 for:新增适配vue3项目的隐藏tab功能
if (permission.isHideTab()) {
meta.put("hideTab", true);
}
// update-end--Author:sunjianlei Date:20210918 for:新增适配vue3项目的隐藏tab功能
json.put("meta", meta);
}
......@@ -776,7 +833,6 @@ public class SysPermissionController {
try {
List<SysPermissionDataRule> permRuleList = sysPermissionDataRuleService.queryPermissionRule(sysPermissionDataRule);
result.setResult(permRuleList);
result.success("查询成功!");
} catch (Exception e) {
log.error(e.getMessage(), e);
result.error500("操作失败");
......
......@@ -107,7 +107,7 @@ public class SysPositionController {
*/
@AutoLog(value = "职务表-编辑")
@ApiOperation(value = "职务表-编辑", notes = "职务表-编辑")
@PutMapping(value = "/edit")
@RequestMapping(value = "/edit", method ={RequestMethod.PUT, RequestMethod.POST})
public Result<SysPosition> edit(@RequestBody SysPosition sysPosition) {
Result<SysPosition> result = new Result<SysPosition>();
SysPosition sysPositionEntity = sysPositionService.getById(sysPosition.getId());
......
......@@ -129,7 +129,7 @@ public class SysRoleController {
* @return
*/
//@RequiresRoles({"admin"})
@RequestMapping(value = "/edit", method = RequestMethod.PUT)
@RequestMapping(value = "/edit",method = {RequestMethod.PUT,RequestMethod.POST})
public Result<SysRole> edit(@RequestBody SysRole role) {
Result<SysRole> result = new Result<SysRole>();
SysRole sysrole = sysRoleService.getById(role.getId());
......
......@@ -17,6 +17,7 @@ import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
......@@ -43,7 +44,23 @@ public class SysTenantController {
public Result<IPage<SysTenant>> queryPageList(SysTenant sysTenant,@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,HttpServletRequest req) {
Result<IPage<SysTenant>> result = new Result<IPage<SysTenant>>();
//---author:zhangyafei---date:20210916-----for: 租户管理添加日期范围查询---
Date beginDate=null;
Date endDate=null;
if(oConvertUtils.isNotEmpty(sysTenant)) {
beginDate=sysTenant.getBeginDate();
endDate=sysTenant.getEndDate();
sysTenant.setBeginDate(null);
sysTenant.setEndDate(null);
}
//---author:zhangyafei---date:20210916-----for: 租户管理添加日期范围查询---
QueryWrapper<SysTenant> queryWrapper = QueryGenerator.initQueryWrapper(sysTenant, req.getParameterMap());
//---author:zhangyafei---date:20210916-----for: 租户管理添加日期范围查询---
if(oConvertUtils.isNotEmpty(sysTenant)){
queryWrapper.ge(oConvertUtils.isNotEmpty(beginDate),"begin_date",beginDate);
queryWrapper.le(oConvertUtils.isNotEmpty(endDate),"end_date",endDate);
}
//---author:zhangyafei---date:20210916-----for: 租户管理添加日期范围查询---
Page<SysTenant> page = new Page<SysTenant>(pageNo, pageSize);
IPage<SysTenant> pageList = sysTenantService.page(page, queryWrapper);
result.setSuccess(true);
......@@ -58,7 +75,7 @@ public class SysTenantController {
*/
@RequestMapping(value = "/add", method = RequestMethod.POST)
public Result<SysTenant> add(@RequestBody SysTenant sysTenant) {
Result<SysTenant> result = new Result<SysTenant>();
Result<SysTenant> result = new Result();
if(sysTenantService.getById(sysTenant.getId())!=null){
return result.error500("该编号已存在!");
}
......@@ -77,18 +94,17 @@ public class SysTenantController {
* @param
* @return
*/
@RequestMapping(value = "/edit", method = RequestMethod.PUT)
@RequestMapping(value = "/edit", method ={RequestMethod.PUT, RequestMethod.POST})
public Result<SysTenant> edit(@RequestBody SysTenant tenant) {
Result<SysTenant> result = new Result<SysTenant>();
Result<SysTenant> result = new Result();
SysTenant sysTenant = sysTenantService.getById(tenant.getId());
if(sysTenant==null) {
result.error500("未找到对应实体");
}else {
return result.error500("未找到对应实体");
}
boolean ok = sysTenantService.updateById(tenant);
if(ok) {
result.success("修改成功!");
}
}
return result;
}
......@@ -97,7 +113,7 @@ public class SysTenantController {
* @param id
* @return
*/
@RequestMapping(value = "/delete", method = RequestMethod.DELETE)
@RequestMapping(value = "/delete", method ={RequestMethod.DELETE, RequestMethod.POST})
public Result<?> delete(@RequestParam(name="id",required=true) String id) {
sysTenantService.removeTenantById(id);
return Result.ok("删除成功");
......
......@@ -107,7 +107,7 @@ public class SysUserAgentController {
* @param sysUserAgent
* @return
*/
@PutMapping(value = "/edit")
@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST})
public Result<SysUserAgent> edit(@RequestBody SysUserAgent sysUserAgent) {
Result<SysUserAgent> result = new Result<SysUserAgent>();
SysUserAgent sysUserAgentEntity = sysUserAgentService.getById(sysUserAgent.getId());
......
......@@ -157,7 +157,7 @@ public class SysUserController {
//@RequiresRoles({"admin"})
//@RequiresPermissions("user:edit")
@RequestMapping(value = "/edit", method = RequestMethod.PUT)
@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST})
public Result<SysUser> edit(@RequestBody JSONObject jsonObject) {
Result<SysUser> result = new Result<SysUser>();
try {
......@@ -172,6 +172,10 @@ public class SysUserController {
user.setPassword(sysUser.getPassword());
String roles = jsonObject.getString("selectedroles");
String departs = jsonObject.getString("selecteddeparts");
if(oConvertUtils.isEmpty(departs)){
//vue3.0前端只传递了departIds
departs=user.getDepartIds();
}
// 修改用户走一个service 保证事务
sysUserService.editUser(user, roles, departs);
result.success("修改成功!");
......
package org.jeecg.modules.system.controller;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.*;
import javax.annotation.Resource;
import org.apache.commons.lang.StringUtils;
......@@ -55,45 +52,38 @@ public class SysUserOnlineController {
private BaseCommonService baseCommonService;
@RequestMapping(value = "/list", method = RequestMethod.GET)
public Result<Page<SysUserOnlineVO>> list(@RequestParam(name="username", required=false) String username, @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize) {
public Result<Page<SysUserOnlineVO>> list(@RequestParam(name="username", required=false) String username,
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,@RequestParam(name="pageSize", defaultValue="10") Integer pageSize) {
Collection<String> keys = redisTemplate.keys(CommonConstant.PREFIX_USER_TOKEN + "*");
SysUserOnlineVO online;
List<SysUserOnlineVO> onlineList = new ArrayList<SysUserOnlineVO>();
for (String key : keys) {
online = new SysUserOnlineVO();
String token = (String) redisUtil.get(key);
if (!StringUtils.isEmpty(token)){
String token = (String)redisUtil.get(key);
if (StringUtils.isNotEmpty(token)) {
SysUserOnlineVO online = new SysUserOnlineVO();
online.setToken(token);
//TODO 改成一次性查询
LoginUser loginUser = sysBaseAPI.getUserByName(JwtUtil.getUsername(token));
BeanUtils.copyProperties(loginUser, online);
if (StringUtils.isNotEmpty(username)) {
if (StringUtils.equals(username, online.getUsername())) {
onlineList.add(online);
}
} else {
onlineList.add(online);
}
}
}
Collections.reverse(onlineList);
Page<SysUserOnlineVO> page = new Page<SysUserOnlineVO>(pageNo, pageSize);
int count = onlineList.size();
List<SysUserOnlineVO> pages = new ArrayList<>();
//计算当前页第一条数据的下标
int currId = pageNo>1 ? (pageNo-1)*pageSize:0;
for (int i=0; i<pageSize && i<count - currId;i++){
pages.add(onlineList.get(currId+i));
// 计算当前页第一条数据的下标
int currId = pageNo > 1 ? (pageNo - 1) * pageSize : 0;
for (int i = 0; i < pageSize && i < count - currId; i++) {
pages.add(onlineList.get(currId + i));
}
page.setSize(pageSize);
page.setCurrent(pageNo);
page.setTotal(count);
//计算分页总页数
page.setPages(count %10 == 0 ? count/10 :count/10+1);
// 计算分页总页数
page.setPages(count % 10 == 0 ? count / 10 : count / 10 + 1);
page.setRecords(pages);
Collections.reverse(onlineList);
onlineList.removeAll(Collections.singleton(null));
Result<Page<SysUserOnlineVO>> result = new Result<Page<SysUserOnlineVO>>();
result.setSuccess(true);
result.setResult(page);
......
......@@ -131,6 +131,11 @@ public class SysPermission implements Serializable {
private boolean hidden;
/**
* 是否隐藏Tab: 0否,1是(默认值0)
*/
private boolean hideTab;
/**
* 创建时间
*/
private Date createTime;
......
......@@ -127,7 +127,7 @@
select ${text} as "title",
${code} as "key",
<if test="hasChildField != null and hasChildField != ''">
(case when ${hasChildField} = '1' then 0 else 1 end) as isLeaf,
${hasChildField} as "isLeaf",
</if>
${pidField} as parentId
from ${table}
......
......@@ -8,7 +8,7 @@
<result column="name" property="title" jdbcType="VARCHAR"/>
<result column="icon" property="icon" jdbcType="VARCHAR"/>
<result column="parent_id" property="parentId" jdbcType="VARCHAR"/>
<result column="leaf_flag" property="isLeaf" jdbcType="INTEGER"/>
<result column="is_leaf" property="isLeaf" jdbcType="INTEGER"/>
</resultMap>
<!-- 通过<resultMap>映射实体类属性名和表的字段名对应关系 -->
......@@ -26,7 +26,7 @@
,parent_id
,name
,icon
,leaf_flag
,is_leaf
FROM sys_permission
WHERE 1=1
<choose>
......
......@@ -29,6 +29,13 @@ public interface ISysDepartService extends IService<SysDepart>{
*/
List<SysDepartTreeModel> queryTreeList();
/**
* 查询所有部门信息,并分节点进行显示
* @return
*/
List<SysDepartTreeModel> queryTreeList(String ids);
/**
* 查询所有部门DepartId信息,并分节点进行显示
* @return
......@@ -112,7 +119,7 @@ public interface ISysDepartService extends IService<SysDepart>{
* 获取我的部门下级所有部门
* @return
*/
List<SysDepartTreeModel> queryTreeListByPid(String parentId);
List<SysDepartTreeModel> queryTreeListByPid(String parentId,String ids);
/**
* 获取某个部门的所有父级部门的ID
......
......@@ -114,8 +114,12 @@ public class SysAnnouncementServiceImpl extends ServiceImpl<SysAnnouncementMappe
}
@Override
public Page<SysAnnouncement> querySysCementPageByUserId(Page<SysAnnouncement> page, String userId,String msgCategory) {
public Page<SysAnnouncement> querySysCementPageByUserId(Page<SysAnnouncement> page, String userId, String msgCategory) {
if (page.getSize() == -1) {
return page.setRecords(sysAnnouncementMapper.querySysCementListByUserId(null, userId, msgCategory));
} else {
return page.setRecords(sysAnnouncementMapper.querySysCementListByUserId(page, userId, msgCategory));
}
}
}
......@@ -25,6 +25,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.function.Consumer;
/**
* <p>
......@@ -77,8 +78,8 @@ public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart
/**
* queryTreeList 对应 queryTreeList 查询所有的部门数据,以树结构形式响应给前端
*/
@Cacheable(value = CacheConstant.SYS_DEPARTS_CACHE)
@Override
@Cacheable(value = CacheConstant.SYS_DEPARTS_CACHE)
public List<SysDepartTreeModel> queryTreeList() {
LambdaQueryWrapper<SysDepart> query = new LambdaQueryWrapper<SysDepart>();
query.eq(SysDepart::getDelFlag, CommonConstant.DEL_FLAG_0.toString());
......@@ -89,6 +90,26 @@ public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart
return listResult;
}
/**
* queryTreeList 根据部门id查询,前端回显调用
*/
@Override
public List<SysDepartTreeModel> queryTreeList(String ids) {
List<SysDepartTreeModel> listResult=new ArrayList<>();
LambdaQueryWrapper<SysDepart> query = new LambdaQueryWrapper<SysDepart>();
query.eq(SysDepart::getDelFlag, CommonConstant.DEL_FLAG_0.toString());
if(oConvertUtils.isNotEmpty(ids)){
query.in(true,SysDepart::getId,ids.split(","));
}
query.orderByAsc(SysDepart::getDepartOrder);
List<SysDepart> list= this.list(query);
for (SysDepart depart : list) {
listResult.add(new SysDepartTreeModel(depart));
}
return listResult;
}
@Cacheable(value = CacheConstant.SYS_DEPART_IDS_CACHE)
@Override
public List<DepartIdModel> queryDepartIdTreeList() {
......@@ -458,11 +479,27 @@ public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart
/**
* 根据parentId查询部门树
* @param parentId
* @param ids 前端回显传递
* @return
*/
@Override
public List<SysDepartTreeModel> queryTreeListByPid(String parentId) {
List<SysDepart> list = this.baseMapper.queryTreeListByPid(parentId);
public List<SysDepartTreeModel> queryTreeListByPid(String parentId,String ids) {
Consumer<LambdaQueryWrapper<SysDepart>> square = i -> {
if (oConvertUtils.isNotEmpty(ids)) {
i.in(SysDepart::getId, ids.split(","));
} else {
if(oConvertUtils.isEmpty(parentId)){
i.and(q->q.isNull(true,SysDepart::getParentId).or().eq(true,SysDepart::getParentId,""));
}else{
i.eq(true,SysDepart::getParentId,parentId);
}
}
};
LambdaQueryWrapper<SysDepart> lqw=new LambdaQueryWrapper();
lqw.eq(true,SysDepart::getDelFlag,CommonConstant.DEL_FLAG_0);
lqw.func(square);
lqw.orderByDesc(SysDepart::getDepartOrder);
List<SysDepart> list = list(lqw);
List<SysDepartTreeModel> records = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
SysDepart depart = list.get(i);
......
......@@ -9,6 +9,7 @@ import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.base.BaseMap;
import org.jeecg.common.constant.CacheConstant;
import org.jeecg.common.constant.GlobalConstants;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.system.entity.SysGatewayRoute;
import org.jeecg.modules.system.mapper.SysGatewayRouteMapper;
import org.jeecg.modules.system.service.ISysGatewayRouteService;
......@@ -17,7 +18,9 @@ import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Description: gateway路由管理
......@@ -42,7 +45,7 @@ public class SysGatewayRouteServiceImpl extends ServiceImpl<SysGatewayRouteMappe
@Override
public void deleteById(String id) {
this.removeById(id);
this.resreshRouter();
this.resreshRouter(id);
}
@Override
......@@ -52,7 +55,14 @@ public class SysGatewayRouteServiceImpl extends ServiceImpl<SysGatewayRouteMappe
try {
json = json.getJSONObject("router");
String id = json.getString("id");
SysGatewayRoute route = getById(id);
//update-begin-author:taoyan date:20211025 for: oracle路由网关新增小bug /issues/I4EV2J
SysGatewayRoute route;
if(oConvertUtils.isEmpty(id)){
route = new SysGatewayRoute();
}else{
route = getById(id);
}
//update-end-author:taoyan date:20211025 for: oracle路由网关新增小bug /issues/I4EV2J
if (ObjectUtil.isEmpty(route)) {
route = new SysGatewayRoute();
}
......@@ -71,10 +81,10 @@ public class SysGatewayRouteServiceImpl extends ServiceImpl<SysGatewayRouteMappe
route.setStatus(json.getInteger("status"));
}
this.saveOrUpdate(route);
resreshRouter();
resreshRouter(null);
} catch (Exception e) {
log.error("路由配置解析失败", e);
resreshRouter();
resreshRouter(null);
e.printStackTrace();
}
}
......@@ -82,11 +92,12 @@ public class SysGatewayRouteServiceImpl extends ServiceImpl<SysGatewayRouteMappe
/**
* 更新redis路由缓存
*/
private void resreshRouter() {
private void resreshRouter(String id) {
//更新redis路由缓存
addRoute2Redis(CacheConstant.GATEWAY_ROUTES);
BaseMap params = new BaseMap();
params.put(GlobalConstants.HANDLER_NAME, "loderRouderHandler");
params.put("routerId", id);
//刷新网关
redisTemplate.convertAndSend(GlobalConstants.REDIS_TOPIC_NAME, params);
}
......
package org.jeecg.modules.system.service.impl.desform;
import org.jeecg.common.api.desform.ISysTranslateAPI;
import org.jeecg.common.system.vo.DictModel;
import org.jeecg.modules.system.service.ISysCategoryService;
import org.jeecg.modules.system.service.ISysDictService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 表单设计器翻译API接口(system实现类)
*
* @author sunjianlei
*/
@Component
public class SysTranslateAPIImpl implements ISysTranslateAPI {
@Autowired
ISysCategoryService sysCategoryService;
@Autowired
ISysDictService sysDictService;
@Override
public List<String> categoryLoadDictItem(String ids) {
return sysCategoryService.loadDictItem(ids, false);
}
@Override
public List<String> dictLoadDictItem(String dictCode, String keys) {
String[] params = dictCode.split(",");
return sysDictService.queryTableDictByKeys(params[0], params[1], params[2], keys, false);
}
@Override
public List<DictModel> dictGetDictItems(String dictCode) {
List<DictModel> ls = sysDictService.getDictItems(dictCode);
if (ls == null) {
ls = new ArrayList<>();
}
return ls;
}
@Override
public List<DictModel> dictLoadDict(String dictCode, String keyword, Integer pageSize) {
return sysDictService.loadDict(dictCode, keyword, pageSize);
}
}
//package org.jeecg.modules.system.util;
//
//import lombok.extern.slf4j.Slf4j;
//
///**
// * 多租户 tenant_id存储器
// */
//@Slf4j
//public class TenantContext {
//
// private static ThreadLocal<String> currentTenant = new ThreadLocal<>();
//
// public static void setTenant(String tenant) {
// log.debug(" setting tenant to " + tenant);
// currentTenant.set(tenant);
// }
//
// public static String getTenant() {
// return currentTenant.get();
// }
//
// public static void clear(){
// currentTenant.remove();
// }
//}
package org.jeecg.modules.system.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.jeecg.common.aspect.annotation.Dict;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
/**
*
* @Author: chenli
* @Date: 2020-06-07
* @Version: V1.0
*/
@Data
public class SysOnlineVO {
/**
* 会话id
*/
private String id;
/**
* 会话编号
*/
private String token;
/**
* 用户名
*/
private String username;
/**
* 用户名
*/
private String realname;
/**
* 头像
*/
private String avatar;
/**
* 生日
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birthday;
/**
* 性别(1:男 2:女)
*/
@Dict(dicCode = "sex")
private Integer sex;
/**
* 手机号
*/
private String phone;
}
......@@ -131,7 +131,7 @@ spring:
connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
datasource:
master:
url: jdbc:mysql://127.0.0.1:3306/jeecg-boot?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
url: jdbc:mysql://127.0.0.1:3306/jeecg-boot-os-re?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
......@@ -176,6 +176,8 @@ minidao :
#DB类型(mysql | postgresql | oracle | sqlserver| other)
db-type: mysql
jeecg :
# 是否启用安全模式
safeMode: false
# 签名密钥串(前后端要一致,正式发布请自行修改)
signatureSecret: dd05f1c54d63749eda95f9fa6d49v442a
# 本地:local\Minio:minio\阿里云:alioss
......
......@@ -174,6 +174,8 @@ mybatis-plus:
minidao :
base-package: org.jeecg.modules.jmreport.*
jeecg :
# 是否启用安全模式
safeMode: false
# 签名密钥串(前后端要一致,正式发布请自行修改)
signatureSecret: dd05f1c54d63749eda95f9fa6d49v442a
# 本地:local\Minio:minio\阿里云:alioss
......
......@@ -174,6 +174,8 @@ mybatis-plus:
minidao :
base-package: org.jeecg.modules.jmreport.*
jeecg :
# 是否启用安全模式
safeMode: false
# 签名密钥串(前后端要一致,正式发布请自行修改)
signatureSecret: dd05f1c54d63749eda95f9fa6d49v442a
# 本地:local\Minio:minio\阿里云:alioss
......
......@@ -9,6 +9,6 @@ ${AnsiColor.BRIGHT_BLUE}
${AnsiColor.BRIGHT_GREEN}
Jeecg Boot Version: 2.4.6
Jeecg Boot Version: 3.0
Spring Boot Version: ${spring-boot.version}${spring-boot.formatted-version}
${AnsiColor.BLACK}
<template>
<div>
<#assign list_need_category=false>
<#assign list_need_pca=false>
<#assign bpm_flag=false>
<#-- 开始循环 -->
<#list columns as po>
<#if po.fieldDbName=='bpm_status'>
<#assign bpm_flag=true>
</#if>
<#if po.classType=='cat_tree' && po.dictText?default("")?trim?length == 0>
<#assign list_need_category=true>
</#if>
<#if po.classType=='pca'>
<#assign list_need_pca=true>
</#if>
</#list>
<#-- 结束循环 -->
<!--引用表格-->
<BasicTable @register="registerTable" :rowSelection="rowSelection">
<!--插槽:table标题-->
<template #tableTitle>
<a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
<ExcelButton :config="excelConfig"></ExcelButton>
<a-dropdown v-if="checkedKeys.length > 0">
<template #overlay>
<a-menu>
<a-menu-item key="1" @click="batchHandleDelete">
<Icon icon="ant-design:delete-outlined"></Icon>
删除
</a-menu-item>
</a-menu>
</template>
<a-button>批量操作
<Icon icon="mdi:chevron-down"></Icon>
</a-button>
</a-dropdown>
</template>
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)"/>
</template>
<!--字段回显插槽-->
<template #htmlSlot="{text}">
<div v-html="text"></div>
</template>
<template #fileSlot="{text}">
<span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
<a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)">下载</a-button>
</template>
</BasicTable>
<!-- 表单区域 -->
<${entityName}Modal @register="registerModal" @success="handleSuccess"></${entityName}Modal>
</div>
</template>
<script lang="ts" setup>
import {ref, computed, unref} from 'vue';
import {BasicTable, useTable, TableAction} from '/@/components/Table';
import ExcelButton from '/@/components/jeecg/ExcelButton.vue'
import {useModal} from '/@/components/Modal';
import ${entityName}Modal from './components/${entityName}Modal.vue'
import {columns, searchFormSchema} from './${entityName?uncap_first}.data';
import {list, deleteOne, batchDelete, getImportUrl,getExportUrl} from './${entityName?uncap_first}.api';
<#if list_need_category>
import { loadCategoryData } from '/@/api/common/api'
import { getAuthCache, setAuthCache } from '/@/utils/auth';
import { DB_DICT_DATA_KEY } from '/@/enums/cacheEnum';
</#if>
const checkedKeys = ref<Array<string | number>>([]);
//注册model
const [registerModal, {openModal}] = useModal();
//注册table数据
const [registerTable, {reload}] = useTable({
title: '${tableVo.ftlDescription}',
api: list,
rowKey: 'id',
columns,
formConfig: {
labelWidth: 120,
schemas: searchFormSchema,
autoSubmitOnEnter:true,
showAdvancedButton:true,
fieldMapToTime: [
<#list columns as po>
<#if po.isQuery=='Y'>
<#if po.queryMode!='single'>
<#if po.classType=='date'>
['${po.fieldName}', ['${po.fieldName}_begin', '${po.fieldName}_end'], 'YYYY-MM-DD'],
<#elseif po.classType=='datetime'>
['${po.fieldName}', ['${po.fieldName}_begin', '${po.fieldName}_end'], 'YYYY-MM-DD HH:mm:ss'],
</#if>
</#if>
</#if>
</#list>
],
},
striped: true,
useSearchForm: true,
showTableSetting: true,
clickToRowSelect: false,
bordered: true,
showIndexColumn: false,
tableSetting: {fullScreen: true},
actionColumn: {
width: 120,
title: '操作',
dataIndex: 'action',
slots: {customRender: 'action'},
fixed: 'right',
},
})
/**
* excel导入导出配置
*/
const excelConfig = {
export: {
name:'${tableVo.ftlDescription}',
url: getExportUrl,
},
import: {
url: getImportUrl,
success: reload,
}
}
/**
* 选择列配置
*/
const rowSelection = {
type: 'checkbox',
columnWidth: 30,
selectedRowKeys: checkedKeys,
onChange: onSelectChange
}
/**
* 选择事件
*/
function onSelectChange(selectedRowKeys: (string | number)[]) {
checkedKeys.value = selectedRowKeys;
}
/**
* 新增事件
*/
function handleAdd() {
openModal(true, {
isUpdate: false,
showFooter: true,
});
}
/**
* 编辑事件
*/
function handleEdit(record: Recordable) {
openModal(true, {
record,
isUpdate: true,
showFooter: true,
});
}
/**
* 详情
*/
function handleDetail(record: Recordable) {
openModal(true, {
record,
isUpdate: true,
showFooter: false,
});
}
/**
* 删除事件
*/
async function handleDelete(record) {
await deleteOne({id: record.id}, reload);
}
/**
* 批量删除事件
*/
async function batchHandleDelete() {
await batchDelete({ids: checkedKeys.value}, reload);
}
/**
* 成功回调
*/
function handleSuccess() {
reload();
}
/**
* 操作栏
*/
function getTableAction(record){
return [
{
label: '编辑',
onClick: handleEdit.bind(null, record),
}
]
}
/**
* 下拉操作栏
*/
function getDropDownAction(record){
return [
{
label: '详情',
onClick: handleDetail.bind(null, record),
}, {
label: '删除',
popConfirm: {
title: '是否确认删除',
confirm: handleDelete.bind(null, record),
}
}
]
}
<#if list_need_category>
/**
* 初始化字典配置
*/
function initDictConfig(){
<#list columns as po>
<#if (po.isQuery=='Y' || po.isShowList=='Y') && po.classType!='popup'>
<#if po.classType=='cat_tree' && list_need_category==true>
loadCategoryData({code:'${po.dictField?default("")}'}).then((res) => {
if (res) {
let allDictDate = getAuthCache(DB_DICT_DATA_KEY);
if(!allDictDate['${po.dictField?default("")}']){
Object.assign(allDictDate,{'${po.dictField?default("")}':res})
}
setAuthCache(DB_DICT_DATA_KEY,allDictDate)
}
})
</#if>
</#if>
</#list>
}
initDictConfig();
</#if>
</script>
<style scoped>
</style>
\ No newline at end of file
import {defHttp} from '/@/utils/http/axios';
import {Modal} from 'ant-design-vue';
enum Api {
list = '/${entityPackage}/${entityName?uncap_first}/list',
save='/${entityPackage}/${entityName?uncap_first}/add',
edit='/${entityPackage}/${entityName?uncap_first}/edit',
deleteOne = '/${entityPackage}/${entityName?uncap_first}/delete',
deleteBatch = '/${entityPackage}/${entityName?uncap_first}/deleteBatch',
importExcel = '/${entityPackage}/${entityName?uncap_first}/importExcel',
exportXls = '/${entityPackage}/${entityName?uncap_first}/exportXls',
}
/**
* 导出api
* @param params
*/
export const getExportUrl = Api.exportXls;
/**
* 导入api
*/
export const getImportUrl = Api.importExcel;
/**
* 列表接口
* @param params
*/
export const list = (params) =>
defHttp.get({url: Api.list, params});
/**
* 删除单个
*/
export const deleteOne = (params,handleSuccess) => {
return defHttp.delete({url: Api.deleteOne, params}, {joinParamsToUrl: true}).then(() => {
handleSuccess();
});
}
/**
* 批量删除
* @param params
*/
export const batchDelete = (params, handleSuccess) => {
Modal.confirm({
title: '确认删除',
content: '是否删除选中数据',
okText: '确认',
cancelText: '取消',
onOk: () => {
return defHttp.delete({url: Api.deleteBatch, data: params}, {joinParamsToUrl: true}).then(() => {
handleSuccess();
});
}
});
}
/**
* 保存或者更新
* @param params
*/
export const saveOrUpdate = (params, isUpdate) => {
let url = isUpdate ? Api.edit : Api.save;
return defHttp.post({url: url, params});
}
import {BasicColumn} from '/@/components/Table';
import {FormSchema} from '/@/components/Table';
import { rules} from '/@/utils/helper/validator';
import { render } from '/@/utils/common/renderUtils';
//列表数据
export const columns: BasicColumn[] = [
<#list columns as po>
<#if po.isShowList =='Y' && po.fieldName !='id'>
{
title: '${po.filedComment}',
align:"center",
<#if po.sort=='Y'>
sorter: true,
</#if>
<#if po.classType=='date'>
dataIndex: '${po.fieldName}',
customRender:({text}) =>{
return !text?"":(text.length>10?text.substr(0,10):text)
},
<#elseif po.fieldDbType=='Blob'>
dataIndex: '${po.fieldName}String'
<#elseif po.classType=='umeditor'>
dataIndex: '${po.fieldName}',
slots: { customRender: 'htmlSlot' },
<#elseif po.classType=='pca'>
dataIndex: '${po.fieldName}',
slots: { customRender: 'pcaSlot' },//TODO 未翻译
<#elseif po.classType=='file'>
dataIndex: '${po.fieldName}',
slots: { customRender: 'fileSlot' },
<#elseif po.classType=='image'>
dataIndex: '${po.fieldName}',
customRender:render.renderAvatar,
<#elseif po.classType=='switch'>
dataIndex: '${po.fieldName}',
<#assign switch_extend_arr=['Y','N']>
<#if po.dictField?default("")?contains("[")>
<#assign switch_extend_arr=po.dictField?eval>
</#if>
<#list switch_extend_arr as a>
<#if a_index == 0>
<#assign switch_extend_arr1=a>
<#else>
<#assign switch_extend_arr2=a>
</#if>
</#list>
customRender:({text}) => {
return render.renderSwitch(text, [{text:'是',value:'${switch_extend_arr1}'},{text:'否',value:'${switch_extend_arr2}'}])
},
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user'>
dataIndex: '${po.fieldName}_dictText'
<#elseif po.classType=='cat_tree'>
dataIndex: '${po.fieldName}',
<#if po.dictText?default("")?trim?length == 0>
customRender:({text}) => {
return render.renderCategoryTree(text,'${po.dictField?default("")}')
},
<#else>
customRender: (text, record) => (text ? record['${po.dictText}'] : '')
</#if>
<#else>
dataIndex: '${po.fieldName}'
</#if>
},
</#if>
</#list>
];
//查询数据
export const searchFormSchema: FormSchema[] = [
<#-- 开始循环 -->
<#list columns as po>
<#if po.fieldDbName=='bpm_status'>
<#assign bpm_flag=true>
</#if>
<#if po.isQuery=='Y'>
<#assign query_flag=true>
<#assign query_field_dictCode="">
<#if po.dictTable?default("")?trim?length gt 1>
<#assign query_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign query_field_dictCode="${po.dictField}">
</#if>
<#if po.queryMode=='single'>
{
label: "${po.filedComment}",
field: "${po.fieldName}",
<#if po.classType=='sel_search'>
component: 'JSearchSelect',
componentProps:{
dict:"${po.dictTable},${po.dictText},${po.dictField}"
},
<#elseif po.classType=='sel_user'>
component: 'JSelectUserByDept',
<#elseif po.classType=='switch'>
component: 'JSwitch',
componentProps:{
<#if po.dictField != 'is_open'>
options:"${po.dictField}"
</#if>
},
<#elseif po.classType=='sel_depart'>
component: 'JSelectDept',
<#elseif po.classType=='list_multi'>
component: 'JMultiSelectTag',//暂无该组件
componentProps:{
dictCode:"query_field_dictCode?default("")"
},
<#elseif po.classType=='cat_tree'>
component: 'JCategorySelect',
componentProps:{
pcode:"${po.dictField?default("")}",//back和事件未添加,暂时有问题
},
<#elseif po.classType=='date'>
component: 'DatePicker',
<#elseif po.classType=='datetime'>
component: 'DatePicker',
componentProps: {
showTime:true
},
<#elseif po.classType=='pca'>
component: 'JAreaLinkage',
<#elseif po.classType=='popup'>
component: 'JPopup',
componentProps: ({ formActionType }) => {
const {setFieldsValue} = formActionType;
return{
setFieldsValue:setFieldsValue,
code:"${po.dictTable}",
fieldConfig:"${po.dictField}",
multi:${po.extendParams.popupMulti?c},
}
},
<#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
<#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
component: 'JDictSelectTag',
componentProps:{
<#if po.dictTable?default("")?trim?length gt 1>
dictCode:"${po.dictTable},${po.dictText},${po.dictField}"
<#elseif po.dictField?default("")?trim?length gt 1>
dictCode:"${po.dictField}"
</#if>
},
<#else>
component: 'Input',
</#if>
<#else>
{
label: "${po.filedComment}",
field: "${po.fieldName}",
<#if po.classType=='date'>
component: 'RangePicker',
<#elseif po.classType=='datetime'>
component: 'RangePicker',
componentProps: {
showTime:true
},
<#else>
component: 'Input', //TODO 范围查询
</#if>
colProps: {span: 6},
},
</#if>
</#if>
</#list>
<#-- 结束循环 -->
];
//表单数据
export const formSchema: FormSchema[] = [
<#assign form_cat_tree = false>
<#assign form_cat_back = "">
<#assign bpm_flag=false>
<#list columns as po><#rt/>
<#if po.fieldDbName=='bpm_status'>
<#assign bpm_flag=true>
</#if>
<#if po.isShow =='Y'>
<#assign form_field_dictCode="">
<#if po.dictTable?default("")?trim?length gt 1 && po.dictText?default("")?trim?length gt 1 && po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictField}">
</#if>
{
label: '${po.filedComment}',
field: '${po.fieldName}',
<#if po.classType =='date'>
component: 'DatePicker',
<#elseif po.fieldType =='datetime'>
component: 'DatePicker',
componentProps: {
showTime:true
},
<#elseif po.fieldType =='time'>
component: 'TimePicker',
<#elseif po.classType =='popup'>
component: 'JPopup',
componentProps: ({ formActionType }) => {
const {setFieldsValue} = formActionType;
return{
setFieldsValue:setFieldsValue,
code:"${po.dictTable}",
fieldConfig:${po.dictField},
multi:${po.extendParams.popupMulti?c},
}
}
<#elseif po.classType =='sel_depart'>
component: 'JSelectDept',
<#elseif po.classType =='switch'>
component: 'JSwitch',
componentProps:{
<#if po.dictField != 'is_open'>
options:${po.dictField}
</#if>
}
<#elseif po.classType =='pca'>
component: 'JAreaLinkage',
<#elseif po.classType =='markdown'>
component: 'JMarkdownEditor',//注意string转换问题
<#elseif po.classType =='password'>
component: 'InputPassword',
<#elseif po.classType =='sel_user'>
component: 'JSelectUserByDept',
componentProps:{
labelKey:'realname',
}
<#elseif po.classType =='textarea'>
component: 'InputTextArea',//TODO 注意string转换问题
<#elseif po.classType=='list' || po.classType=='radio'>
component: 'JDictSelectTag',
componentProps:{
dictCode:"${form_field_dictCode}"
}
<#elseif po.classType=='list_multi' || po.classType=='checkbox'>
component: 'JMultiSelectTag',//TODO 暂无该组件
componentProps:{
dictCode:"${form_field_dictCode}"
}
<#elseif po.classType=='sel_search'>
component: 'JSearchSelect',
componentProps:{
dict:"${form_field_dictCode}"
}
<#elseif po.classType=='cat_tree'>
<#assign form_cat_tree = true>
component: 'JCategorySelect',
componentProps:{
pcode:"${po.dictField?default("")}", //TODO back和事件未添加,暂时有问题
}
<#if po.dictText?default("")?trim?length gt 1>
<#assign form_cat_back = "${po.dictText}">
</#if>
<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
component: 'InputNumber',
<#elseif po.classType=='file'>
component: 'JUpload',
componentProps:{
<#if po.uploadnum??>
maxCount:${po.uploadnum}
</#if>
}
<#elseif po.classType=='image'>
component: 'JImageUpload',
componentProps:{
<#if po.uploadnum??>
fileMax:${po.uploadnum}
</#if>
}
<#elseif po.classType=='umeditor'>
component: 'JCodeEditor', //TODO String后缀暂未添加
<#elseif po.classType == 'sel_tree'>
component: 'JTreeSelect',
componentProps:{
<#if po.dictText??>
<#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??>
dict:"${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}",
<#elseif po.dictText?split(',')[1]??>
pidField:"${po.dictText?split(',')[1]}",
<#elseif po.dictText?split(',')[3]??>
hasChildField:"${po.dictText?split(',')[3]}",
</#if>
</#if>
pidValue:"${po.dictField}",
}
<#else>
component: 'Input',
</#if>
<#include "/common/utils.ftl">
<#if po.isShow == 'Y' && poHasCheck(po)>
dynamicRules: ({model,schema}) => {
<#if po.fieldName != 'id'>
<#assign fieldValidType = po.fieldValidType!''>
return [
<#-- 非空校验 -->
<#if po.nullable == 'N' || fieldValidType == '*'>
{ required: true, message: '请输入${po.filedComment}!'},
<#elseif fieldValidType!=''>
{ required: false},
</#if>
<#-- 唯一校验 -->
<#if fieldValidType == 'only'>
{...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema,true)[0]},
<#-- 6到16位数字 -->
<#elseif fieldValidType == 'n6-16'>
{ pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'},
<#-- 6到16位任意字符 -->
<#elseif fieldValidType == '*6-16'>
{ pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'},
<#-- 6到18位字符串 -->
<#elseif fieldValidType == 's6-18'>
{ pattern: /^.{6,18}$/, message: '请输入6到18位任意字符!'},
<#-- 网址 -->
<#elseif fieldValidType == 'url'>
{ pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'},
<#-- 电子邮件 -->
<#elseif fieldValidType == 'e'>
{ pattern: /^([\w]+\.*)([\w]+)@[\w]+\.\w{3}(\.\w{2}|)$/, message: '请输入正确的电子邮件!'},
<#-- 手机号码 -->
<#elseif fieldValidType == 'm'>
{ pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号码!'},
<#-- 邮政编码 -->
<#elseif fieldValidType == 'p'>
{ pattern: /^[1-9]\d{5}$/, message: '请输入正确的邮政编码!'},
<#-- 字母 -->
<#elseif fieldValidType == 's'>
{ pattern: /^[A-Z|a-z]+$/, message: '请输入字母!'},
<#-- 数字 -->
<#elseif fieldValidType == 'n'>
{ pattern: /^-?\d+\.?\d*$/, message: '请输入数字!'},
<#-- 整数 -->
<#elseif fieldValidType == 'z'>
{ pattern: /^-?\d+$/, message: '请输入整数!'},
<#-- 金额 -->
<#elseif fieldValidType == 'money'>
{ pattern: /^(([1-9][0-9]*)|([0]\.\d{0,2}|[1-9][0-9]*\.\d{0,2}))$/, message: '请输入正确的金额!'},
<#-- 正则校验 -->
<#elseif fieldValidType != '' && fieldValidType != '*'>
{ pattern: '${fieldValidType}', message: '不符合校验规则!'},
<#-- 无校验 -->
<#else>
<#t>
</#if>
];
</#if>
},
</#if>
<#if po.readonly=='Y'>
dynamicDisabled:true
</#if>
},
</#if>
</#list>
];
<template>
<BasicModal v-bind="$attrs" @register="registerModal" :title="title" @ok="handleSubmit">
<BasicForm @register="registerForm"/>
</BasicModal>
</template>
<script lang="ts" setup>
import {ref, computed, unref} from 'vue';
import {BasicModal, useModalInner} from '/@/components/Modal';
import {BasicForm, useForm} from '/@/components/Form/index';
import {formSchema} from '../${entityName?uncap_first}.data';
import {saveOrUpdate} from '../${entityName?uncap_first}.api';
// Emits声明
const emit = defineEmits(['register','success']);
const isUpdate = ref(true);
//表单配置
const [registerForm, {setProps,resetFields, setFieldsValue, validate}] = useForm({
labelWidth: 150,
schemas: formSchema,
showActionButtonGroup: false,
});
//表单赋值
const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => {
//重置表单
await resetFields();
setModalProps({confirmLoading: false,showFooter:!!data?.showFooter});
isUpdate.value = !!data?.isUpdate;
if (unref(isUpdate)) {
//表单赋值
await setFieldsValue({
...data.record,
});
}
// 隐藏底部时禁用整个表单
setProps({ disabled: !data?.showFooter })
});
//设置标题
const title = computed(() => (!unref(isUpdate) ? '新增' : '编辑'));
//表单提交事件
async function handleSubmit(v) {
try {
let values = await validate();
setModalProps({confirmLoading: true});
//提交表单
await saveOrUpdate(values, isUpdate.value);
//关闭弹窗
closeModal();
//刷新列表
emit('success');
} finally {
setModalProps({confirmLoading: false});
}
}
</script>
<style lang="less" scoped>
</style>
\ No newline at end of file
......@@ -266,6 +266,34 @@
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#elseif col.classType =='sel_depart'>
type: FormTypes.sel_depart,
<#if col.extendParams.multiSelect?default(true) == false>
multi: false,
</#if>
<#if col.extendParams.store?default("")?trim?length gt 1>
store: "${col.extendParams.store}",
</#if>
<#if col.extendParams.text?default("")?trim?length gt 1>
text: "${col.extendParams.text}",
</#if>
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#elseif col.classType =='sel_user'>
type: FormTypes.sel_user,
<#if col.extendParams.multiSelect?default(true) == false>
multi: false,
</#if>
<#if col.extendParams.store?default("")?trim?length gt 1>
store: "${col.extendParams.store}",
</#if>
<#if col.extendParams.text?default("")?trim?length gt 1>
text: "${col.extendParams.text}",
</#if>
<#if col.readonly=='Y'>
disabled: true,
</#if>
<#elseif col.classType =='image'>
type: FormTypes.image,
token:true,
......
import {defHttp} from "/@/utils/http/axios";
import {Modal} from 'ant-design-vue';
enum Api {
list = '/${entityPackage}/${entityName?uncap_first}/rootList',
save='/${entityPackage}/${entityName?uncap_first}/add',
edit='/${entityPackage}/${entityName?uncap_first}/edit',
delete${entityName} = '/sys/${entityName?uncap_first}/delete',
deleteBatch = '/${entityPackage}/${entityName?uncap_first}/deleteBatch',
importExcel = '/${entityPackage}/${entityName?uncap_first}/importExcel',
exportXls = '/${entityPackage}/${entityName?uncap_first}/exportXls',
loadTreeData = '/${entityPackage}/${entityName?uncap_first}/loadTreeRoot',
getChildList = '/${entityPackage}/${entityName?uncap_first}/childList',
getChildListBatch = '/${entityPackage}/${entityName?uncap_first}/getChildListBatch',
}
/**
* 导出api
* @param params
*/
export const getExportUrl = Api.exportXls;
/**
* 导入api
* @param params
*/
export const getImportUrl = Api.importExcel;
/**
* 列表接口
* @param params
*/
export const list = (params) =>
defHttp.get({url: Api.list, params});
/**
* 删除
*/
export const delete${entityName} = (params,handleSuccess) => {
return defHttp.delete({url: Api.delete${entityName}, params}, {joinParamsToUrl: true}).then(() => {
handleSuccess();
});
}
/**
* 批量删除
* @param params
*/
export const batchDelete${entityName} = (params, handleSuccess) => {
Modal.confirm({
title: '确认删除',
content: '是否删除选中数据',
okText: '确认',
cancelText: '取消',
onOk: () => {
return defHttp.delete({url: Api.deleteBatch, data: params}, {joinParamsToUrl: true}).then(() => {
handleSuccess();
});
}
});
}
/**
* 保存或者更新
* @param params
*/
export const saveOrUpdateDict = (params, isUpdate) => {
let url = isUpdate ? Api.edit : Api.save;
return defHttp.post({url: url, params});
}
/**
* 查询全部树形节点数据
* @param params
*/
export const loadTreeData = (params) =>
defHttp.get({url: Api.loadTreeData,params});
/**
* 查询子节点数据
* @param params
*/
export const getChildList = (params) =>
defHttp.get({url: Api.getChildList, params});
/**
* 批量查询子节点数据
* @param params
*/
export const getChildListBatch = (params) =>
defHttp.get({url: Api.getChildListBatch, params},{isTransformResponse:false});
import {BasicColumn} from '/@/components/Table';
import {FormSchema} from '/@/components/Table';
import { rules} from '/@/utils/helper/validator';
import { render } from '/@/utils/common/renderUtils';
//列表数据
export const columns: BasicColumn[] = [
<#list columns as po>
<#if po.isShowList =='Y' && po.fieldName !='id'>
{
title: '${po.filedComment}',
align:"center",
<#if po.sort=='Y'>
sorter: true,
</#if>
<#if po.classType=='date'>
dataIndex: '${po.fieldName}',
customRender:({text}) =>{
return !text?"":(text.length>10?text.substr(0,10):text)
},
<#elseif po.fieldDbType=='Blob'>
dataIndex: '${po.fieldName}String'
<#elseif po.classType=='umeditor'>
dataIndex: '${po.fieldName}',
slots: { customRender: 'htmlSlot' },
<#elseif po.classType=='pca'>
dataIndex: '${po.fieldName}',
slots: { customRender: 'pcaSlot' },//TODO 未翻译
<#elseif po.classType=='file'>
dataIndex: '${po.fieldName}',
slots: { customRender: 'fileSlot' },
<#elseif po.classType=='image'>
dataIndex: '${po.fieldName}',
customRender:render.renderAvatar,
<#elseif po.classType=='switch'>
dataIndex: '${po.fieldName}',
<#assign switch_extend_arr=['Y','N']>
<#if po.dictField?default("")?contains("[")>
<#assign switch_extend_arr=po.dictField?eval>
</#if>
<#list switch_extend_arr as a>
<#if a_index == 0>
<#assign switch_extend_arr1=a>
<#else>
<#assign switch_extend_arr2=a>
</#if>
</#list>
customRender:({text}) => {
return render.renderSwitch(text, [{text:'是',value:'${switch_extend_arr1}'},{text:'否',value:'${switch_extend_arr2}'}])
},
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user'>
dataIndex: '${po.fieldName}_dictText'
<#elseif po.classType=='cat_tree'>
dataIndex: '${po.fieldName}',
<#if po.dictText?default("")?trim?length == 0>
customRender:({text}) => {
return render.renderCategoryTree(text,'${po.dictField?default("")}')
},
<#else>
customRender: (text, record) => (text ? record['${po.dictText}'] : '')
</#if>
<#else>
dataIndex: '${po.fieldName}'
</#if>
},
</#if>
</#list>
];
//查询数据
export const searchFormSchema: FormSchema[] = [
<#-- 开始循环 -->
<#list columns as po>
<#if po.fieldDbName=='bpm_status'>
<#assign bpm_flag=true>
</#if>
<#if po.isQuery=='Y'>
<#assign query_flag=true>
<#assign query_field_dictCode="">
<#if po.dictTable?default("")?trim?length gt 1>
<#assign query_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign query_field_dictCode="${po.dictField}">
</#if>
<#if po.queryMode=='single'>
{
label: "${po.filedComment}",
field: "${po.fieldName}",
<#if po.classType=='sel_search'>
component: 'JSearchSelect',
componentProps:{
dict:"${po.dictTable},${po.dictText},${po.dictField}"
},
<#elseif po.classType=='sel_user'>
component: 'JSelectUserByDept',
<#elseif po.classType=='switch'>
component: 'JSwitch',
componentProps:{
<#if po.dictField != 'is_open'>
options:"${po.dictField}"
</#if>
},
<#elseif po.classType=='sel_depart'>
component: 'JSelectDept',
<#elseif po.classType=='list_multi'>
component: 'JMultiSelectTag',//暂无该组件
componentProps:{
dictCode:"query_field_dictCode?default("")"
},
<#elseif po.classType=='cat_tree'>
component: 'JCategorySelect',
componentProps:{
pcode:"${po.dictField?default("")}",//back和事件未添加,暂时有问题
},
<#elseif po.classType=='date'>
component: 'DatePicker',
<#elseif po.classType=='datetime'>
component: 'DatePicker',
componentProps: {
showTime:true
},
<#elseif po.classType=='pca'>
component: 'JAreaLinkage',
<#elseif po.classType=='popup'>
component: 'JPopup',
componentProps: ({ formActionType }) => {
const {setFieldsValue} = formActionType;
return{
setFieldsValue:setFieldsValue,
code:"${po.dictTable}",
fieldConfig:"${po.dictField}",
multi:${po.extendParams.popupMulti?c},
}
},
<#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
<#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
component: 'JDictSelectTag',
componentProps:{
<#if po.dictTable?default("")?trim?length gt 1>
dictCode:"${po.dictTable},${po.dictText},${po.dictField}"
<#elseif po.dictField?default("")?trim?length gt 1>
dictCode:"${po.dictField}"
</#if>
},
<#else>
component: 'Input',
</#if>
<#else>
{
label: "${po.filedComment}",
field: "${po.fieldName}",
<#if po.classType=='date'>
component: 'RangePicker',
<#elseif po.classType=='datetime'>
component: 'RangePicker',
componentProps: {
showTime:true
},
<#else>
component: 'Input', //TODO 范围查询
</#if>
colProps: {span: 6},
},
</#if>
</#if>
</#list>
<#-- 结束循环 -->
];
//表单数据
export const formSchema: FormSchema[] = [
<#assign form_cat_tree = false>
<#assign form_cat_back = "">
<#assign bpm_flag=false>
<#list columns as po><#rt/>
<#if po.fieldDbName=='bpm_status'>
<#assign bpm_flag=true>
</#if>
<#if po.isShow =='Y'>
<#assign form_field_dictCode="">
<#if po.dictTable?default("")?trim?length gt 1 && po.dictText?default("")?trim?length gt 1 && po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictField}">
</#if>
{
label: '${po.filedComment}',
field: '${po.fieldName}',
<#if po.classType =='date'>
component: 'DatePicker',
<#elseif po.fieldType =='datetime'>
component: 'DatePicker',
componentProps: {
showTime:true
},
<#elseif po.fieldType =='time'>
component: 'TimePicker',
<#elseif po.classType =='popup'>
component: 'JPopup',
componentProps: ({ formActionType }) => {
const {setFieldsValue} = formActionType;
return{
setFieldsValue:setFieldsValue,
code:"${po.dictTable}",
fieldConfig:${po.dictField},
multi:${po.extendParams.popupMulti?c},
}
}
<#elseif po.classType =='sel_depart'>
component: 'JSelectDept',
<#elseif po.classType =='switch'>
component: 'JSwitch',
componentProps:{
<#if po.dictField != 'is_open'>
options:${po.dictField}
</#if>
}
<#elseif po.classType =='pca'>
component: 'JAreaLinkage',
<#elseif po.classType =='markdown'>
component: 'JMarkdownEditor',//注意string转换问题
<#elseif po.classType =='password'>
component: 'InputPassword',
<#elseif po.classType =='sel_user'>
component: 'JSelectUserByDept',
componentProps:{
labelKey:'realname',
}
<#elseif po.classType =='textarea'>
component: 'InputTextArea',//TODO 注意string转换问题
<#elseif po.classType=='list' || po.classType=='radio'>
component: 'JDictSelectTag',
componentProps:{
dictCode:"${form_field_dictCode}"
}
<#elseif po.classType=='list_multi' || po.classType=='checkbox'>
component: 'JMultiSelectTag',//TODO 暂无该组件
componentProps:{
dictCode:"${form_field_dictCode}"
}
<#elseif po.classType=='sel_search'>
component: 'JSearchSelect',
componentProps:{
dict:"${form_field_dictCode}"
}
<#elseif po.classType=='cat_tree'>
<#assign form_cat_tree = true>
component: 'JCategorySelect',
componentProps:{
pcode:"${po.dictField?default("")}", //TODO back和事件未添加,暂时有问题
}
<#if po.dictText?default("")?trim?length gt 1>
<#assign form_cat_back = "${po.dictText}">
</#if>
<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
component: 'InputNumber',
<#elseif po.classType=='file'>
component: 'JUpload',
componentProps:{
<#if po.uploadnum??>
maxCount:${po.uploadnum}
</#if>
}
<#elseif po.classType=='image'>
component: 'JImageUpload',
componentProps:{
<#if po.uploadnum??>
fileMax:${po.uploadnum}
</#if>
}
<#elseif po.classType=='umeditor'>
component: 'JCodeEditor', //TODO String后缀暂未添加
<#elseif po.classType == 'sel_tree'>
component: 'JTreeSelect',
componentProps:{
<#if po.dictText??>
<#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??>
dict:"${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}",
<#elseif po.dictText?split(',')[1]??>
pidField:"${po.dictText?split(',')[1]}",
<#elseif po.dictText?split(',')[3]??>
hasChildField:"${po.dictText?split(',')[3]}",
</#if>
</#if>
pidValue:"${po.dictField}",
}
<#else>
component: 'Input',
</#if>
<#include "/common/utils.ftl">
<#if po.isShow == 'Y' && poHasCheck(po)>
dynamicRules: ({model,schema}) => {
<#if po.fieldName != 'id'>
<#assign fieldValidType = po.fieldValidType!''>
return [
<#-- 非空校验 -->
<#if po.nullable == 'N' || fieldValidType == '*'>
{ required: true, message: '请输入${po.filedComment}!'},
<#elseif fieldValidType!=''>
{ required: false},
</#if>
<#-- 唯一校验 -->
<#if fieldValidType == 'only'>
{...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema,true)[0]},
<#-- 6到16位数字 -->
<#elseif fieldValidType == 'n6-16'>
{ pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'},
<#-- 6到16位任意字符 -->
<#elseif fieldValidType == '*6-16'>
{ pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'},
<#-- 6到18位字符串 -->
<#elseif fieldValidType == 's6-18'>
{ pattern: /^.{6,18}$/, message: '请输入6到18位任意字符!'},
<#-- 网址 -->
<#elseif fieldValidType == 'url'>
{ pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'},
<#-- 电子邮件 -->
<#elseif fieldValidType == 'e'>
{ pattern: /^([\w]+\.*)([\w]+)@[\w]+\.\w{3}(\.\w{2}|)$/, message: '请输入正确的电子邮件!'},
<#-- 手机号码 -->
<#elseif fieldValidType == 'm'>
{ pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号码!'},
<#-- 邮政编码 -->
<#elseif fieldValidType == 'p'>
{ pattern: /^[1-9]\d{5}$/, message: '请输入正确的邮政编码!'},
<#-- 字母 -->
<#elseif fieldValidType == 's'>
{ pattern: /^[A-Z|a-z]+$/, message: '请输入字母!'},
<#-- 数字 -->
<#elseif fieldValidType == 'n'>
{ pattern: /^-?\d+\.?\d*$/, message: '请输入数字!'},
<#-- 整数 -->
<#elseif fieldValidType == 'z'>
{ pattern: /^-?\d+$/, message: '请输入整数!'},
<#-- 金额 -->
<#elseif fieldValidType == 'money'>
{ pattern: /^(([1-9][0-9]*)|([0]\.\d{0,2}|[1-9][0-9]*\.\d{0,2}))$/, message: '请输入正确的金额!'},
<#-- 正则校验 -->
<#elseif fieldValidType != '' && fieldValidType != '*'>
{ pattern: '${fieldValidType}', message: '不符合校验规则!'},
<#-- 无校验 -->
<#else>
<#t>
</#if>
];
</#if>
},
</#if>
<#if po.readonly=='Y'>
dynamicDisabled:true
</#if>
},
</#if>
</#list>
];
<template>
<BasicModal v-bind="$attrs" @register="registerModal" :title="getTitle" @ok="handleSubmit">
<BasicForm @register="registerForm"/>
</BasicModal>
</template>
<script lang="ts" setup>
import {ref, computed, unref} from 'vue';
import {BasicModal, useModalInner} from '/src/components/Modal';
import {BasicForm, useForm} from '/src/components/Form';
import {formSchema} from '../${entityName?uncap_first}.data';
import {loadTreeData, saveOrUpdateDict} from '../${entityName?uncap_first}.api';
// 获取emit
const emit = defineEmits(['register', 'success']);
const isUpdate = ref(true);
const expandedRowKeys = ref([]);
const treeData = ref([]);
//表单配置
const [registerForm, {resetFields, setFieldsValue, validate, updateSchema}] = useForm({
schemas: formSchema,
showActionButtonGroup: false,
labelCol: {
xs: { span: 24 },
sm: { span: 4 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 18 },
},
});
//表单赋值
const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => {
//重置表单
await resetFields();
expandedRowKeys.value = [];
setModalProps({confirmLoading: false, minHeight: 80});
isUpdate.value = !!data?.isUpdate;
if (data?.record) {
//表单赋值
await setFieldsValue({
...data.record,
});
}
//父级节点树信息
treeData.value = await loadTreeData({'async': false,'pcode':''});
updateSchema({
field: 'pid',
componentProps: {treeData},
});
});
//设置标题
const getTitle = computed(() => (!unref(isUpdate) ? '新增字典' : '编辑字典'));
/**
* 根据pid获取展开的节点
* @param pid
* @param arr
*/
function getExpandKeysByPid(pid,arr){
if(pid && arr && arr.length>0){
for(let i=0;i<arr.length;i++){
if(arr[i].key==pid && unref(expandedRowKeys).indexOf(pid)<0){
expandedRowKeys.value.push(arr[i].key);
getExpandKeysByPid(arr[i]['parentId'],unref(treeData))
}else{
getExpandKeysByPid(pid,arr[i].children)
}
}
}
}
//表单提交事件
async function handleSubmit() {
try {
let values = await validate();
setModalProps({confirmLoading: true});
//提交表单
await saveOrUpdateDict(values, isUpdate.value);
//关闭弹窗
closeModal();
//展开的节点信息
await getExpandKeysByPid(values['pid'],unref(treeData))
//刷新列表(isUpdate:是否编辑;values:表单信息;expandedArr:展开的节点信息)
emit('success', {isUpdate: unref(isUpdate), values:{...values},expandedArr: unref(expandedRowKeys).reverse()});
} finally {
setModalProps({confirmLoading: false});
}
}
</script>
<template>
<div class="p-4">
<!--引用表格-->
<BasicTable @register="registerTable" :rowSelection="rowSelection" :expandedRowKeys="expandedRowKeys" @expand="handleExpand" @fetch-success="onFetchSuccess">
<!--插槽:table标题-->
<template #tableTitle>
<a-button type="primary" preIcon="ant-design:plus-outlined" @click="handleCreate"> 新增</a-button>
<a-upload name="file" :showUploadList="false" :customRequest="(file)=>handleImportXls(file,getImportUrl,importSuccess)">
<a-button type="primary" preIcon="ant-design:import-outlined">导入</a-button>
</a-upload>
<a-button type="primary" preIcon="ant-design:export-outlined" @click="handleExportXls('${tableVo.ftlDescription}管理',getExportUrl)"> 导出</a-button>
<a-dropdown v-if="checkedKeys.length > 0">
<template #overlay>
<a-menu>
<a-menu-item key="1" @click="batchHandleDelete">
<Icon icon="ant-design:delete-outlined"></Icon>
删除
</a-menu-item>
</a-menu>
</template>
<a-button>批量操作
<Icon icon="ant-design:down-outlined"></Icon>
</a-button>
</a-dropdown>
</template>
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)"/>
</template>
</BasicTable>
<!--字典弹窗-->
<${entityName}Modal @register="registerModal" @success="handleSuccess"/>
</div>
</template>
<script lang="ts" setup>
//ts语法
import {ref, computed, unref, toRaw, nextTick} from 'vue';
import {BasicTable, useTable, TableAction} from '/src/components/Table';
import {useDrawer} from '/src/components/Drawer';
import ${entityName}Modal from './components/${entityName}Modal.vue';
import {useModal} from '/src/components/Modal';
import {useMethods} from '/src/hooks/system/useMethods';
import {columns} from './${entityName}.data';
import {list, delete${entityName}, batchDelete${entityName}, getExportUrl,getImportUrl, getChildList,getChildListBatch} from './${entityName}.api';
const checkedKeys = ref<Array<string | number>>([]);
const expandedRowKeys = ref([]);
const {handleExportXls,handleImportXls} = useMethods();
//字典model
const [registerModal, {openModal}] = useModal();
//注册table数据
const [registerTable, {reload, collapseAll, updateTableDataRecord, findTableDataRecord,getDataSource}] = useTable({
api: list,
rowKey: 'id',
columns,
striped: true,
useSearchForm: false,
showTableSetting: true,
clickToRowSelect: false,
bordered: true,
showIndexColumn: false,
tableSetting: {fullScreen: true},
canResize: false,
actionColumn: {
width: 80,
title: '操作',
dataIndex: 'action',
slots: {customRender: 'action'},
fixed: undefined,
},
})
/**
* 选择列配置
*/
const rowSelection = {
type: 'checkbox',
columnWidth: 10,
selectedRowKeys: checkedKeys,
onChange: onSelectChange
}
/**
* 选择事件
*/
function onSelectChange(selectedRowKeys: (string | number)[]) {
checkedKeys.value = selectedRowKeys;
}
/**
* 新增事件
*/
function handleCreate() {
openModal(true, {
isUpdate: false,
});
}
/**
* 编辑事件
*/
async function handleEdit(record) {
openModal(true, {
record,
isUpdate: true,
});
}
/**
* 详情
*/
async function handleDetail(record) {
openModal(true, {
record,
isUpdate: true,
hideFooter: true,
});
}
/**
* 删除事件
*/
async function handleDelete(record) {
await delete${entityName}({id: record.id}, importSuccess);
}
/**
* 批量删除事件
*/
async function batchHandleDelete() {
const ids = checkedKeys.value.filter(item => !item.includes('loading'))
await batchDelete${entityName}({ids: ids}, importSuccess);
}
/**
* 导入
*/
function importSuccess() {
reload() && (expandedRowKeys.value = []);
}
/**
* 添加下级
*/
function handleAddSub(record) {
openModal(true, {
record,
isUpdate: false,
});
}
/**
* 成功回调
*/
async function handleSuccess({isUpdate, values, expandedArr}) {
if (isUpdate) {
//编辑回调
updateTableDataRecord(values.id, values);
} else {
if(!values['pid']){
//新增根节点
reload();
}else{
//新增子集
expandedRowKeys.value = [];
for (let key of unref(expandedArr)) {
await expandTreeNode(key)
}
}
}
}
/**
* 接口请求成功后回调
*/
function onFetchSuccess(result) {
getDataByResult(result.items)&&loadDataByExpandedRows();
}
/**
* 根据已展开的行查询数据(用于保存后刷新时异步加载子级的数据)
*/
async function loadDataByExpandedRows() {
if (unref(expandedRowKeys).length > 0) {
const res = await getChildListBatch({ parentIds: unref(expandedRowKeys).join(',')});
if (res.success && res.result.records.length>0) {
//已展开的数据批量子节点
let records = res.result.records
const listMap = new Map();
for (let item of records) {
let pid = item['pid'];
if (unref(expandedRowKeys).includes(pid)) {
let mapList = listMap.get(pid);
if (mapList == null) {
mapList = [];
}
mapList.push(item);
listMap.set(pid, mapList);
}
}
let childrenMap = listMap;
let fn = (list) => {
if(list) {
list.forEach(data => {
if (unref(expandedRowKeys).includes(data.id)) {
data.children = getDataByResult(childrenMap.get(data.id))
fn(data.children)
}
})
}
};
fn(getDataSource())
}
}
}
/**
* 处理数据集
*/
function getDataByResult(result){
if(result && result.length>0){
return result.map(item=>{
//判断是否标记了带有子节点
if(item["hasChild"]=='1'){
let loadChild = { id: item.id+'_loadChild', name: 'loading...', isLoading: true }
item.children = [loadChild]
}
return item
})
}
}
/**
*树节点展开合并
* */
async function handleExpand(expanded, record) {
// 判断是否是展开状态,展开状态(expanded)并且存在子集(children)并且未加载过(isLoading)的就去查询子节点数据
if (expanded) {
expandedRowKeys.value.push(record.id)
if (record.children.length > 0 && !!record.children[0].isLoading) {
let result = await getChildList({pid: record.id});
result=result.records?result.records:result;
if (result && result.length > 0) {
record.children = getDataByResult(result);
} else {
record.children = null
record.hasChild = '0'
}
}
} else {
let keyIndex = expandedRowKeys.value.indexOf(record.id)
if (keyIndex >= 0) {
expandedRowKeys.value.splice(keyIndex, 1);
}
}
}
/**
*操作表格后处理树节点展开合并
* */
async function expandTreeNode(key) {
let record = findTableDataRecord(key)
expandedRowKeys.value.push(key);
let result = await getChildList({pid: key});
if (result && result.length > 0) {
record.children = getDataByResult(result);
} else {
record.children = null
record.hasChild = '0'
}
updateTableDataRecord(key, record);
}
/**
* 操作栏
*/
function getTableAction(record) {
return [
{
label: '编辑',
onClick: handleEdit.bind(null, record),
},
{
label: '删除',
popConfirm: {
title: '确定删除吗?',
confirm: handleDelete.bind(null, record),
},
},
{
label: '添加下级',
onClick: handleAddSub.bind(null, {pid: record.id}),
}
]
}
</script>
<style scoped>
</style>
......@@ -255,6 +255,34 @@
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#elseif col.classType =='sel_depart'>
type: FormTypes.sel_depart,
<#if col.extendParams.multiSelect?default(true) == false>
multi: false,
</#if>
<#if col.extendParams.store?default("")?trim?length gt 1>
store: "${col.extendParams.store}",
</#if>
<#if col.extendParams.text?default("")?trim?length gt 1>
text: "${col.extendParams.text}",
</#if>
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#elseif col.classType =='sel_user'>
type: FormTypes.sel_user,
<#if col.extendParams.multiSelect?default(true) == false>
multi: false,
</#if>
<#if col.extendParams.store?default("")?trim?length gt 1>
store: "${col.extendParams.store}",
</#if>
<#if col.extendParams.text?default("")?trim?length gt 1>
text: "${col.extendParams.text}",
</#if>
<#if col.readonly=='Y'>
disabled: true,
</#if>
<#elseif col.classType =='image'>
type: FormTypes.image,
token:true,
......
......@@ -119,7 +119,7 @@ public class ${entityName}Controller {
*/
@AutoLog(value = "${tableVo.ftlDescription}-编辑")
@ApiOperation(value="${tableVo.ftlDescription}-编辑", notes="${tableVo.ftlDescription}-编辑")
@PutMapping(value = "/edit")
@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST})
public Result<?> edit(@RequestBody ${entityName}Page ${entityName?uncap_first}Page) {
${entityName} ${entityName?uncap_first} = new ${entityName}();
BeanUtils.copyProperties(${entityName?uncap_first}Page, ${entityName?uncap_first});
......
......@@ -266,6 +266,34 @@
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#elseif col.classType =='sel_depart'>
type: JVXETypes.departSelect,
<#if col.extendParams.multiSelect?default(true) == false>
multi: false,
</#if>
<#if col.extendParams.store?default("")?trim?length gt 1>
store: "${col.extendParams.store}",
</#if>
<#if col.extendParams.text?default("")?trim?length gt 1>
text: "${col.extendParams.text}",
</#if>
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#elseif col.classType =='sel_user'>
type: JVXETypes.userSelect,
<#if col.extendParams.multiSelect?default(true) == false>
multi: false,
</#if>
<#if col.extendParams.store?default("")?trim?length gt 1>
store: "${col.extendParams.store}",
</#if>
<#if col.extendParams.text?default("")?trim?length gt 1>
text: "${col.extendParams.text}",
</#if>
<#if col.readonly=='Y'>
disabled: true,
</#if>
<#elseif col.classType =='image'>
type: JVXETypes.image,
token:true,
......
<template>
<div>
<#assign list_need_category=false>
<#assign list_need_pca=false>
<#assign bpm_flag=false>
<#-- 开始循环 -->
<#list columns as po>
<#if po.fieldDbName=='bpm_status'>
<#assign bpm_flag=true>
</#if>
<#if po.classType=='cat_tree' && po.dictText?default("")?trim?length == 0>
<#assign list_need_category=true>
</#if>
<#if po.classType=='pca'>
<#assign list_need_pca=true>
</#if>
</#list>
<#-- 结束循环 -->
<!--引用表格-->
<BasicTable @register="registerTable" :rowSelection="rowSelection">
<!--插槽:table标题-->
<template #tableTitle>
<a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
<ExcelButton :config="excelConfig"></ExcelButton>
<a-dropdown v-if="checkedKeys.length > 0">
<template #overlay>
<a-menu>
<a-menu-item key="1" @click="batchHandleDelete">
<Icon icon="ant-design:delete-outlined"></Icon>
删除
</a-menu-item>
</a-menu>
</template>
<a-button>批量操作
<Icon icon="mdi:chevron-down"></Icon>
</a-button>
</a-dropdown>
</template>
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)"/>
</template>
<!--字段回显插槽-->
<template #htmlSlot="{text}">
<div v-html="text"></div>
</template>
<template #fileSlot="{text}">
<span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
<a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)">下载</a-button>
</template>
</BasicTable>
<!-- 表单区域 -->
<${entityName}Modal @register="registerModal" @success="handleSuccess"></${entityName}Modal>
</div>
</template>
<script lang="ts" setup>
import {ref, computed, unref} from 'vue';
import {BasicTable, useTable, TableAction} from '/@/components/Table';
import ExcelButton from '/@/components/jeecg/ExcelButton.vue'
import {useModal} from '/@/components/Modal';
import ${entityName}Modal from './components/${entityName}Modal.vue'
import {columns, searchFormSchema} from './${entityName?uncap_first}.data';
import {list, deleteOne, batchDelete, getImportUrl,getExportUrl} from './${entityName?uncap_first}.api';
<#if list_need_category>
import { loadCategoryData } from '/@/api/common/api'
import { getAuthCache, setAuthCache } from '/@/utils/auth';
import { DB_DICT_DATA_KEY } from '/@/enums/cacheEnum';
</#if>
const checkedKeys = ref<Array<string | number>>([]);
//注册model
const [registerModal, {openModal}] = useModal();
//注册table数据
const [registerTable, {reload}] = useTable({
title: '${tableVo.ftlDescription}',
api: list,
rowKey: 'id',
columns,
formConfig: {
labelWidth: 120,
schemas: searchFormSchema,
autoSubmitOnEnter:true,
showAdvancedButton:true,
fieldMapToTime: [
<#list columns as po>
<#if po.isQuery=='Y'>
<#if po.queryMode!='single'>
<#if po.classType=='date'>
['${po.fieldName}', ['${po.fieldName}_begin', '${po.fieldName}_end'], 'YYYY-MM-DD'],
<#elseif po.classType=='datetime'>
['${po.fieldName}', ['${po.fieldName}_begin', '${po.fieldName}_end'], 'YYYY-MM-DD HH:mm:ss'],
</#if>
</#if>
</#if>
</#list>
],
},
striped: true,
useSearchForm: true,
showTableSetting: true,
clickToRowSelect: false,
bordered: true,
showIndexColumn: false,
tableSetting: {fullScreen: true},
actionColumn: {
width: 120,
title: '操作',
dataIndex: 'action',
slots: {customRender: 'action'},
fixed: 'right',
},
})
/**
* excel导入导出配置
*/
const excelConfig = {
export: {
name:'${tableVo.ftlDescription}',
url: getExportUrl,
},
import: {
url: getImportUrl,
success: reload,
}
}
/**
* 选择列配置
*/
const rowSelection = {
type: 'checkbox',
columnWidth: 30,
selectedRowKeys: checkedKeys,
onChange: onSelectChange
}
/**
* 选择事件
*/
function onSelectChange(selectedRowKeys: (string | number)[]) {
checkedKeys.value = selectedRowKeys;
}
/**
* 新增事件
*/
function handleAdd() {
openModal(true, {
isUpdate: false,
showFooter: true,
});
}
/**
* 编辑事件
*/
function handleEdit(record: Recordable) {
openModal(true, {
record,
isUpdate: true,
showFooter: true,
});
}
/**
* 详情
*/
function handleDetail(record: Recordable) {
openModal(true, {
record,
isUpdate: true,
showFooter: false,
});
}
/**
* 删除事件
*/
async function handleDelete(record) {
await deleteOne({id: record.id}, reload);
}
/**
* 批量删除事件
*/
async function batchHandleDelete() {
await batchDelete({ids: checkedKeys.value}, reload);
}
/**
* 成功回调
*/
function handleSuccess() {
reload();
}
/**
* 操作栏
*/
function getTableAction(record){
return [
{
label: '编辑',
onClick: handleEdit.bind(null, record),
}
]
}
/**
* 下拉操作栏
*/
function getDropDownAction(record){
return [
{
label: '详情',
onClick: handleDetail.bind(null, record),
}, {
label: '删除',
popConfirm: {
title: '是否确认删除',
confirm: handleDelete.bind(null, record),
}
}
]
}
<#if list_need_category>
/**
* 初始化字典配置
*/
function initDictConfig(){
<#list columns as po>
<#if (po.isQuery=='Y' || po.isShowList=='Y') && po.classType!='popup'>
<#if po.classType=='cat_tree' && list_need_category==true>
loadCategoryData({code:'${po.dictField?default("")}'}).then((res) => {
if (res) {
let allDictDate = getAuthCache(DB_DICT_DATA_KEY);
if(!allDictDate['${po.dictField?default("")}']){
Object.assign(allDictDate,{'${po.dictField?default("")}':res})
}
setAuthCache(DB_DICT_DATA_KEY,allDictDate)
}
})
</#if>
</#if>
</#list>
}
initDictConfig();
</#if>
</script>
<style scoped>
</style>
\ No newline at end of file
import {defHttp} from '/@/utils/http/axios';
import {Modal} from 'ant-design-vue';
enum Api {
list = '/${entityPackage}/${entityName?uncap_first}/list',
save='/${entityPackage}/${entityName?uncap_first}/add',
edit='/${entityPackage}/${entityName?uncap_first}/edit',
deleteOne = '/${entityPackage}/${entityName?uncap_first}/delete',
deleteBatch = '/${entityPackage}/${entityName?uncap_first}/deleteBatch',
importExcel = '/${entityPackage}/${entityName?uncap_first}/importExcel',
exportXls = '/${entityPackage}/${entityName?uncap_first}/exportXls',
<#list subTables as sub><#rt/>
${sub.entityName?uncap_first}List = '/${entityPackage}/${entityName?uncap_first}/query${sub.entityName}ByMainId',
</#list>
}
/**
* 导出api
* @param params
*/
export const getExportUrl = Api.exportXls;
/**
* 导入api
*/
export const getImportUrl = Api.importExcel;
<#list subTables as sub><#rt/>
/**
* 查询子表数据
* @param params
*/
export const ${sub.entityName?uncap_first}List = Api.${sub.entityName?uncap_first}List;
</#list>
/**
* 列表接口
* @param params
*/
export const list = (params) =>
defHttp.get({url: Api.list, params});
/**
* 删除单个
*/
export const deleteOne = (params,handleSuccess) => {
return defHttp.delete({url: Api.deleteOne, params}, {joinParamsToUrl: true}).then(() => {
handleSuccess();
});
}
/**
* 批量删除
* @param params
*/
export const batchDelete = (params, handleSuccess) => {
Modal.confirm({
title: '确认删除',
content: '是否删除选中数据',
okText: '确认',
cancelText: '取消',
onOk: () => {
return defHttp.delete({url: Api.deleteBatch, data: params}, {joinParamsToUrl: true}).then(() => {
handleSuccess();
});
}
});
}
/**
* 保存或者更新
* @param params
*/
export const saveOrUpdate = (params, isUpdate) => {
let url = isUpdate ? Api.edit : Api.save;
return defHttp.post({url: url, params});
}
import {BasicColumn} from '/@/components/Table';
import {FormSchema} from '/@/components/Table';
import { rules} from '/@/utils/helper/validator';
import { render } from '/@/utils/common/renderUtils';
import {JVxeTypes,JVxeColumn} from '/@/components/jeecg/JVxeTable/types'
//列表数据
export const columns: BasicColumn[] = [
<#list columns as po>
<#if po.isShowList =='Y' && po.fieldName !='id'>
{
title: '${po.filedComment}',
align:"center",
<#if po.sort=='Y'>
sorter: true,
</#if>
<#if po.classType=='date'>
dataIndex: '${po.fieldName}',
customRender:({text}) =>{
return !text?"":(text.length>10?text.substr(0,10):text)
},
<#elseif po.fieldDbType=='Blob'>
dataIndex: '${po.fieldName}String'
<#elseif po.classType=='umeditor'>
dataIndex: '${po.fieldName}',
slots: { customRender: 'htmlSlot' },
<#elseif po.classType=='pca'>
dataIndex: '${po.fieldName}',
slots: { customRender: 'pcaSlot' },//TODO 未翻译
<#elseif po.classType=='file'>
dataIndex: '${po.fieldName}',
slots: { customRender: 'fileSlot' },
<#elseif po.classType=='image'>
dataIndex: '${po.fieldName}',
customRender:render.renderAvatar,
<#elseif po.classType=='switch'>
dataIndex: '${po.fieldName}',
<#assign switch_extend_arr=['Y','N']>
<#if po.dictField?default("")?contains("[")>
<#assign switch_extend_arr=po.dictField?eval>
</#if>
<#list switch_extend_arr as a>
<#if a_index == 0>
<#assign switch_extend_arr1=a>
<#else>
<#assign switch_extend_arr2=a>
</#if>
</#list>
customRender:({text}) => {
return render.renderSwitch(text, [{text:'是',value:'${switch_extend_arr1}'},{text:'否',value:'${switch_extend_arr2}'}])
},
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user'>
dataIndex: '${po.fieldName}_dictText'
<#elseif po.classType=='cat_tree'>
dataIndex: '${po.fieldName}',
<#if po.dictText?default("")?trim?length == 0>
customRender:({text}) => {
return render.renderCategoryTree(text,'${po.dictField?default("")}')
},
<#else>
customRender: (text, record) => (text ? record['${po.dictText}'] : '')
</#if>
<#else>
dataIndex: '${po.fieldName}'
</#if>
},
</#if>
</#list>
];
//查询数据
export const searchFormSchema: FormSchema[] = [
<#-- 开始循环 -->
<#list columns as po>
<#if po.fieldDbName=='bpm_status'>
<#assign bpm_flag=true>
</#if>
<#if po.isQuery=='Y'>
<#assign query_flag=true>
<#assign query_field_dictCode="">
<#if po.dictTable?default("")?trim?length gt 1>
<#assign query_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign query_field_dictCode="${po.dictField}">
</#if>
<#if po.queryMode=='single'>
{
label: "${po.filedComment}",
field: "${po.fieldName}",
<#if po.classType=='sel_search'>
component: 'JSearchSelect',
componentProps:{
dict:"${po.dictTable},${po.dictText},${po.dictField}"
},
<#elseif po.classType=='sel_user'>
component: 'JSelectUserByDept',
<#elseif po.classType=='switch'>
component: 'JSwitch',
componentProps:{
<#if po.dictField != 'is_open'>
options:"${po.dictField}"
</#if>
},
<#elseif po.classType=='sel_depart'>
component: 'JSelectDept',
<#elseif po.classType=='list_multi'>
component: 'JMultiSelectTag',//暂无该组件
componentProps:{
dictCode:"query_field_dictCode?default("")"
},
<#elseif po.classType=='cat_tree'>
component: 'JCategorySelect',
componentProps:{
pcode:"${po.dictField?default("")}",//back和事件未添加,暂时有问题
},
<#elseif po.classType=='date'>
component: 'DatePicker',
<#elseif po.classType=='datetime'>
component: 'DatePicker',
componentProps: {
showTime:true
},
<#elseif po.classType=='pca'>
component: 'JAreaLinkage',
<#elseif po.classType=='popup'>
component: 'JPopup',
componentProps: ({ formActionType }) => {
const {setFieldsValue} = formActionType;
return{
setFieldsValue:setFieldsValue,
code:"${po.dictTable}",
fieldConfig:"${po.dictField}",
multi:${po.extendParams.popupMulti?c},
}
},
<#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
<#-- ---------------------------下拉或是单选 判断数据字典是表字典还是普通字典------------------------------- -->
component: 'JDictSelectTag',
componentProps:{
<#if po.dictTable?default("")?trim?length gt 1>
dictCode:"${po.dictTable},${po.dictText},${po.dictField}"
<#elseif po.dictField?default("")?trim?length gt 1>
dictCode:"${po.dictField}"
</#if>
},
<#else>
component: 'Input',
</#if>
<#else>
{
label: "${po.filedComment}",
field: "${po.fieldName}",
<#if po.classType=='date'>
component: 'RangePicker',
<#elseif po.classType=='datetime'>
component: 'RangePicker',
componentProps: {
showTime:true
},
<#else>
component: 'Input', //TODO 范围查询
</#if>
colProps: {span: 6},
},
</#if>
</#if>
</#list>
<#-- 结束循环 -->
];
//表单数据
export const formSchema: FormSchema[] = [
<#assign form_cat_tree = false>
<#assign form_cat_back = "">
<#assign bpm_flag=false>
<#list columns as po><#rt/>
<#if po.fieldDbName=='bpm_status'>
<#assign bpm_flag=true>
</#if>
<#if po.isShow =='Y'>
<#assign form_field_dictCode="">
<#if po.dictTable?default("")?trim?length gt 1 && po.dictText?default("")?trim?length gt 1 && po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictField}">
</#if>
{
label: '${po.filedComment}',
field: '${po.fieldName}',
<#if po.classType =='date'>
component: 'DatePicker',
<#elseif po.fieldType =='datetime'>
component: 'DatePicker',
componentProps: {
showTime:true
},
<#elseif po.fieldType =='time'>
component: 'TimePicker',
<#elseif po.classType =='popup'>
component: 'JPopup',
componentProps: ({ formActionType }) => {
const {setFieldsValue} = formActionType;
return{
setFieldsValue:setFieldsValue,
code:"${po.dictTable}",
fieldConfig:${po.dictField},
multi:${po.extendParams.popupMulti?c},
}
}
<#elseif po.classType =='sel_depart'>
component: 'JSelectDept',
<#elseif po.classType =='switch'>
component: 'JSwitch',
componentProps:{
<#if po.dictField != 'is_open'>
options:${po.dictField}
</#if>
}
<#elseif po.classType =='pca'>
component: 'JAreaLinkage',
<#elseif po.classType =='markdown'>
component: 'JMarkdownEditor',//注意string转换问题
<#elseif po.classType =='password'>
component: 'InputPassword',
<#elseif po.classType =='sel_user'>
component: 'JSelectUserByDept',
componentProps:{
labelKey:'realname',
}
<#elseif po.classType =='textarea'>
component: 'InputTextArea',//TODO 注意string转换问题
<#elseif po.classType=='list' || po.classType=='radio'>
component: 'JDictSelectTag',
componentProps:{
dictCode:"${form_field_dictCode}"
}
<#elseif po.classType=='list_multi' || po.classType=='checkbox'>
component: 'JMultiSelectTag',//TODO 暂无该组件
componentProps:{
dictCode:"${form_field_dictCode}"
}
<#elseif po.classType=='sel_search'>
component: 'JSearchSelect',
componentProps:{
dict:"${form_field_dictCode}"
}
<#elseif po.classType=='cat_tree'>
<#assign form_cat_tree = true>
component: 'JCategorySelect',
componentProps:{
pcode:"${po.dictField?default("")}", //TODO back和事件未添加,暂时有问题
}
<#if po.dictText?default("")?trim?length gt 1>
<#assign form_cat_back = "${po.dictText}">
</#if>
<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
component: 'InputNumber',
<#elseif po.classType=='file'>
component: 'JUpload',
componentProps:{
<#if po.uploadnum??>
maxCount:${po.uploadnum}
</#if>
}
<#elseif po.classType=='image'>
component: 'JImageUpload',
componentProps:{
<#if po.uploadnum??>
fileMax:${po.uploadnum}
</#if>
}
<#elseif po.classType=='umeditor'>
component: 'JCodeEditor', //TODO String后缀暂未添加
<#elseif po.classType == 'sel_tree'>
component: 'JTreeSelect',
componentProps:{
<#if po.dictText??>
<#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??>
dict:"${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}",
<#elseif po.dictText?split(',')[1]??>
pidField:"${po.dictText?split(',')[1]}",
<#elseif po.dictText?split(',')[3]??>
hasChildField:"${po.dictText?split(',')[3]}",
</#if>
</#if>
pidValue:"${po.dictField}",
}
<#else>
component: 'Input',
</#if>
<#include "/common/utils.ftl">
<#if po.isShow == 'Y' && poHasCheck(po)>
dynamicRules: ({model,schema}) => {
<#if po.fieldName != 'id'>
<#assign fieldValidType = po.fieldValidType!''>
return [
<#-- 非空校验 -->
<#if po.nullable == 'N' || fieldValidType == '*'>
{ required: true, message: '请输入${po.filedComment}!'},
<#elseif fieldValidType!=''>
{ required: false},
</#if>
<#-- 唯一校验 -->
<#if fieldValidType == 'only'>
{...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema,true)[0]},
<#-- 6到16位数字 -->
<#elseif fieldValidType == 'n6-16'>
{ pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'},
<#-- 6到16位任意字符 -->
<#elseif fieldValidType == '*6-16'>
{ pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'},
<#-- 6到18位字符串 -->
<#elseif fieldValidType == 's6-18'>
{ pattern: /^.{6,18}$/, message: '请输入6到18位任意字符!'},
<#-- 网址 -->
<#elseif fieldValidType == 'url'>
{ pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'},
<#-- 电子邮件 -->
<#elseif fieldValidType == 'e'>
{ pattern: /^([\w]+\.*)([\w]+)@[\w]+\.\w{3}(\.\w{2}|)$/, message: '请输入正确的电子邮件!'},
<#-- 手机号码 -->
<#elseif fieldValidType == 'm'>
{ pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号码!'},
<#-- 邮政编码 -->
<#elseif fieldValidType == 'p'>
{ pattern: /^[1-9]\d{5}$/, message: '请输入正确的邮政编码!'},
<#-- 字母 -->
<#elseif fieldValidType == 's'>
{ pattern: /^[A-Z|a-z]+$/, message: '请输入字母!'},
<#-- 数字 -->
<#elseif fieldValidType == 'n'>
{ pattern: /^-?\d+\.?\d*$/, message: '请输入数字!'},
<#-- 整数 -->
<#elseif fieldValidType == 'z'>
{ pattern: /^-?\d+$/, message: '请输入整数!'},
<#-- 金额 -->
<#elseif fieldValidType == 'money'>
{ pattern: /^(([1-9][0-9]*)|([0]\.\d{0,2}|[1-9][0-9]*\.\d{0,2}))$/, message: '请输入正确的金额!'},
<#-- 正则校验 -->
<#elseif fieldValidType != '' && fieldValidType != '*'>
{ pattern: '${fieldValidType}', message: '不符合校验规则!'},
<#-- 无校验 -->
<#else>
<#t>
</#if>
];
</#if>
},
</#if>
<#if po.readonly=='Y'>
dynamicDisabled:true
</#if>
},
</#if>
</#list>
];
//子表单数据
<#list subTables as sub>
<#if sub.foreignRelationType =='1'>
export const ${sub.entityName?uncap_first}FormSchema: FormSchema[] = [
<#assign form_cat_tree = false>
<#assign form_cat_back = "">
<#assign bpm_flag=false>
<#list sub.colums as po><#rt/>
<#if po.fieldDbName=='bpm_status'>
<#assign bpm_flag=true>
</#if>
<#if po.isShow =='Y'>
<#assign form_field_dictCode="">
<#if po.dictTable?default("")?trim?length gt 1 && po.dictText?default("")?trim?length gt 1 && po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
<#elseif po.dictField?default("")?trim?length gt 1>
<#assign form_field_dictCode="${po.dictField}">
</#if>
{
label: '${po.filedComment}',
field: '${po.fieldName}',
<#if po.classType =='date'>
component: 'DatePicker',
<#elseif po.fieldType =='datetime'>
component: 'DatePicker',
componentProps: {
showTime:true
},
<#elseif po.fieldType =='time'>
component: 'TimePicker',
<#elseif po.classType =='popup'>
component: 'JPopup',
componentProps: ({ formActionType }) => {
const {setFieldsValue} = formActionType;
return{
setFieldsValue:setFieldsValue,
code:"${po.dictTable}",
fieldConfig:${po.dictField},
multi:${po.extendParams.popupMulti?c},
}
}
<#elseif po.classType =='sel_depart'>
component: 'JSelectDept',
<#elseif po.classType =='switch'>
component: 'JSwitch',
componentProps:{
<#if po.dictField != 'is_open'>
options:${po.dictField}
</#if>
}
<#elseif po.classType =='pca'>
component: 'JAreaLinkage',
<#elseif po.classType =='markdown'>
component: 'JMarkdownEditor',//注意string转换问题
<#elseif po.classType =='password'>
component: 'InputPassword',
<#elseif po.classType =='sel_user'>
component: 'JSelectUserByDept',
componentProps:{
labelKey:'realname',
}
<#elseif po.classType =='textarea'>
component: 'InputTextArea',//TODO 注意string转换问题
<#elseif po.classType=='list' || po.classType=='radio'>
component: 'JDictSelectTag',
componentProps:{
dictCode:"${form_field_dictCode}"
}
<#elseif po.classType=='list_multi' || po.classType=='checkbox'>
component: 'JMultiSelectTag',//TODO 暂无该组件
componentProps:{
dictCode:"${form_field_dictCode}"
}
<#elseif po.classType=='sel_search'>
component: 'JSearchSelect',
componentProps:{
dict:"${form_field_dictCode}"
}
<#elseif po.classType=='cat_tree'>
<#assign form_cat_tree = true>
component: 'JCategorySelect',
componentProps:{
pcode:"${po.dictField?default("")}", //TODO back和事件未添加,暂时有问题
}
<#if po.dictText?default("")?trim?length gt 1>
<#assign form_cat_back = "${po.dictText}">
</#if>
<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
component: 'InputNumber',
<#elseif po.classType=='file'>
component: 'JUpload',
componentProps:{
<#if po.uploadnum??>
maxCount:${po.uploadnum}
</#if>
}
<#elseif po.classType=='image'>
component: 'JImageUpload',
componentProps:{
<#if po.uploadnum??>
fileMax:${po.uploadnum}
</#if>
}
<#elseif po.classType=='umeditor'>
component: 'JCodeEditor', //TODO String后缀暂未添加
<#elseif po.classType == 'sel_tree'>
component: 'JTreeSelect',
componentProps:{
<#if po.dictText??>
<#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??>
dict:"${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}",
<#elseif po.dictText?split(',')[1]??>
pidField:"${po.dictText?split(',')[1]}",
<#elseif po.dictText?split(',')[3]??>
hasChildField:"${po.dictText?split(',')[3]}",
</#if>
</#if>
pidValue:"${po.dictField}",
}
<#else>
component: 'Input',
</#if>
<#include "/common/utils.ftl">
<#if po.isShow == 'Y' && poHasCheck(po)>
dynamicRules: ({model,schema}) => {
<#if po.fieldName != 'id'>
<#assign fieldValidType = po.fieldValidType!''>
return [
<#-- 非空校验 -->
<#if po.nullable == 'N' || fieldValidType == '*'>
{ required: true, message: '请输入${po.filedComment}!'},
<#elseif fieldValidType!=''>
{ required: false},
</#if>
<#-- 唯一校验 -->
<#if fieldValidType == 'only'>
{...rules.duplicateCheckRule(<#if sub?default("")?trim?length gt 1>'${sub.tableName}'<#else>'${tableName}'</#if>, '${po.fieldDbName}',model,schema,true)[0]},
<#-- 6到16位数字 -->
<#elseif fieldValidType == 'n6-16'>
{ pattern: /^\d{6,16}$/, message: '请输入6到16位数字!'},
<#-- 6到16位任意字符 -->
<#elseif fieldValidType == '*6-16'>
{ pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'},
<#-- 6到18位字符串 -->
<#elseif fieldValidType == 's6-18'>
{ pattern: /^.{6,18}$/, message: '请输入6到18位任意字符!'},
<#-- 网址 -->
<#elseif fieldValidType == 'url'>
{ pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'},
<#-- 电子邮件 -->
<#elseif fieldValidType == 'e'>
{ pattern: /^([\w]+\.*)([\w]+)@[\w]+\.\w{3}(\.\w{2}|)$/, message: '请输入正确的电子邮件!'},
<#-- 手机号码 -->
<#elseif fieldValidType == 'm'>
{ pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号码!'},
<#-- 邮政编码 -->
<#elseif fieldValidType == 'p'>
{ pattern: /^[1-9]\d{5}$/, message: '请输入正确的邮政编码!'},
<#-- 字母 -->
<#elseif fieldValidType == 's'>
{ pattern: /^[A-Z|a-z]+$/, message: '请输入字母!'},
<#-- 数字 -->
<#elseif fieldValidType == 'n'>
{ pattern: /^-?\d+\.?\d*$/, message: '请输入数字!'},
<#-- 整数 -->
<#elseif fieldValidType == 'z'>
{ pattern: /^-?\d+$/, message: '请输入整数!'},
<#-- 金额 -->
<#elseif fieldValidType == 'money'>
{ pattern: /^(([1-9][0-9]*)|([0]\.\d{0,2}|[1-9][0-9]*\.\d{0,2}))$/, message: '请输入正确的金额!'},
<#-- 正则校验 -->
<#elseif fieldValidType != '' && fieldValidType != '*'>
{ pattern: '${fieldValidType}', message: '不符合校验规则!'},
<#-- 无校验 -->
<#else>
<#t>
</#if>
];
</#if>
},
</#if>
<#if po.readonly=='Y'>
dynamicDisabled:true
</#if>
},
</#if>
</#list>
];
</#if>
</#list>
//子表表格配置
<#list subTables as sub>
<#if sub.foreignRelationType =='0'>
export const ${sub.entityName?uncap_first}Columns: JVxeColumn[] = [
<#assign popupBackFields = "">
<#-- 循环子表的列 开始 -->
<#list sub.colums as col><#rt/>
<#if col.isShow =='Y'>
<#if col.filedComment !='外键' >
{
title: '${col.filedComment}',
key: '${autoStringSuffixForModel(col)}',
<#if col.classType =='date'>
type: JVxeTypes.date,
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#elseif col.classType =='datetime'>
type: JVxeTypes.datetime,
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#elseif col.classType =='textarea'>
type: JVxeTypes.textarea,
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#elseif "int,decimal,double,"?contains(col.classType)>
type: JVxeTypes.inputNumber,
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#elseif col.classType =='list' || col.classType =='radio'>
type: JVxeTypes.select,
options:[],
<#if col.dictTable?default("")?trim?length gt 1>
dictCode:"${col.dictTable},${col.dictText},${col.dictField}",
<#else>
dictCode:"${col.dictField}",
</#if>
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#elseif col.classType =='list_multi' || col.classType =='checkbox'>
type: JVxeTypes.selectMultiple,
options:[],
<#if col.dictTable?default("")?trim?length gt 1>
dictCode:"${col.dictTable},${col.dictText},${col.dictField}",
<#else>
dictCode:"${col.dictField}",
</#if>
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#elseif col.classType =='sel_search'>
type: JVxeTypes.selectSearch,
<#if col.dictTable?default("")?trim?length gt 1>
dictCode:"${col.dictTable},${col.dictText},${col.dictField}",
<#else>
dictCode:"${col.dictField}",
</#if>
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#elseif col.classType =='image'>
type: JVxeTypes.image,
token:true,
responseName:"message",
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#if col.uploadnum??>
number: ${col.uploadnum},
</#if>
<#elseif col.classType =='file'>
type: JVxeTypes.file,
token:true,
responseName:"message",
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#if col.uploadnum??>
number: ${col.uploadnum},
</#if>
<#elseif col.classType =='switch'>
type: JVxeTypes.checkbox,
<#if col.dictField == 'is_open'>
customValue: ['Y', 'N'],
<#else>
customValue: ${col.dictField},
</#if>
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#elseif col.classType =='popup'>
<#if popupBackFields?length gt 0>
<#assign popupBackFields = "${popupBackFields}"+","+"${col.dictText}">
<#else>
<#assign popupBackFields = "${col.dictText}">
</#if>
type: JVxeTypes.popup,
popupCode:"${col.dictTable}",
field:"${col.dictField}",
orgFields:"${col.dictField}",
destFields:"${Format.underlineToHump(col.dictText)}",
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#else>
type: JVxeTypes.input,
<#if col.readonly=='Y'>
disabled:true,
</#if>
</#if>
<#if col.classType =='list_multi' || col.classType =='checkbox'>
width:"250px",
<#else>
width:"200px",
</#if>
<#if col.classType =='file'>
placeholder: '请选择文件',
<#else>
placeholder: '请输入${'$'}{title}',
</#if>
<#if col.defaultVal??>
<#if col.fieldDbType=="BigDecimal" || col.fieldDbType=="double" || col.fieldDbType=="int">
defaultValue:${col.defaultVal},
<#else>
defaultValue:"${col.defaultVal}",
</#if>
<#else>
defaultValue:'',
</#if>
<#-- 子表的校验 -->
<#assign subFieldValidType = col.fieldValidType!''>
<#-- 非空校验 -->
<#if col.nullable == 'N' || subFieldValidType == '*'>
validateRules: [{ required: true, message: '${'$'}{title}不能为空' }],
<#-- 其他情况下,只要有值就被认为是正则校验 -->
<#elseif subFieldValidType?length gt 0>
<#assign subMessage = '格式不正确'>
<#if subFieldValidType == 'only' >
<#assign subMessage = '不能重复'>
</#if>
validateRules: [{ pattern: "${subFieldValidType}", message: "${'$'}{title}${subMessage}" }],
</#if>
},
</#if>
</#if>
</#list>
<#-- 循环子表的列 结束 -->
]
</#if>
</#list>
\ No newline at end of file
<template>
<BasicModal v-bind="$attrs" @register="registerModal" :title="title" @ok="handleSubmit">
<BasicForm @register="registerForm" ref="formRef"/>
<!-- 子表单区域 -->
<a-tabs v-model:activeKey="activeKey" @change="handleChangeTabs">
<#list subTables as sub><#rt/>
<#if sub.foreignRelationType =='1'>
<a-tab-pane tab="${sub.ftlDescription}" :key="refKeys[${sub_index}]" :forceRender="true">
<${sub.entityName}Form ref="${sub.entityName?uncap_first}Form"></${sub.entityName}Form>
</a-tab-pane>
<#else>
<a-tab-pane tab="${sub.ftlDescription}" :key="refKeys[${sub_index}]" :forceRender="true">
<JVxeTable
keep-source
resizable
:ref="refKeys[${sub_index}]"
:loading="${sub.entityName?uncap_first}Table.loading"
:columns="${sub.entityName?uncap_first}Table.columns"
:dataSource="${sub.entityName?uncap_first}Table.dataSource"
:maxHeight="300"
:rowNumber="true"
:rowSelection="true"
:toolbar="true"
/>
</a-tab-pane>
</#if>
</#list>
</a-tabs>
</BasicModal>
</template>
<script lang="ts" setup>
import {ref, computed, unref,reactive} from 'vue';
import {BasicModal, useModalInner} from '/@/components/Modal';
import {BasicForm, useForm} from '/@/components/Form/index';
import { JVxeTable } from '/@/components/jeecg/JVxeTable'
import { useJvxeMethod } from '/@/hooks/system/useJvxeMethods.ts'
<#list subTables as sub>
<#if sub.foreignRelationType =='1'>
import ${sub.entityName}Form from './${sub.entityName}Form.vue'
</#if>
</#list>
import {formSchema<#list subTables as sub><#if sub.foreignRelationType =='0'>,${sub.entityName?uncap_first}Columns</#if></#list>} from '../${entityName?uncap_first}.data';
import {saveOrUpdate<#list subTables as sub>,${sub.entityName?uncap_first}List</#list>} from '../${entityName?uncap_first}.api';
import { VALIDATE_FAILED } from '/@/utils/common/vxeUtils'
// Emits声明
const emit = defineEmits(['register','success']);
const isUpdate = ref(true);
const refKeys = ref([<#list subTables as sub>'${sub.entityName?uncap_first}', </#list>]);
<#assign hasOne2Many = false>
<#assign hasOne2One = false>
const activeKey = ref('${subTables[0].entityName?uncap_first}');
<#list subTables as sub>
<#if sub.foreignRelationType =='0'>
<#assign hasOne2Many = true>
const ${sub.entityName?uncap_first} = ref();
</#if>
<#if sub.foreignRelationType =='1'>
<#assign hasOne2One = true>
const ${sub.entityName?uncap_first}Form = ref();
</#if>
</#list>
const tableRefs = {<#list subTables as sub><#if sub.foreignRelationType =='0'>${sub.entityName?uncap_first}, <#assign hasOne2Many = true></#if></#list>};
<#list subTables as sub>
<#if sub.foreignRelationType =='0'>
const ${sub.entityName?uncap_first}Table = reactive({
loading: false,
dataSource: [],
columns:${sub.entityName?uncap_first}Columns
})
</#if>
</#list>
//表单配置
const [registerForm, {setProps,resetFields, setFieldsValue, validate}] = useForm({
labelWidth: 150,
schemas: formSchema,
showActionButtonGroup: false,
});
//表单赋值
const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => {
//重置表单
await reset();
setModalProps({confirmLoading: false,showCancelBtn:data?.showFooter,showOkBtn:data?.showFooter});
isUpdate.value = !!data?.isUpdate;
if (unref(isUpdate)) {
//表单赋值
await setFieldsValue({
...data.record,
});
<#list subTables as sub><#rt/>
<#if sub.foreignRelationType =='1'>
${sub.entityName?uncap_first}Form.value.initFormData(${sub.entityName?uncap_first}List,data?.record?.id)
</#if>
</#list>
<#list subTables as sub><#rt/>
<#if sub.foreignRelationType =='0'>
requestSubTableData(${sub.entityName?uncap_first}List, {id:data?.record?.id}, ${sub.entityName?uncap_first}Table)
</#if>
</#list>
}
// 隐藏底部时禁用整个表单
setProps({ disabled: !data?.showFooter })
});
//方法配置
const [handleChangeTabs,handleSubmit,requestSubTableData,formRef] = useJvxeMethod(requestAddOrEdit,classifyIntoFormData,tableRefs,activeKey,refKeys<#if hasOne2One==true>,validateSubForm</#if>);
//设置标题
const title = computed(() => (!unref(isUpdate) ? '新增' : '编辑'));
async function reset(){
await resetFields();
activeKey.value = ref('${subTables[0].entityName?uncap_first}');
<#list subTables as sub>
<#if sub.foreignRelationType =='0'>
${sub.entityName?uncap_first}Table.dataSource = [];
</#if>
<#if sub.foreignRelationType =='1'>
${sub.entityName?uncap_first}Form.value.resetFields();
</#if>
</#list>
}
function classifyIntoFormData(allValues) {
let main = Object.assign({}, allValues.formValue)
return {
...main, // 展开
<#assign subManyIndex = 0>
<#list subTables as sub><#rt/>
<#if sub.foreignRelationType =='0'>
${sub.entityName?uncap_first}List: allValues.tablesValue[${subManyIndex}].tableData,
<#assign subManyIndex = subManyIndex+1>
<#else>
${sub.entityName?uncap_first}List: ${sub.entityName?uncap_first}Form.value.getFormData(),
</#if>
</#list>
}
}
<#if hasOne2One==true>
//校验所有一对一子表表单
function validateSubForm(allValues){
return new Promise((resolve,reject)=>{
Promise.all([
<#list subTables as sub><#rt/>
<#if sub.foreignRelationType =='1'>
${sub.entityName?uncap_first}Form.value.validateForm(${sub_index}),
</#if>
</#list>
]).then(() => {
resolve(allValues)
}).catch(e => {
if (e.error === VALIDATE_FAILED) {
// 如果有未通过表单验证的子表,就自动跳转到它所在的tab
activeKey.value = e.index == null ? unref(activeKey) : refKeys.value[e.index]
} else {
console.error(e)
}
})
})
}
</#if>
//表单提交事件
async function requestAddOrEdit(values) {
try {
setModalProps({confirmLoading: true});
//提交表单
await saveOrUpdate(values, isUpdate.value);
//关闭弹窗
closeModal();
//刷新列表
emit('success');
} finally {
setModalProps({confirmLoading: false});
}
}
</script>
<style lang="less" scoped>
</style>
\ No newline at end of file
<#list subTables as sub>
<#if sub.foreignRelationType=='1'>
#segment#${sub.entityName}Form.vue
<template>
<BasicForm @register="registerForm"/>
</template>
<script lang="ts">
import {defineComponent} from 'vue';
import {BasicForm, useForm} from '/@/components/Form/index';
import {${sub.entityName?uncap_first}FormSchema} from '../${entityName?uncap_first}.data';
import {defHttp} from '/@/utils/http/axios';
import { VALIDATE_FAILED } from '/@/utils/common/vxeUtils'
export default defineComponent({
name:"${sub.entityName}Form",
components: {BasicForm},
emits:['register'],
setup(_,{emit}) {
const [registerForm, {resetFields, setFieldsValue,getFieldsValue,validate}] = useForm({
labelWidth: 150,
schemas: ${sub.entityName?uncap_first}FormSchema,
showActionButtonGroup: false,
});
/**
*初始化加载数据
*/
function initFormData(url,id){
if(id){
defHttp.get({url,params:{id}},{isTransformResponse:false}).then(res=>{
res.success && setFieldsValue({...res.result[0]});
})
}
}
/**
*获取表单数据
*/
function getFormData(){
return [getFieldsValue()];
}
/**
*表单校验
*/
function validateForm(index){
return new Promise((resolve, reject) => {
// 验证子表表单
validate().then(()=>{
return resolve()
}).catch(()=> {
return reject({ error: VALIDATE_FAILED ,index})
})
})
}
return {
registerForm,
resetFields,
initFormData,
getFormData,
validateForm
}
}
})
</script>
</#if>
</#list>
......@@ -245,6 +245,34 @@ export default {
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#elseif col.classType =='sel_depart'>
type: FormTypes.sel_depart,
<#if col.extendParams.multiSelect?default(true) == false>
multi: false,
</#if>
<#if col.extendParams.store?default("")?trim?length gt 1>
store: "${col.extendParams.store}",
</#if>
<#if col.extendParams.text?default("")?trim?length gt 1>
text: "${col.extendParams.text}",
</#if>
<#if col.readonly=='Y'>
disabled:true,
</#if>
<#elseif col.classType =='sel_user'>
type: FormTypes.sel_user,
<#if col.extendParams.multiSelect?default(true) == false>
multi: false,
</#if>
<#if col.extendParams.store?default("")?trim?length gt 1>
store: "${col.extendParams.store}",
</#if>
<#if col.extendParams.text?default("")?trim?length gt 1>
text: "${col.extendParams.text}",
</#if>
<#if col.readonly=='Y'>
disabled: true,
</#if>
<#elseif col.classType =='switch'>
type: FormTypes.checkbox,
<#if col.dictField == 'is_open'>
......
......@@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-boot-starter</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>2.4.6</version>
<version>3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jeecg-boot-starter-cloud</artifactId>
......
......@@ -8,10 +8,10 @@ import java.util.SortedMap;
import javax.servlet.http.HttpServletRequest;
import org.jeecg.common.config.mqtoken.UserTokenContext;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.PathMatcherUtil;
import org.jeecg.common.config.mqtoken.UserTokenContext;
import org.jeecg.config.sign.interceptor.SignAuthConfiguration;
import org.jeecg.config.sign.util.HttpUtils;
import org.jeecg.config.sign.util.SignUtil;
......
......@@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-boot-starter</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>2.4.6</version>
<version>3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jeecg-boot-starter-job</artifactId>
......
......@@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-boot-starter</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>2.4.6</version>
<version>3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jeecg-boot-starter-lock</artifactId>
......
......@@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-boot-starter</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>2.4.6</version>
<version>3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jeecg-boot-starter-rabbitmq</artifactId>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-parent</artifactId>
<version>2.4.6</version>
<version>3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jeecg-boot-starter</artifactId>
......
......@@ -10,6 +10,6 @@ WORKDIR /jeecg-cloud-gateway
EXPOSE 9999
ADD ./target/jeecg-cloud-gateway-2.4.6.jar ./
ADD ./target/jeecg-cloud-gateway-3.0.jar ./
CMD sleep 10;java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jeecg-cloud-gateway-2.4.6.jar
\ No newline at end of file
CMD sleep 10;java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jeecg-cloud-gateway-3.0.jar
\ No newline at end of file
......@@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-cloud-module</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>2.4.6</version>
<version>3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
......@@ -79,11 +79,6 @@
<!-- Swagger API文档 -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-ui</artifactId>
<version>${knife4j-spring-ui.version}</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>${knife4j-spring-boot-starter.version}</version>
</dependency>
......
......@@ -34,6 +34,6 @@ public class JeecgGatewayApplication implements CommandLineRunner {
*/
@Override
public void run(String... strings) {
dynamicRouteLoader.refresh();
dynamicRouteLoader.refresh(null);
}
}
......@@ -21,7 +21,7 @@ public class LoderRouderHandler implements JeecgRedisListerer {
@Override
public void onMessage(BaseMap message) {
dynamicRouteLoader.refresh();
dynamicRouteLoader.refresh(message);
}
}
\ No newline at end of file
......@@ -11,6 +11,8 @@ import com.alibaba.nacos.api.exception.NacosException;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.jeecg.common.base.BaseMap;
import org.jeecg.common.constant.CacheConstant;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.config.GatewayRoutersConfiguration;
......@@ -66,6 +68,9 @@ public class DynamicRouteLoader implements ApplicationEventPublisherAware {
@PostConstruct
public void init() {
init(null);
}
public void init(BaseMap baseMap) {
String dataType = GatewayRoutersConfiguration.DATA_TYPE;
log.info("初始化路由,dataType:"+ dataType);
if (RouterDataType.nacos.toString().endsWith(dataType)) {
......@@ -73,20 +78,18 @@ public class DynamicRouteLoader implements ApplicationEventPublisherAware {
}
//从数据库加载路由
if (RouterDataType.database.toString().endsWith(dataType)) {
loadRoutesByRedis();
loadRoutesByRedis(baseMap);
}
}
/**
* 刷新路由
*
* @return
*/
public Mono<Void> refresh() {
public Mono<Void> refresh(BaseMap baseMap) {
String dataType = GatewayRoutersConfiguration.DATA_TYPE;
if (!RouterDataType.yml.toString().endsWith(dataType)) {
this.init();
this.init(baseMap);
}
return Mono.empty();
}
......@@ -127,7 +130,7 @@ public class DynamicRouteLoader implements ApplicationEventPublisherAware {
*
* @return
*/
private void loadRoutesByRedis() {
private void loadRoutesByRedis(BaseMap baseMap) {
List<MyRouteDefinition> routes = Lists.newArrayList();
configService = createConfigService();
if (configService == null) {
......@@ -152,6 +155,12 @@ public class DynamicRouteLoader implements ApplicationEventPublisherAware {
dynamicRouteService.add(definition);
}
}
if(ObjectUtils.isNotEmpty(baseMap)){
String routerId=baseMap.get("routerId");
if(ObjectUtils.isNotEmpty(routerId)) {
dynamicRouteService.delete(routerId);
}
}
this.publisher.publishEvent(new RefreshRoutesEvent(this));
}
......@@ -277,8 +286,8 @@ public class DynamicRouteLoader implements ApplicationEventPublisherAware {
@Override
public void receiveConfigInfo(String configInfo) {
log.info("进行网关更新:\n\r{}", configInfo);
List<RouteDefinition> definitionList = JSON.parseArray(configInfo, RouteDefinition.class);
for (RouteDefinition definition : definitionList) {
List<MyRouteDefinition> definitionList = JSON.parseArray(configInfo, MyRouteDefinition.class);
for (MyRouteDefinition definition : definitionList) {
log.info("update route : {}", definition.toString());
dynamicRouteService.update(definition);
}
......
......@@ -52,7 +52,7 @@ public class DynamicRouteService implements ApplicationEventPublisherAware {
repository.delete(Mono.just(id)).subscribe();
this.publisher.publishEvent(new RefreshRoutesEvent(this));
}catch (Exception e){
e.printStackTrace();
//e.printStackTrace();
}
}
......@@ -65,7 +65,7 @@ public class DynamicRouteService implements ApplicationEventPublisherAware {
public synchronized String update(RouteDefinition definition) {
try {
log.info("gateway update route {}", definition);
delete(definition.getId());
//delete(definition.getId());
} catch (Exception e) {
return "update fail,not find route routeId: " + definition.getId();
}
......
......@@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-cloud-module</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>2.4.6</version>
<version>3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jeecg-cloud-monitor</artifactId>
......
......@@ -10,6 +10,6 @@ WORKDIR /jeecg-cloud-nacos
EXPOSE 8848
ADD ./target/jeecg-cloud-nacos-2.4.6.jar ./
ADD ./target/jeecg-cloud-nacos-3.0.jar ./
CMD sleep 5;java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jeecg-cloud-nacos-2.4.6.jar
\ No newline at end of file
CMD sleep 5;java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jeecg-cloud-nacos-3.0.jar
\ No newline at end of file
......@@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-cloud-module</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>2.4.6</version>
<version>3.0</version>
</parent>
<artifactId>jeecg-cloud-nacos</artifactId>
<name>jeecg-cloud-nacos</name>
......
访问地址
http://localhost:8087
账号密码:sentinel/sentinel
\ No newline at end of file
......@@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-cloud-module</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>2.4.6</version>
<version>3.0</version>
</parent>
<artifactId>jeecg-cloud-sentinel</artifactId>
<name>jeecg-cloud-sentinel</name>
......
......@@ -10,6 +10,6 @@ WORKDIR /jeecg-cloud-system
EXPOSE 7001
ADD ./target/jeecg-cloud-system-start-2.4.6.jar ./
ADD ./target/jeecg-cloud-system-start-3.0.jar ./
CMD sleep 10;java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jeecg-cloud-system-start-2.4.6.jar
\ No newline at end of file
CMD sleep 10;java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jeecg-cloud-system-start-3.0.jar
\ No newline at end of file
......@@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-cloud-module</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>2.4.6</version>
<version>3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jeecg-cloud-system-start</artifactId>
......
......@@ -10,7 +10,7 @@ WORKDIR /jeecg-cloud-xxljob
EXPOSE 9080
ADD ./target/jeecg-cloud-xxljob-2.4.6.jar ./
ADD ./target/jeecg-cloud-xxljob-3.0.jar ./
CMD java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jeecg-cloud-xxljob-2.4.6.jar
CMD java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jeecg-cloud-xxljob-3.0.jar
......@@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-cloud-module</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>2.4.6</version>
<version>3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
......
......@@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-boot-parent</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>2.4.6</version>
<version>3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
......
......@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-parent</artifactId>
<version>2.4.6</version>
<version>3.0</version>
<packaging>pom</packaging>
<parent>
......@@ -13,7 +13,7 @@
</parent>
<properties>
<jeecgboot.version>2.4.6</jeecgboot.version>
<jeecgboot.version>3.0</jeecgboot.version>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-cloud.version>Hoxton.SR8</spring-cloud.version>
......@@ -26,7 +26,7 @@
<postgresql.version>42.2.6</postgresql.version>
<ojdbc6.version>11.2.0.3</ojdbc6.version>
<sqljdbc4.version>4.0</sqljdbc4.version>
<mysql-connector-java.version>8.0.21</mysql-connector-java.version>
<mysql-connector-java.version>8.0.27</mysql-connector-java.version>
<!-- 动态数据源-->
<dynamic-datasource-spring-boot-starter.version>3.2.0</dynamic-datasource-spring-boot-starter.version>
<hutool.version>5.3.8</hutool.version>
......@@ -41,7 +41,7 @@
<shiro.version>1.7.1</shiro.version>
<java-jwt.version>3.11.0</java-jwt.version>
<shiro-redis.version>3.1.0</shiro-redis.version>
<codegenerate.version>1.3.6</codegenerate.version>
<codegenerate.version>1.3.7</codegenerate.version>
<autopoi-web.version>1.3.5</autopoi-web.version>
<minio.version>8.0.3</minio.version>
<justauth-spring-boot-starter.version>1.3.4</justauth-spring-boot-starter.version>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment