From 806bedc0352d842f2bd93ee219e53446bfe7ac42 Mon Sep 17 00:00:00 2001 From: xiachao Date: Mon, 5 Aug 2024 13:48:32 +0800 Subject: [PATCH] application --- application/Dockerfile | 11 + application/pom.xml | 148 ++++++++ .../java/com/thing/ThingBiApplication.java | 16 + .../listener/QueueCacheEventListener.java | 78 ++++ .../com/thing/mock/IpCommandLineRunner.java | 15 + .../com/thing/mock/MockDataController.java | 102 ++++++ .../com/thing/queue/DataTransferListener.java | 69 ++++ .../src/main/resources/application.yml | 271 ++++++++++++++ application/src/main/resources/logback.xml | 160 ++++++++ .../src/main/resources/static/favicon.ico | Bin 0 -> 37029 bytes tools/code-generator/pom.xml | 34 ++ .../codegenerator/config/DataSourceInfo.java | 71 ++++ .../config/query/AbstractQuery.java | 59 +++ .../config/query/MySqlQuery.java | 68 ++++ .../config/query/OracleQuery.java | 73 ++++ .../config/query/PostgreSqlQuery.java | 72 ++++ .../config/query/SqlServerQuery.java | 83 +++++ .../controller/BaseClassController.java | 65 ++++ .../controller/DataSourceController.java | 74 ++++ .../controller/FieldTypeController.java | 65 ++++ .../controller/GenParamController.java | 36 ++ .../controller/GeneratorController.java | 118 ++++++ .../controller/TemplateController.java | 83 +++++ .../codegenerator/entity/BaseClassEntity.java | 39 ++ .../entity/DataSourceEntity.java | 49 +++ .../codegenerator/entity/FieldTypeEntity.java | 38 ++ .../tools/codegenerator/entity/GenParam.java | 25 ++ .../codegenerator/entity/MenuEntity.java | 19 + .../entity/TableFieldEntity.java | 102 ++++++ .../codegenerator/entity/TableInfoEntity.java | 83 +++++ .../codegenerator/entity/TemplateEntity.java | 46 +++ .../codegenerator/mapper/BaseClassMapper.java | 15 + .../mapper/DataSourceMapper.java | 15 + .../codegenerator/mapper/FieldTypeMapper.java | 26 ++ .../mapper/GeneratorMenuMapper.java | 18 + .../mapper/TableFieldMapper.java | 22 ++ .../codegenerator/mapper/TableInfoMapper.java | 17 + .../codegenerator/mapper/TemplateMapper.java | 18 + .../service/BaseClassService.java | 20 + .../service/DataSourceService.java | 20 + .../service/FieldTypeService.java | 26 ++ .../service/GeneratorService.java | 26 ++ .../service/TableFieldService.java | 20 + .../service/TableInfoService.java | 23 ++ .../service/TemplateService.java | 24 ++ .../service/impl/BaseClassServiceImpl.java | 43 +++ .../service/impl/DataSourceServiceImpl.java | 43 +++ .../service/impl/FieldTypeServiceImpl.java | 57 +++ .../service/impl/GeneratorServiceImpl.java | 342 ++++++++++++++++++ .../service/impl/TableFieldServiceImpl.java | 43 +++ .../service/impl/TableInfoServiceImpl.java | 58 +++ .../service/impl/TemplateServiceImpl.java | 51 +++ .../tools/codegenerator/utils/DbType.java | 28 ++ .../tools/codegenerator/utils/DbUtils.java | 148 ++++++++ .../tools/codegenerator/utils/GenUtils.java | 56 +++ .../mapper/codegenerator/FieldTypeMapper.xml | 13 + .../codegenerator/GeneratorMenuMapper.xml | 18 + .../mapper/codegenerator/TableFieldMapper.xml | 20 + .../mapper/codegenerator/TableInfoMapper.xml | 14 + .../mapper/codegenerator/TemplateMapper.xml | 13 + tools/pom.xml | 23 ++ tools/system-monitor/pom.xml | 45 +++ .../com/thing/tools/monitor/config/.gitkeep | 0 63 files changed, 3477 insertions(+) create mode 100644 application/Dockerfile create mode 100644 application/pom.xml create mode 100644 application/src/main/java/com/thing/ThingBiApplication.java create mode 100644 application/src/main/java/com/thing/listener/QueueCacheEventListener.java create mode 100644 application/src/main/java/com/thing/mock/IpCommandLineRunner.java create mode 100644 application/src/main/java/com/thing/mock/MockDataController.java create mode 100644 application/src/main/java/com/thing/queue/DataTransferListener.java create mode 100644 application/src/main/resources/application.yml create mode 100644 application/src/main/resources/logback.xml create mode 100644 application/src/main/resources/static/favicon.ico create mode 100644 tools/code-generator/pom.xml create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/config/DataSourceInfo.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/config/query/AbstractQuery.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/config/query/MySqlQuery.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/config/query/OracleQuery.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/config/query/PostgreSqlQuery.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/config/query/SqlServerQuery.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/controller/BaseClassController.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/controller/DataSourceController.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/controller/FieldTypeController.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/controller/GenParamController.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/controller/GeneratorController.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/controller/TemplateController.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/entity/BaseClassEntity.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/entity/DataSourceEntity.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/entity/FieldTypeEntity.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/entity/GenParam.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/entity/MenuEntity.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/entity/TableFieldEntity.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/entity/TableInfoEntity.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/entity/TemplateEntity.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/mapper/BaseClassMapper.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/mapper/DataSourceMapper.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/mapper/FieldTypeMapper.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/mapper/GeneratorMenuMapper.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/mapper/TableFieldMapper.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/mapper/TableInfoMapper.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/mapper/TemplateMapper.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/BaseClassService.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/DataSourceService.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/FieldTypeService.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/GeneratorService.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/TableFieldService.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/TableInfoService.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/TemplateService.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/impl/BaseClassServiceImpl.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/impl/DataSourceServiceImpl.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/impl/FieldTypeServiceImpl.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/impl/GeneratorServiceImpl.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/impl/TableFieldServiceImpl.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/impl/TableInfoServiceImpl.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/impl/TemplateServiceImpl.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/utils/DbType.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/utils/DbUtils.java create mode 100644 tools/code-generator/src/main/java/com/thing/tools/codegenerator/utils/GenUtils.java create mode 100644 tools/code-generator/src/main/resources/mapper/codegenerator/FieldTypeMapper.xml create mode 100644 tools/code-generator/src/main/resources/mapper/codegenerator/GeneratorMenuMapper.xml create mode 100644 tools/code-generator/src/main/resources/mapper/codegenerator/TableFieldMapper.xml create mode 100644 tools/code-generator/src/main/resources/mapper/codegenerator/TableInfoMapper.xml create mode 100644 tools/code-generator/src/main/resources/mapper/codegenerator/TemplateMapper.xml create mode 100644 tools/pom.xml create mode 100644 tools/system-monitor/pom.xml create mode 100644 tools/system-monitor/src/main/java/com/thing/tools/monitor/config/.gitkeep diff --git a/application/Dockerfile b/application/Dockerfile new file mode 100644 index 0000000..06a3b8b --- /dev/null +++ b/application/Dockerfile @@ -0,0 +1,11 @@ +FROM java:17 + +ENV LANG C.UTF-8 +ENV LC_ALL C.UTF-8 en_US.UTF-8 + +EXPOSE 2020 + +VOLUME /tmp +ADD appliction.jar /app.jar +RUN bash -c 'touch /app.jar' +ENTRYPOINT ["java","-jar","/app.jar"] diff --git a/application/pom.xml b/application/pom.xml new file mode 100644 index 0000000..37ada59 --- /dev/null +++ b/application/pom.xml @@ -0,0 +1,148 @@ + + + 4.0.0 + + com.thing + thingbi + 5.1 + + application + ThingBI Application + + + + UTF-8 + UTF-8 + + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + + + + org.springframework.boot + spring-boot-starter-web + + + com.google.guava + guava + provided + + + org.mybatis + mybatis-spring + + + + com.thing.common + data + + + com.thing.common + orm + + + com.thing.common + queue + + + com.thing.common + script + + + com.thing.common + security + + + com.thing.common + transport + + + com.thing.common + tskv + + + com.thing.common + util + + + + + com.thing.modules + alarm + + + com.thing.modules + calculation + + + com.thing.modules + mock + + + com.thing.modules + report-analysis + + + com.thing.modules + configuration + + + com.thing.modules + dequeue + + + com.thing.modules + msg + + + com.thing.modules + quartz + + + com.thing.modules + carbon-track + + + com.thing.modules + carbon-public + + + com.thing.modules + equipment + + + com.thing.modules + thing + + + com.thing.tools + system-monitor + + + com.thing.tools + code-generator + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + diff --git a/application/src/main/java/com/thing/ThingBiApplication.java b/application/src/main/java/com/thing/ThingBiApplication.java new file mode 100644 index 0000000..5ec17f5 --- /dev/null +++ b/application/src/main/java/com/thing/ThingBiApplication.java @@ -0,0 +1,16 @@ +package com.thing; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableAsync; + + +@EnableAsync +@SpringBootApplication +public class ThingBiApplication { + + + public static void main(String[] args) { + SpringApplication.run(ThingBiApplication.class, args); + } +} diff --git a/application/src/main/java/com/thing/listener/QueueCacheEventListener.java b/application/src/main/java/com/thing/listener/QueueCacheEventListener.java new file mode 100644 index 0000000..9991f9e --- /dev/null +++ b/application/src/main/java/com/thing/listener/QueueCacheEventListener.java @@ -0,0 +1,78 @@ +package com.thing.listener; + +import cn.hutool.core.collection.CollectionUtil; +import com.thing.common.core.enumeration.QueueOriginType; +import com.thing.common.core.event.QueueCacheEvent; +import com.thing.common.data.dto.QueueMsgDTO; +import com.thing.common.data.event.QueueConsumerEvent; +import com.thing.common.data.proto.QueueProto; +import com.thing.queue.util.Topics; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * @author zhenghh. 2022-10-13 + **/ +@Slf4j +@Component +@RequiredArgsConstructor +public class QueueCacheEventListener { + +// private final DynamicCacheTsKvService tsKvService; +// private final CacheTsKvLastestService tsKvLastService; +// @Resource +// private ThreadPoolTaskExecutor threadPoolTaskExecutor; +// private DateTime dateTime = new DateTime(); + + + private final ApplicationEventPublisher eventPublisher; + + + @EventListener(QueueCacheEvent.class) + public void onCacheEvent(QueueCacheEvent event) { + List list = event.getList(); + if (CollectionUtil.isEmpty(list)) { + return; + } + // 去除来源为TB的数据,否则在ClickHouse的视图中会有重复数据 + List nonTbList = + list.stream() + .filter( + e -> + !Objects.equals( + QueueOriginType.TB.name(), e.getOrigin())) + .toList(); + List protoList = new ArrayList<>(); + + //新版本,将数据send到遥测数据全局监听器中 + nonTbList.forEach(temp->{ + QueueProto.TsKvProto tsKvProto =QueueProto.TsKvProto.newBuilder().setThingCode(temp.getThingCode()).setKey(temp.getAttrKey()).setTs(temp.getTs()).setVal(temp.getVal()).build(); + protoList.add(QueueProto.DataProto.newBuilder().setTskvProto(tsKvProto).build()); + }); + //JSON.toJSONString(protoList) + eventPublisher.publishEvent(new QueueConsumerEvent(Topics.V1_TSKV_HISTORY.getValue(), protoList)); + } + +// +// //保存历史值 +// threadPoolTaskExecutor.execute(() -> tsKvService.saveList(nonTbList)); +// +// if ((new DateTime().getMillis() - dateTime.getMillis()) > 3000) { +// //保存最新值 +// List deduplicatedList = new ArrayList<>(nonTbList.stream() +// .collect(Collectors.toMap(queueMsgDTO -> queueMsgDTO.getThingCode() + "_" + queueMsgDTO.getAttrKey() + "_" + queueMsgDTO.getTs(), +// Function.identity(), +// (a, b) -> a, LinkedHashMap::new)) +// .values()); +// tsKvLastService.saveList(deduplicatedList); +// dateTime = new DateTime(); +// } + +} diff --git a/application/src/main/java/com/thing/mock/IpCommandLineRunner.java b/application/src/main/java/com/thing/mock/IpCommandLineRunner.java new file mode 100644 index 0000000..f10ab2f --- /dev/null +++ b/application/src/main/java/com/thing/mock/IpCommandLineRunner.java @@ -0,0 +1,15 @@ +package com.thing.mock; + +import com.thing.common.core.annotation.LogOperation; +import org.springframework.boot.CommandLineRunner; +import org.springframework.stereotype.Component; + +@Component +public class IpCommandLineRunner implements CommandLineRunner { + + @LogOperation(value = "项目启动", type = "1") + @Override + public void run(String... args) throws Exception { + + } +} diff --git a/application/src/main/java/com/thing/mock/MockDataController.java b/application/src/main/java/com/thing/mock/MockDataController.java new file mode 100644 index 0000000..e23cc19 --- /dev/null +++ b/application/src/main/java/com/thing/mock/MockDataController.java @@ -0,0 +1,102 @@ +package com.thing.mock; + +import com.github.jsonzou.jmockdata.JMockData; +import com.thing.common.core.web.response.Result; +import com.thing.common.data.event.QueueConsumerEvent; +import com.thing.common.data.proto.QueueProto.DataProto; +import com.thing.common.data.proto.QueueProto.TsKvProto; +import com.thing.common.data.tskv.TsKvDTO; +import com.thing.queue.util.Topics; + +import lombok.Data; +import lombok.RequiredArgsConstructor; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.web.bind.annotation.*; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author siyang + * @date 2024-03-08 + * @description mock数据服务(仅用作内部测试)不对外开放 + */ +@RestController +@RequestMapping("v2/mock/data") +@RequiredArgsConstructor +public class MockDataController { + + @Value("${calculate.am_total.keys}") + private String keys; + + private final ApplicationEventPublisher eventPublisher; + + private static final List mockThings = new ArrayList<>(10); + + static { + for (int i = 0; i < 10; i++) { + mockThings.add(JMockData.mock(String.class)); + } + } + + /** mock数据推送,随机数据 */ + @RequestMapping("push/random") + public Result> randomPush() { + List list = new ArrayList<>(); + long ts = System.currentTimeMillis(); + List keyList = Arrays.stream(this.keys.split(",")).toList(); + Random random = new Random(); + for (int i = 0; i < 100; i++) { + TsKvProto mockTskv = + TsKvProto.newBuilder() + .setThingCode(mockThings.get(i % 10)) + .setKey(keyList.get(random.nextInt(keyList.size()))) + .setTs(ts) + .setVal(String.valueOf(JMockData.mock(Integer.class))) + .build(); + list.add(DataProto.newBuilder().setTskvProto(mockTskv).build()); + } + + eventPublisher.publishEvent( + new QueueConsumerEvent(Topics.V1_TSKV_HISTORY.getValue(), list)); + List tsKvList = + list.stream() + .map(DataProto::getTskvProto) + .map(e -> new TsKvDTO(e.getThingCode(), e.getKey(), e.getTs(), e.getVal())) + .collect(Collectors.toList()); + + return new Result>().ok(tsKvList); + } + + /** mock数据推送,指定数据 */ + @PostMapping("push/specify") + public Result specifyPush(@RequestBody TskvVO[] tskvVOList) { + List tsKvDTOList = new ArrayList<>(); + for (TskvVO tskvVO : tskvVOList) { + TsKvDTO tsKvDTO = + new TsKvDTO( + tskvVO.getThingCode(), + tskvVO.getAttrKey(), + Optional.ofNullable(tskvVO.getTs()).orElse(System.currentTimeMillis()), + Optional.ofNullable(tskvVO.getVal()).orElse(String.valueOf(JMockData.mock(Integer.class)))); + tsKvDTOList.add(tsKvDTO); + } + List dataList = + tsKvDTOList.stream().map(TsKvDTO::toDataProto).collect(Collectors.toList()); + + eventPublisher.publishEvent( + new QueueConsumerEvent(Topics.V1_TSKV_HISTORY.getValue(), dataList)); + + return new Result<>(); + } + + @Data + public static class TskvVO { + private String thingCode; + private String attrKey; + private Long ts; + private String val; + } +} diff --git a/application/src/main/java/com/thing/queue/DataTransferListener.java b/application/src/main/java/com/thing/queue/DataTransferListener.java new file mode 100644 index 0000000..28955dc --- /dev/null +++ b/application/src/main/java/com/thing/queue/DataTransferListener.java @@ -0,0 +1,69 @@ +package com.thing.queue; + +import com.alibaba.fastjson.JSON; +import lombok.extern.slf4j.Slf4j; +import com.thing.queue.util.Topics; +import com.thing.common.tskv.event.TsKvEvent; +import org.springframework.stereotype.Component; +import com.thing.common.data.event.QueueConsumerEvent; +import org.springframework.context.event.EventListener; +import org.springframework.context.ApplicationEventPublisher; + +import java.util.Map; +import java.util.Arrays; +import java.util.HashMap; +import javax.annotation.PreDestroy; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.Executors; +import javax.annotation.PostConstruct; +import java.util.concurrent.ScheduledExecutorService; + +/** + * @description 数据传输监听,范围: + * 1. tskv入库事件 + * 2. todo + */ +@Slf4j +@Component +public class DataTransferListener { + + private final ApplicationEventPublisher publisher; + private final Map total = new HashMap<>(); + private final ScheduledExecutorService schedule = Executors.newSingleThreadScheduledExecutor(); + + public DataTransferListener(ApplicationEventPublisher eventPublisher) { + this.publisher = eventPublisher; + } + + //数据统一消费中转 + @EventListener(QueueConsumerEvent.class) + void dataListener(QueueConsumerEvent consumerEvent) { + if (!consumerEvent.getList().isEmpty()) { + String topic = consumerEvent.getSource().toString(); + if (topic.contains(Topics.V1_TSKV.getValue())) { + publisher.publishEvent(new TsKvEvent(topic, consumerEvent.getList())); + } else { + log.info("-----QueueConsumerEvent--其它数据-----{}----->{}", consumerEvent.getSource(), consumerEvent.getList()); + } + String t = String.join("/", Arrays.copyOfRange(topic.split("/"), 0, 3)); + if (total.get(t) != null) { + total.put(t, total.get(t) + consumerEvent.getList().size()); + } else { + total.put(t, (long) consumerEvent.getList().size()); + } + } + } + + @PostConstruct + void dataTotalPrint() { + schedule.scheduleAtFixedRate(() -> { + log.info("------------数据累计处理--------->{}", total); + }, 1, 1, TimeUnit.MINUTES); + } + + @PreDestroy + void stopActorSystem() { + schedule.shutdown(); + } + +} diff --git a/application/src/main/resources/application.yml b/application/src/main/resources/application.yml new file mode 100644 index 0000000..3042094 --- /dev/null +++ b/application/src/main/resources/application.yml @@ -0,0 +1,271 @@ +server: + port: 18080 + servlet: + context-path: /thing +spring: + cache: + type: caffeine # 支持 redis/caffeine, 当选择redis时,要在application.yml中配置redis连接信息 + main: + allow-bean-definition-overriding: true + allow-circular-references: true + servlet: + multipart: + max-file-size: 100MB + max-request-size: 100MB + enabled: true + messages: + encoding: UTF-8 + basename: i18n/messages + data: + redis: + host: 192.168.188.185 + port: 7963 + password: Sddt8888! + database: 5 + #项目入口签名 + title: + sign: ck #企业签名 + technical: + phone: + map-bucket: geojson #地图文件路径 + +queue: + type: in-memory # 队列类型: inMemory / disruptor + inMemory: + maxSize: 500 + pollInterval: 100 + disruptor: + maximumPoolSize: 8 + bufferSize: 256 # 指定ringbuffer字节大小,当前值将乘1024 + partitions: + hash_function_name: murmur3_128 # murmur3_32, murmur3_128 or sha256 + core: + topic: queue_core + poll-interval: 1000 + partitions: 30 + debug: false + log-interval: 300 + rabbitmq: + exchange_name: + host: localhost + port: 5673 + virtual_host: / + username: guest + password: guest + automatic_recovery_enabled: false + connection_timeout: 60000 + handshake_timeout: 10000 + queue-properties: + core: x-max-length-bytes:1048576000;x-message-ttl:604800000 +#数据源配置 +database: + ts_kv: + type: postgresql # 时序数据存储类型 clickhouse/timescale/postgresql/tidb/mysql + latest: + type: postgresql # 最新数据存储类型 postgresql/timescale/mysql/tidb/clickhouse + save_maximumPoolSize: 12 +# 数据源及mybatis、mybatis-flex配置 +mybatis-flex: + typeAliasesPackage: com.thing.**.mapper + mapperLocations: classpath*:/mapper/**/*.xml + #本部分(Configuration)的配置都为 MyBatis 原生支持的配置,有关配置请参考:https://mybatis.org/mybatis-3/zh/configuration.html#%E8%AE%BE%E7%BD%AE%EF%BC%88settings%EF%BC%89 + configuration: + mapUnderscoreToCamelCase: true + autoMappingBehavior: FULL + autoMappingUnknownColumnBehavior: NONE + cacheEnabled: true + global-config: + print-banner: true + normal-value-of-logic-delete: 0 + deleted-value-of-logic-delete: 1 + datasource: + pg: + type: com.zaxxer.hikari.HikariDataSource + url: jdbc:postgresql://192.168.188.185:5432/thing_v2 + driver-class-name: org.postgresql.Driver + username: postgres + password: sddt8888 + postgresql: + type: com.zaxxer.hikari.HikariDataSource + url: jdbc:postgresql://192.168.188.185:5432/thing_v2 + driver-class-name: org.postgresql.Driver + username: postgres + password: sddt8888 + sqlServer: + type: com.zaxxer.hikari.HikariDataSource + url: jdbc:sqlserver://127.0.0.1:1433;databaseName=销售生产其他 + driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver + username: czj + password: 1234 + +# 区间统计计算相关配置 +calculate: + am_total: + offset: 24 #当数据出现断点时,向后偏移查询多少小时 + interval: 15 # 分区间统计,间隔时长(分)1/3/5/10/15/20/30/60 + keys: A29,B2,C2,C6,D2,D4,E3,E4,F4,G2,G4,H2,I2,I4,K2,N2,N4,P4,Q2,R2,R4,S2,S4,F2,T2,T4,U2,U4,J2,J4,L2,A30,P2,Q4,V2,V4,A29_rush,A29_peak,A29_valley,A29_normal,A29_generate,A30_rush,A30_peak,A30_valley,A30_normal,tce_C6,tce_A29,tce_E3,CO2_A29,CO2_C6,CO2_E3,CO2_run,tce_run,tce_E3,A201,A202,A204,tce_J2 + ddmmyy: #例如:每月1号0时0分 开始统计年/月/日用量 + start_hh: 0 #小时/天/月/年 用量统计开始的分钟数(0-59) + start_dd: 0 #天/月/年 用量统计开始的小时(0-23) + start_mm: 1 #月/年 用量统计开始的天(1-30) + start_yy: 1 #年 用量统计开始的月份(1-12) + maximumPoolSize: 12 + +# 产品碳足迹 相关配置 +carbon: + syncButton: false + pub: + # 公共服务侧租户标识 + tenantTag: 公共服务 + api: + secret: nba!w^0@01 + +#物管理相关配置 +thing: + # token 过期时间 30天 + token: + expire: 2592000 + +##数据解析配置 +nashorn: + # JS Eval max request timeout. 0 - no timeout + max_requests_timeout: 0 + # Specify thread pool size for javascript executor service + js_thread_pool_size: 120 + # Specify thread pool size for JavaScript sandbox resource monitor + monitor_thread_pool_size: 12 + # Maximum CPU time in milliseconds allowed for script execution + max_cpu_time: 8000 +tbel: + # JS Eval max request timeout. 0 - no timeout + max_requests_timeout: 0 + # Specify thread pool size for javascript executor service + thread_pool_size: 100 + # Maximum allowed TBEL script execution memory + max_memory_limit_mb: 8 + compiled_scripts_cache_size: 1000 +aviator: + # JS Eval max request timeout. 0 - no timeout + max_requests_timeout: 0 + # Specify thread pool size for javascript executor service + js_thread_pool_size: 100 + # Whether to put capturing groups into passed-in env map + # when regular-expression pattern matches + put_capturing_groups_into_env: false + # Max loop count to prevent too much CPU consumption. If it's value is zero or negative, it means + # no limitation on loop count.Default is zero. + max_loop_count: 1000 +#队列相关配置 +transport: + # Enable/disable http/mqtt/... transport protocols (has higher priority than certain protocol's 'enabled' property) + api_enabled: true + sessions: + inactivity_timeout: 300000 + report_timeout: 30000 + rate_limits: + enabled: false + # 1s 10次,60s 300次 + device: 10:1,300:60 + # Local HTTP transport parameters + http: + # Enable/disable http transport protocol. + enabled: false + request_timeout: 60000 + # Local MQTT transport parameters + mqtt: + # Enable/disable mqtt transport protocol. + enabled: false + bind_address: 0.0.0.0 + bind_port: 1883 + timeout: 10000 + netty: + leak_detector_level: DISABLED + boss_group_thread_count: 1 + worker_group_thread_count: 12 + max_payload_size: 65536 + so_keep_alive: false +#告警模块 配置 +alarm: + event_bus: + queue_size: 50 + core_pool_size: 5 + max_pool_size: 20 + +#swagger 文档配置 +springdoc: + swagger-ui: + path: /swagger-ui.html + packages-to-scan: com.thing + api-docs: + enabled: true +# knife4j的增强配置,不需要增强可以不配 +knife4j: + enable: true + setting: + language: zh_cn +#数据过滤配置 +filter: + rule: + enable: false +#项目状态 +management: + health: + redis: + enabled: false + endpoints: + enabled-by-default: true #暴露所有端点信息 + web: + exposure: + include: '*' #以web方式暴露 + +# 缓存管理 +cache-manager: + specs: + security: + timeToLiveInMinutes: 10 + maxSize: 50 + thingModel: + timeToLiveInMinutes: 1440 + maxSize: 10000 + authThingCodes: + timeToLiveInMinutes: 1440 + maxSize: 10000 + thingEntity: + timeToLiveInMinutes: 1440 + maxSize: 10000 + thingDict: + timeToLiveInMinutes: 1440 + maxSize: 10000 + thingDictRelation: + timeToLiveInMinutes: 1440 + maxSize: 10000 + thingDetailRelation: + timeToLiveInMinutes: 1440 + maxSize: 10000 + thingRootRelation: + timeToLiveInMinutes: 1440 + maxSize: 10000 + thingCalcConfig: + timeToLiveInMinutes: 525600 + maxSize: 10000 + filterRule: + timeToLiveInMinutes: 525600 + maxSize: 10000 + alarmRule: + timeToLiveInMinutes: 525600 + maxSize: 1000 + alarmRuleEntity: + timeToLiveInMinutes: 525600 + maxSize: 1000 + alarmRuleAction: + timeToLiveInMinutes: 525600 + maxSize: 1000 + scriptInfo: + timeToLiveInMinutes: 525600 + maxSize: 1000 + mockDataConfig: + timeToLiveInMinutes: 525600 + maxSize: 1000 + mockDataLatestTime: + timeToLiveInMinutes: 525600 + maxSize: 1000 diff --git a/application/src/main/resources/logback.xml b/application/src/main/resources/logback.xml new file mode 100644 index 0000000..b3fe325 --- /dev/null +++ b/application/src/main/resources/logback.xml @@ -0,0 +1,160 @@ + + + + + + + + + logback + + + + + + + + + + + + + + + + + info + + + ${CONSOLE_LOG_PATTERN} + + UTF-8 + + + + + + + + + + ${log.path}/debug.log + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n + UTF-8 + + + + + ${log.path}/debug/debug-%d{yyyy-MM-dd}.%i.log + + 100MB + + + 15 + + + + debug + ACCEPT + DENY + + + + + + + ${log.path}/info.log + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n + UTF-8 + + + + + ${log.path}/info/info-%d{yyyy-MM-dd}.%i.log + + 2048MB + + + 90 + + + + info + ACCEPT + DENY + + + + + + + ${log.path}/warn.log + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n + UTF-8 + + + + ${log.path}/warn/warn-%d{yyyy-MM-dd}.%i.log + + 1024MB + + + 365 + + + + warn + ACCEPT + DENY + + + + + + + + ${log.path}/error.log + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n + UTF-8 + + + + ${log.path}/error/error-%d{yyyy-MM-dd}.%i.log + + 1024MB + + + 365 + + + + ERROR + ACCEPT + DENY + + + + + + + + + + + + + + \ No newline at end of file diff --git a/application/src/main/resources/static/favicon.ico b/application/src/main/resources/static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..dea688e1759328c4ee57dd2e461931fb8a0e2e86 GIT binary patch literal 37029 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 MgbgE&TN6(I4_~fT`v3p{ literal 0 HcmV?d00001 diff --git a/tools/code-generator/pom.xml b/tools/code-generator/pom.xml new file mode 100644 index 0000000..96e6a99 --- /dev/null +++ b/tools/code-generator/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + + com.thing + tools + 5.1 + ../pom.xml + + + com.thing.tools + code-generator + jar + ThingBI Server Modules code-generator + + UTF-8 + + + + + com.thing.modules + thing + + + + org.freemarker + freemarker + 2.3.31 + + + + \ No newline at end of file diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/config/DataSourceInfo.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/config/DataSourceInfo.java new file mode 100644 index 0000000..bf4d4f8 --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/config/DataSourceInfo.java @@ -0,0 +1,71 @@ +package com.thing.tools.codegenerator.config; + +import com.thing.tools.codegenerator.config.query.*; +import com.thing.tools.codegenerator.entity.DataSourceEntity; +import com.thing.tools.codegenerator.utils.DbType; +import com.thing.tools.codegenerator.utils.DbUtils; + +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.sql.Connection; +import java.sql.SQLException; + +/** + * 数据源信息 + * + * @author Mark sunlightcs@gmail.com + */ +@Data +@Slf4j +public class DataSourceInfo { + /** 数据源ID */ + private Long id; + /** 数据库类型 */ + private DbType dbType; + /** 数据库URL */ + private String connUrl; + /** 用户名 */ + private String username; + /** 密码 */ + private String password; + + private AbstractQuery dbQuery; + + private Connection connection; + + public DataSourceInfo(DataSourceEntity entity) { + this.id = entity.getId(); + this.dbType = DbType.valueOf(entity.getDbType()); + this.connUrl = entity.getConnUrl(); + this.username = entity.getUsername(); + this.password = entity.getPassword(); + + switch (dbType) { + case MySQL -> this.dbQuery = new MySqlQuery(); + case Oracle -> this.dbQuery = new OracleQuery(); + case SQLServer -> this.dbQuery = new SqlServerQuery(); + case PostgreSQL -> this.dbQuery = new PostgreSqlQuery(); + } + + try { + this.connection = DbUtils.getConnection(this); + } catch (Exception e) { + log.error("connect error: ", e); + } + } + + public DataSourceInfo(Connection connection) throws SQLException { + this.id = 0L; + this.dbType = DbType.valueOf(connection.getMetaData().getDatabaseProductName()); + + switch (dbType) { + case MySQL -> this.dbQuery = new MySqlQuery(); + case Oracle -> this.dbQuery = new OracleQuery(); + case SQLServer -> this.dbQuery = new SqlServerQuery(); + case PostgreSQL -> this.dbQuery = new PostgreSqlQuery(); + } + + this.connection = connection; + } +} diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/config/query/AbstractQuery.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/config/query/AbstractQuery.java new file mode 100644 index 0000000..8c3f81a --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/config/query/AbstractQuery.java @@ -0,0 +1,59 @@ +package com.thing.tools.codegenerator.config.query; + + +import com.thing.tools.codegenerator.utils.DbType; + +/** + * Query + * + * @author Mark sunlightcs@gmail.com + */ +public interface AbstractQuery { + + /** + * 数据库类型 + */ + DbType dbType(); + + /** + * 表信息查询 SQL + */ + String tablesSql(String tableName); + + /** + * 表名称 + */ + String tableName(); + + /** + * 表注释 + */ + String tableComment(); + + /** + * 表字段信息查询 SQL + */ + String tableFieldsSql(); + + /** + * 字段名称 + */ + String fieldName(); + + + /** + * 字段类型 + */ + String fieldType(); + + + /** + * 字段注释 + */ + String fieldComment(); + + /** + * 主键字段 + */ + String fieldKey(); +} diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/config/query/MySqlQuery.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/config/query/MySqlQuery.java new file mode 100644 index 0000000..7b66a29 --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/config/query/MySqlQuery.java @@ -0,0 +1,68 @@ +package com.thing.tools.codegenerator.config.query; + +import com.thing.tools.codegenerator.utils.DbType; + +import org.apache.commons.lang3.StringUtils; + +/** + * MySQL查询 + * + * @author Mark sunlightcs@gmail.com + */ +public class MySqlQuery implements AbstractQuery { + + @Override + public DbType dbType() { + return DbType.MySQL; + } + + @Override + public String tablesSql(String tableName) { + StringBuilder sql = new StringBuilder(); + sql.append("select table_name, table_comment from information_schema.tables "); + sql.append("where table_schema = (select database()) "); + // 表名查询 + if (StringUtils.isNotBlank(tableName)) { + sql.append("and table_name = '").append(tableName).append("' "); + } + sql.append("order by table_name asc"); + + return sql.toString(); + } + + @Override + public String tableName() { + return "table_name"; + } + + @Override + public String tableComment() { + return "table_comment"; + } + + @Override + public String tableFieldsSql() { + return "select column_name, data_type, column_comment, column_key from information_schema.columns " + + "where table_name = '%s' and table_schema = (select database()) order by ordinal_position"; + } + + @Override + public String fieldName() { + return "column_name"; + } + + @Override + public String fieldType() { + return "data_type"; + } + + @Override + public String fieldComment() { + return "column_comment"; + } + + @Override + public String fieldKey() { + return "column_key"; + } +} diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/config/query/OracleQuery.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/config/query/OracleQuery.java new file mode 100644 index 0000000..d83c007 --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/config/query/OracleQuery.java @@ -0,0 +1,73 @@ +package com.thing.tools.codegenerator.config.query; + +import com.thing.tools.codegenerator.utils.DbType; +import org.apache.commons.lang3.StringUtils; + +/** + * Oracle查询 + * + * @author Mark sunlightcs@gmail.com + */ +public class OracleQuery implements AbstractQuery { + + @Override + public DbType dbType() { + return DbType.Oracle; + } + + @Override + public String tablesSql(String tableName) { + StringBuilder sql = new StringBuilder(); + sql.append("select dt.table_name, dtc.comments from user_tables dt,user_tab_comments dtc "); + sql.append("where dt.table_name = dtc.table_name "); + //表名查询 + if(StringUtils.isNotBlank(tableName)){ + sql.append("and dt.table_name = '").append(tableName).append("' "); + } + sql.append("order by dt.table_name asc"); + + return sql.toString(); + } + + @Override + public String tableName() { + return "table_name"; + } + + @Override + public String tableComment() { + return "comments"; + } + + @Override + public String tableFieldsSql() { + return "SELECT A.COLUMN_NAME, A.DATA_TYPE, B.COMMENTS,DECODE(C.POSITION, '1', 'PRI') KEY FROM ALL_TAB_COLUMNS A " + + " INNER JOIN ALL_COL_COMMENTS B ON A.TABLE_NAME = B.TABLE_NAME AND A.COLUMN_NAME = B.COLUMN_NAME AND B.OWNER = '#schema'" + + " LEFT JOIN ALL_CONSTRAINTS D ON D.TABLE_NAME = A.TABLE_NAME AND D.CONSTRAINT_TYPE = 'P' AND D.OWNER = '#schema'" + + " LEFT JOIN ALL_CONS_COLUMNS C ON C.CONSTRAINT_NAME = D.CONSTRAINT_NAME AND C.COLUMN_NAME=A.COLUMN_NAME AND C.OWNER = '#schema'" + + "WHERE A.OWNER = '#schema' AND A.TABLE_NAME = '%s' ORDER BY A.COLUMN_ID "; + } + + @Override + public String fieldName() { + return "COLUMN_NAME"; + } + + + @Override + public String fieldType() { + return "DATA_TYPE"; + } + + + @Override + public String fieldComment() { + return "COMMENTS"; + } + + + @Override + public String fieldKey() { + return "KEY"; + } +} diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/config/query/PostgreSqlQuery.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/config/query/PostgreSqlQuery.java new file mode 100644 index 0000000..bee784e --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/config/query/PostgreSqlQuery.java @@ -0,0 +1,72 @@ +package com.thing.tools.codegenerator.config.query; + +import com.thing.tools.codegenerator.utils.DbType; + +import org.apache.commons.lang3.StringUtils; + +/** + * PostgreSql查询 + * + * @author Mark sunlightcs@gmail.com + */ +public class PostgreSqlQuery implements AbstractQuery { + + @Override + public DbType dbType() { + return DbType.PostgreSQL; + } + + @Override + public String tablesSql(String tableName) { + StringBuilder sql = new StringBuilder(); + sql.append( + "select t1.tablename, obj_description(relfilenode, 'pg_class') as comments from pg_tables t1, pg_class t2 "); + sql.append( + "where t1.tablename not like 'pg%' and t1.tablename not like 'sql_%' and t1.tablename = t2.relname "); + // 表名查询 + if (StringUtils.isNotBlank(tableName)) { + sql.append("and t1.tablename = '").append(tableName).append("' "); + } + + return sql.toString(); + } + + @Override + public String tableFieldsSql() { + return "select t2.attname as columnName, pg_type.typname as dataType, col_description(t2.attrelid,t2.attnum) as columnComment," + + "(CASE t3.contype WHEN 'p' THEN 'PRI' ELSE '' END) as columnKey " + + "from pg_class as t1, pg_attribute as t2 inner join pg_type on pg_type.oid = t2.atttypid " + + "left join pg_constraint t3 on t2.attnum = t3.conkey[1] and t2.attrelid = t3.conrelid " + + "where t1.relname = '%s' and t2.attrelid = t1.oid and t2.attnum>0"; + } + + @Override + public String tableName() { + return "tablename"; + } + + @Override + public String tableComment() { + return "comments"; + } + + @Override + public String fieldName() { + return "columnName"; + } + + @Override + public String fieldType() { + return "dataType"; + } + + @Override + public String fieldComment() { + return "columnComment"; + } + + @Override + public String fieldKey() { + return "columnKey"; + } +} diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/config/query/SqlServerQuery.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/config/query/SqlServerQuery.java new file mode 100644 index 0000000..b6d123c --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/config/query/SqlServerQuery.java @@ -0,0 +1,83 @@ +package com.thing.tools.codegenerator.config.query; + +import com.thing.tools.codegenerator.utils.DbType; +import org.apache.commons.lang3.StringUtils; + +/** + * SqlServer查询 + * + * @author Mark sunlightcs@gmail.com + */ +public class SqlServerQuery implements AbstractQuery { + + @Override + public DbType dbType() { + return DbType.SQLServer; + } + + @Override + public String tablesSql(String tableName) { + StringBuilder sql = new StringBuilder(); + sql.append( + "select cast(so.name as varchar(500)) as TABLE_NAME, cast(sep.value as varchar(500)) as COMMENTS from sysobjects so "); + sql.append( + "left JOIN sys.extended_properties sep on sep.major_id=so.id and sep.minor_id=0 where (xtype='U' or xtype='V') "); + + // 表名查询 + if (StringUtils.isNotBlank(tableName)) { + sql.append("and cast(so.name as varchar(500)) = '").append(tableName).append("' "); + } + sql.append(" order by cast(so.name as varchar(500))"); + + return sql.toString(); + } + + @Override + public String tableFieldsSql() { + return "SELECT cast(a.name AS VARCHAR(500)) AS TABLE_NAME,cast(b.name AS VARCHAR(500)) AS COLUMN_NAME, " + + "cast(c.VALUE AS NVARCHAR(500)) AS COMMENTS,cast(sys.types.name AS VARCHAR (500)) AS DATA_TYPE," + + "(SELECT CASE count(1) WHEN 1 then 'PRI' ELSE '' END" + + " FROM syscolumns,sysobjects,sysindexes,sysindexkeys,systypes " + + " WHERE syscolumns.xusertype = systypes.xusertype AND syscolumns.id = object_id (a.name) AND sysobjects.xtype = 'PK'" + + " AND sysobjects.parent_obj = syscolumns.id AND sysindexes.id = syscolumns.id " + + " AND sysobjects.name = sysindexes.name AND sysindexkeys.id = syscolumns.id " + + " AND sysindexkeys.indid = sysindexes.indid " + + " AND syscolumns.colid = sysindexkeys.colid AND syscolumns.name = b.name) as 'KEY'," + + " b.is_identity isIdentity " + + " FROM ( select name,object_id from sys.tables UNION all select name,object_id from sys.views ) a " + + " INNER JOIN sys.columns b ON b.object_id = a.object_id " + + " LEFT JOIN sys.types ON b.user_type_id = sys.types.user_type_id " + + " LEFT JOIN sys.extended_properties c ON c.major_id = b.object_id AND c.minor_id = b.column_id " + + " WHERE a.name = '%s' and sys.types.name !='sysname' "; + } + + @Override + public String tableName() { + return "TABLE_NAME"; + } + + @Override + public String tableComment() { + return "COMMENTS"; + } + + @Override + public String fieldName() { + return "COLUMN_NAME"; + } + + @Override + public String fieldType() { + return "DATA_TYPE"; + } + + @Override + public String fieldComment() { + return "COMMENTS"; + } + + @Override + public String fieldKey() { + return "KEY"; + } +} diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/controller/BaseClassController.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/controller/BaseClassController.java new file mode 100644 index 0000000..7a39fa8 --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/controller/BaseClassController.java @@ -0,0 +1,65 @@ +package com.thing.tools.codegenerator.controller; + +import com.thing.common.core.web.response.PageData; +import com.thing.common.core.web.response.Result; +import com.thing.tools.codegenerator.entity.BaseClassEntity; +import com.thing.tools.codegenerator.service.BaseClassService; + +import lombok.RequiredArgsConstructor; + +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Map; + +/** + * 基类管理 + * + * @author Mark sunlightcs@gmail.com + */ +@RestController +@RequestMapping("devtools/baseclass") +@RequiredArgsConstructor +public class BaseClassController { + private final BaseClassService baseClassService; + + @GetMapping("page") + public Result> page(@RequestParam Map params) { + PageData page = baseClassService.page(params); + + return new Result>().ok(page); + } + + @GetMapping("list") + public Result> list() { + List list = baseClassService.list(); + + return new Result>().ok(list); + } + + @GetMapping("{id}") + public Result get(@PathVariable("id") Long id) { + BaseClassEntity data = baseClassService.getById(id); + + return new Result().ok(data); + } + + @PostMapping + public Result save(@RequestBody BaseClassEntity entity) { + baseClassService.save(entity); + return new Result<>(); + } + + @PutMapping + public Result update(@RequestBody BaseClassEntity entity) { + baseClassService.updateById(entity); + + return new Result<>(); + } + + @DeleteMapping + public Result delete(@RequestBody Long[] ids) { + baseClassService.batchDelete(ids); + return new Result<>(); + } +} diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/controller/DataSourceController.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/controller/DataSourceController.java new file mode 100644 index 0000000..dc906e5 --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/controller/DataSourceController.java @@ -0,0 +1,74 @@ +package com.thing.tools.codegenerator.controller; + +import com.thing.common.core.web.response.PageData; +import com.thing.common.core.web.response.Result; +import com.thing.tools.codegenerator.config.DataSourceInfo; +import com.thing.tools.codegenerator.entity.DataSourceEntity; +import com.thing.tools.codegenerator.service.DataSourceService; +import com.thing.tools.codegenerator.utils.DbUtils; + +import lombok.RequiredArgsConstructor; + +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Map; + +/** + * 数据源管理 + * + * @author Mark sunlightcs@gmail.com + */ +@RestController +@RequestMapping("devtools/datasource") +@RequiredArgsConstructor +public class DataSourceController { + private final DataSourceService datasourceService; + + @GetMapping("page") + public Result> page(@RequestParam Map params){ + PageData page = datasourceService.page(params); + return new Result>().ok(page); + } + + @GetMapping("list") + public Result> list(){ + List list = datasourceService.list(); + return new Result>().ok(list); + } + + @GetMapping("{id}") + public Result get(@PathVariable("id") Long id){ + DataSourceEntity data = datasourceService.getById(id); + return new Result().ok(data); + } + + @GetMapping("test/{id}") + public Result test(@PathVariable("id") Long id){ + try { + DataSourceEntity entity = datasourceService.getById(id); + DbUtils.getConnection(new DataSourceInfo(entity)); + return new Result().ok("连接成功"); + } catch (Exception e) { + return new Result().error("连接失败,请检查配置信息"); + } + } + + @PostMapping + public Result save(@RequestBody DataSourceEntity entity){ + datasourceService.save(entity); + return new Result<>(); + } + + @PutMapping + public Result update(@RequestBody DataSourceEntity entity){ + datasourceService.updateById(entity); + return new Result<>(); + } + + @DeleteMapping + public Result delete(@RequestBody Long[] ids){ + datasourceService.batchDelete(ids); + return new Result<>(); + } +} \ No newline at end of file diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/controller/FieldTypeController.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/controller/FieldTypeController.java new file mode 100644 index 0000000..d61e0d7 --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/controller/FieldTypeController.java @@ -0,0 +1,65 @@ +package com.thing.tools.codegenerator.controller; + +import com.thing.common.core.web.response.PageData; +import com.thing.common.core.web.response.Result; +import com.thing.tools.codegenerator.entity.FieldTypeEntity; +import com.thing.tools.codegenerator.service.FieldTypeService; + +import lombok.RequiredArgsConstructor; + +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * 字段类型管理 + * + * @author Mark sunlightcs@gmail.com + */ +@RestController +@RequestMapping("devtools/fieldtype") +@RequiredArgsConstructor +public class FieldTypeController { + private final FieldTypeService fieldTypeService; + + @GetMapping("page") + public Result> page(@RequestParam Map params) { + PageData page = fieldTypeService.page(params); + return new Result>().ok(page); + } + + @GetMapping("{id}") + public Result get(@PathVariable("id") Long id) { + FieldTypeEntity data = fieldTypeService.getById(id); + return new Result().ok(data); + } + + @GetMapping("list") + public Result> list() { + List list = fieldTypeService.list(); + Set set = + list.stream().map(FieldTypeEntity::getAttrType).collect(Collectors.toSet()); + return new Result>().ok(set); + } + + @PostMapping + public Result save(@RequestBody FieldTypeEntity entity) { + fieldTypeService.save(entity); + return new Result<>(); + } + + @PutMapping + public Result update(@RequestBody FieldTypeEntity entity) { + fieldTypeService.updateById(entity); + return new Result<>(); + } + + @DeleteMapping + public Result delete(@RequestBody Long[] ids) { + fieldTypeService.batchDelete(ids); + return new Result<>(); + } +} diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/controller/GenParamController.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/controller/GenParamController.java new file mode 100644 index 0000000..9268d8f --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/controller/GenParamController.java @@ -0,0 +1,36 @@ +package com.thing.tools.codegenerator.controller; + +import com.google.gson.Gson; +import com.thing.common.core.constants.Constant; +import com.thing.common.core.web.response.Result; +import com.thing.sys.biz.service.SysParamsService; +import com.thing.tools.codegenerator.entity.GenParam; + +import lombok.RequiredArgsConstructor; + +import org.springframework.web.bind.annotation.*; + +/** + * 代码生成参数配置 + * + * @author Mark sunlightcs@gmail.com + */ +@RestController +@RequestMapping("devtools/param") +@RequiredArgsConstructor +public class GenParamController { + private final SysParamsService sysParamsService; + + @GetMapping("info") + public Result info() { + GenParam param = + sysParamsService.getValueObject(Constant.DEV_TOOLS_PARAM_KEY, GenParam.class); + return new Result().ok(param); + } + + @PostMapping + public Result saveConfig(@RequestBody GenParam param) { + sysParamsService.updateValueByCode(Constant.DEV_TOOLS_PARAM_KEY, new Gson().toJson(param)); + return new Result<>(); + } +} diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/controller/GeneratorController.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/controller/GeneratorController.java new file mode 100644 index 0000000..0a61bd2 --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/controller/GeneratorController.java @@ -0,0 +1,118 @@ +package com.thing.tools.codegenerator.controller; + +import com.thing.common.core.web.response.PageData; +import com.thing.common.core.web.response.Result; +import com.thing.sys.biz.entity.DictType; +import com.thing.sys.biz.service.SysDictTypeService; +import com.thing.tools.codegenerator.config.DataSourceInfo; +import com.thing.tools.codegenerator.entity.MenuEntity; +import com.thing.tools.codegenerator.entity.TableFieldEntity; +import com.thing.tools.codegenerator.entity.TableInfoEntity; +import com.thing.tools.codegenerator.service.GeneratorService; +import com.thing.tools.codegenerator.service.TableFieldService; +import com.thing.tools.codegenerator.service.TableInfoService; +import com.thing.tools.codegenerator.utils.DbUtils; + +import lombok.RequiredArgsConstructor; + +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Map; + +/** + * 代码生成 + * + * @author Mark sunlightcs@gmail.com + */ +@RestController +@RequestMapping("devtools") +@RequiredArgsConstructor +public class GeneratorController { + private final GeneratorService generatorService; + private final TableInfoService tableInfoService; + private final TableFieldService tableFieldService; + private final SysDictTypeService sysDictTypeService; + + @GetMapping("table/page") + public Result> pageTable(@RequestParam Map params) { + PageData page = tableInfoService.getPageData(params); + return new Result>().ok(page); + } + + @GetMapping("table/{id}") + public Result getTable(@PathVariable("id") Long id) { + TableInfoEntity table = tableInfoService.getById(id); + List fieldList = tableFieldService.getByTableName(table.getTableName()); + table.setFields(fieldList); + return new Result().ok(table); + } + + @PutMapping("table") + public Result updateTable(@RequestBody TableInfoEntity tableInfo) { + tableInfoService.updateById(tableInfo); + return new Result<>(); + } + + @DeleteMapping("table") + public Result deleteTable(@RequestBody Long[] ids) { + tableInfoService.deleteBatchIds(ids); + return new Result<>(); + } + + /** 获取数据源中所有表 */ + @GetMapping("datasource/table/list/{id}") + public Result> getDataSourceTableList(@PathVariable("id") Long id) { + try { + // 初始化配置信息 + DataSourceInfo info = generatorService.getDataSourceInfo(id); + List tableInfoList = DbUtils.getTablesInfoList(info); + return new Result>().ok(tableInfoList); + } catch (Exception e) { + return new Result>().error("数据源配置错误,请检查数据源配置!"); + } + } + + /** 导入数据源中的表 */ + @PostMapping("datasource/table") + public Result datasourceTable(@RequestBody TableInfoEntity tableInfo) { + generatorService.datasourceTable(tableInfo); + return new Result<>(); + } + + /** 更新列数据 */ + @PutMapping("table/field/{tableId}") + public Result updateTableField( + @PathVariable("tableId") Long tableId, + @RequestBody List tableFieldList) { + generatorService.updateTableField(tableId, tableFieldList); + return new Result<>(); + } + + @GetMapping("dict") + public Result> dict() { + List list = sysDictTypeService.getDictTypeList(); + return new Result>().ok(list); + } + + /** 生成代码 */ + @PostMapping("generator") + public Result generator(@RequestBody TableInfoEntity tableInfo) { + // 保存表信息 + tableInfoService.updateById(tableInfo); + + // 生成代码 + generatorService.generatorCode(tableInfo); + + return new Result<>(); + } + + /** 创建菜单 */ + @PostMapping("menu") + public Result menu(@RequestBody MenuEntity menu) { + // 创建菜单 + generatorService.generatorMenu(menu); + + return new Result<>(); + } +} diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/controller/TemplateController.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/controller/TemplateController.java new file mode 100644 index 0000000..2771044 --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/controller/TemplateController.java @@ -0,0 +1,83 @@ +package com.thing.tools.codegenerator.controller; + +import com.google.common.collect.Maps; +import com.thing.common.core.exception.SysException; +import com.thing.common.core.web.response.PageData; +import com.thing.common.core.web.response.Result; +import com.thing.tools.codegenerator.entity.TemplateEntity; +import com.thing.tools.codegenerator.service.TemplateService; +import com.thing.tools.codegenerator.utils.GenUtils; + +import lombok.RequiredArgsConstructor; + +import org.springframework.web.bind.annotation.*; + +import java.util.Map; + +/** + * 模板管理 + * + * @author Mark sunlightcs@gmail.com + */ +@RestController +@RequestMapping("devtools/template") +@RequiredArgsConstructor +public class TemplateController { + private final TemplateService templateService; + + @GetMapping("page") + public Result> page(@RequestParam Map params) { + PageData page = templateService.page(params); + return new Result>().ok(page); + } + + @GetMapping("{id}") + public Result get(@PathVariable("id") Long id) { + TemplateEntity data = templateService.getById(id); + return new Result().ok(data); + } + + @PostMapping + public Result save(@RequestBody TemplateEntity entity) { + try { + // 检查模板语法是否正确 + GenUtils.getTemplateContent(entity.getContent(), Maps.newHashMap()); + } catch (Exception e) { + throw new SysException("模板语法错误,请查看控制台报错信息!", e); + } + templateService.save(entity); + return new Result<>(); + } + + @PutMapping + public Result update(@RequestBody TemplateEntity entity) { + try { + // 检查模板语法是否正确 + GenUtils.getTemplateContent(entity.getContent(), Maps.newHashMap()); + } catch (Exception e) { + throw new SysException("模板语法错误,请查看控制台报错信息!", e); + } + templateService.updateById(entity); + return new Result<>(); + } + + @DeleteMapping + public Result delete(@RequestBody Long[] ids) { + templateService.batchDelete(ids); + return new Result<>(); + } + + /** 启用 */ + @PutMapping("enabled") + public Result enabled(@RequestBody Long[] ids) { + templateService.updateStatusBatch(ids, 0); + return new Result<>(); + } + + /** 禁用 */ + @PutMapping("disabled") + public Result disabled(@RequestBody Long[] ids) { + templateService.updateStatusBatch(ids, 1); + return new Result<>(); + } +} diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/entity/BaseClassEntity.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/entity/BaseClassEntity.java new file mode 100644 index 0000000..0b992a6 --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/entity/BaseClassEntity.java @@ -0,0 +1,39 @@ +package com.thing.tools.codegenerator.entity; + +import com.mybatisflex.annotation.Table; + +import lombok.Data; + +/** + * 基类管理 + * + * @author Mark sunlightcs@gmail.com + */ +@Data +@Table("gen_base_class") +public class BaseClassEntity { + /** + * id + */ + private Long id; + /** + * 基类包名 + */ + private String packageName; + /** + * 基类编码 + */ + private String code; + /** + * 公共字段,多个用英文逗号分隔 + */ + private String fields; + /** + * 备注 + */ + private String remark; + /** + * 创建时间 + */ + private Long createDate; +} \ No newline at end of file diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/entity/DataSourceEntity.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/entity/DataSourceEntity.java new file mode 100644 index 0000000..b1e83e7 --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/entity/DataSourceEntity.java @@ -0,0 +1,49 @@ +package com.thing.tools.codegenerator.entity; + +import com.mybatisflex.annotation.Id; +import com.mybatisflex.annotation.Table; + +import lombok.Data; + +/** + * 数据源管理 + * + * @author Mark sunlightcs@gmail.com + */ +@Data +@Table("gen_datasource") +public class DataSourceEntity { + /** + * id + */ + @Id + private Long id; + /** + * 数据库类型 MySQL、Oracle、SQLServer、PostgreSQL + */ + private String dbType; + /** + * 连接名 + */ + private String connName; + /** + * URL + */ + private String connUrl; + /** + * 用户名 + */ + private String username; + /** + * 密码 + */ + private String password; + /** + * 状态 0:启用 1:禁用 + */ + private Integer status; + /** + * 创建时间 + */ + private Long createDate; +} \ No newline at end of file diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/entity/FieldTypeEntity.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/entity/FieldTypeEntity.java new file mode 100644 index 0000000..55666c0 --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/entity/FieldTypeEntity.java @@ -0,0 +1,38 @@ +package com.thing.tools.codegenerator.entity; + + +import com.mybatisflex.annotation.Id; +import com.mybatisflex.annotation.Table; + +import lombok.Data; + +/** + * 字段类型管理 + * + * @author Mark sunlightcs@gmail.com + */ +@Data +@Table("gen_field_type") +public class FieldTypeEntity { + /** + * id + */ + @Id + private Long id; + /** + * 字段类型 + */ + private String columnType; + /** + * 属性类型 + */ + private String attrType; + /** + * 属性包名 + */ + private String packageName; + /** + * 创建时间 + */ + private Long createDate; +} \ No newline at end of file diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/entity/GenParam.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/entity/GenParam.java new file mode 100644 index 0000000..a30f231 --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/entity/GenParam.java @@ -0,0 +1,25 @@ + +package com.thing.tools.codegenerator.entity; + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + +/** + * 代码生成参数配置 + * + * @author Mark sunlightcs@gmail.com + */ +@Data +public class GenParam implements Serializable { + @Serial + private static final long serialVersionUID = 1L; + + private String packageName; + private String version; + private String author; + private String email; + private String backendPath; + private String frontendPath; +} diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/entity/MenuEntity.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/entity/MenuEntity.java new file mode 100644 index 0000000..12bea95 --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/entity/MenuEntity.java @@ -0,0 +1,19 @@ + +package com.thing.tools.codegenerator.entity; + +import lombok.Data; + +/** + * 创建菜单 + * + * @author Mark sunlightcs@gmail.com + */ +@Data +public class MenuEntity { + private Long pid; + private String name; + private String icon; + private String moduleName; + private String className; + +} diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/entity/TableFieldEntity.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/entity/TableFieldEntity.java new file mode 100644 index 0000000..cd9489f --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/entity/TableFieldEntity.java @@ -0,0 +1,102 @@ +package com.thing.tools.codegenerator.entity; + + +import com.mybatisflex.annotation.Column; +import com.mybatisflex.annotation.Id; +import com.mybatisflex.annotation.Table; + +import lombok.Data; + +/** + * 表字段信息 + * + * @author Mark sunlightcs@gmail.com + */ +@Data +@Table("gen_table_field") +public class TableFieldEntity { + @Id + private Long id; + /** + * 表ID + */ + private Long tableId; + /** + * 表名 + */ + private String tableName; + /** + * 列名 + */ + private String columnName; + /** + * 类型 + */ + private String columnType; + /** + * 列说明 + */ + private String columnComment; + /** + * 列说明 + */ + @Column(ignore = true) + private String comment; + + public String getComment() { + return this.columnComment; + } + + /** + * 属性名 + */ + private String attrName; + /** + * 属性类型 + */ + private String attrType; + /** + * 属性包名 + */ + private String packageName; + /** + * 是否主键 0:否 1:是 + */ + private boolean isPk; + /** + * 是否必填 0:否 1:是 + */ + private boolean isRequired; + /** + * 是否表单字段 0:否 1:是 + */ + private boolean isForm; + /** + * 是否列表字段 0:否 1:是 + */ + private boolean isList; + /** + * 是否查询字段 0:否 1:是 + */ + private boolean isQuery; + /** + * 查询方式 + */ + private String queryType; + /** + * 表单类型 + */ + private String formType; + /** + * 字典名称 + */ + private String dictName; + /** + * 效验方式 + */ + private String validatorType; + /** + * 排序 + */ + private Integer sort; +} diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/entity/TableInfoEntity.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/entity/TableInfoEntity.java new file mode 100644 index 0000000..88d7f68 --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/entity/TableInfoEntity.java @@ -0,0 +1,83 @@ +package com.thing.tools.codegenerator.entity; + +import com.mybatisflex.annotation.Column; +import com.mybatisflex.annotation.Id; +import com.mybatisflex.annotation.Table; + +import lombok.Data; + +import java.util.List; + +/** + * 表信息 + * + * @author Mark sunlightcs@gmail.com + */ +@Data +@Table("gen_table_info") +public class TableInfoEntity { + @Id + private Long id; + /** + * 表名 + */ + private String tableName; + /** + * 实体类名称 + */ + private String className; + /** + * 功能名 + */ + private String tableComment; + /** + * 项目包名 + */ + private String packageName; + /** + * 项目版本号 + */ + private String version; + /** + * 作者 + */ + private String author; + /** + * 邮箱 + */ + private String email; + /** + * 后端生成路径 + */ + private String backendPath; + /** + * 前端生成路径 + */ + private String frontendPath; + /** + * 模块名 + */ + private String moduleName; + /** + * 子模块名 + */ + private String subModuleName; + /** + * 数据源ID + */ + private Long datasourceId; + /** + * 基类ID + */ + private Long baseclassId; + /** + * 时间 + */ + private Long createDate; + /** + * 表字段 + */ + @Column(ignore = true) + private List fields; + +} diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/entity/TemplateEntity.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/entity/TemplateEntity.java new file mode 100644 index 0000000..f8082ff --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/entity/TemplateEntity.java @@ -0,0 +1,46 @@ +package com.thing.tools.codegenerator.entity; + +import com.mybatisflex.annotation.Id; +import com.mybatisflex.annotation.Table; + +import lombok.Data; + +/** + * 模板管理 + * + * @author Mark sunlightcs@gmail.com + */ +@Data +@Table("gen_template") +public class TemplateEntity { + /** + * id + */ + @Id + private Long id; + /** + * 名称 + */ + private String name; + /** + * 内容 + */ + private String content; + /** + * 文件名 + */ + private String fileName; + /** + * 生成路径 + */ + private String path; + /** + * 状态 0:启用 1:禁用 + */ + private Integer status; + /** + * 创建时间 + */ + private Long createDate; + +} \ No newline at end of file diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/mapper/BaseClassMapper.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/mapper/BaseClassMapper.java new file mode 100644 index 0000000..9bc7b12 --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/mapper/BaseClassMapper.java @@ -0,0 +1,15 @@ +package com.thing.tools.codegenerator.mapper; + +import com.mybatisflex.core.BaseMapper; +import com.thing.tools.codegenerator.entity.BaseClassEntity; +import org.apache.ibatis.annotations.Mapper; + +/** + * 基类管理 + * + * @author Mark sunlightcs@gmail.com + */ +@Mapper +public interface BaseClassMapper extends BaseMapper { + +} \ No newline at end of file diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/mapper/DataSourceMapper.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/mapper/DataSourceMapper.java new file mode 100644 index 0000000..c63553a --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/mapper/DataSourceMapper.java @@ -0,0 +1,15 @@ +package com.thing.tools.codegenerator.mapper; + +import com.mybatisflex.core.BaseMapper; +import com.thing.tools.codegenerator.entity.DataSourceEntity; +import org.apache.ibatis.annotations.Mapper; + +/** + * 数据源管理 + * + * @author Mark sunlightcs@gmail.com + */ +@Mapper +public interface DataSourceMapper extends BaseMapper { + +} \ No newline at end of file diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/mapper/FieldTypeMapper.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/mapper/FieldTypeMapper.java new file mode 100644 index 0000000..4fbbbfc --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/mapper/FieldTypeMapper.java @@ -0,0 +1,26 @@ +package com.thing.tools.codegenerator.mapper; + +import com.mybatisflex.core.BaseMapper; +import com.thing.tools.codegenerator.entity.FieldTypeEntity; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Set; + +/** + * 字段类型管理 + * + * @author Mark sunlightcs@gmail.com + */ +@Mapper +public interface FieldTypeMapper extends BaseMapper { + + /** + * 根据tableId,获取包列表 + */ + Set getPackageListByTableId(Long tableId); + + /** + * 获取全部字段类型 + */ + Set list(); +} \ No newline at end of file diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/mapper/GeneratorMenuMapper.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/mapper/GeneratorMenuMapper.java new file mode 100644 index 0000000..65e542e --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/mapper/GeneratorMenuMapper.java @@ -0,0 +1,18 @@ +package com.thing.tools.codegenerator.mapper; + +import org.apache.ibatis.annotations.Mapper; + +import java.util.Map; + +/** + * 创建菜单 + * + * @author Mark sunlightcs@gmail.com + */ +@Mapper +public interface GeneratorMenuMapper { + + void generatorMenu(Map params); + + void generatorMenuLanguage(Map params); +} \ No newline at end of file diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/mapper/TableFieldMapper.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/mapper/TableFieldMapper.java new file mode 100644 index 0000000..f068056 --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/mapper/TableFieldMapper.java @@ -0,0 +1,22 @@ +package com.thing.tools.codegenerator.mapper; + +import com.mybatisflex.core.BaseMapper; +import com.thing.tools.codegenerator.entity.TableFieldEntity; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 表 + * + * @author Mark sunlightcs@gmail.com + */ +@Mapper +public interface TableFieldMapper extends BaseMapper { + + List getByTableName(String tableName); + + void deleteByTableName(String tableName); + + void deleteBatchTableIds(Long[] tableIds); +} diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/mapper/TableInfoMapper.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/mapper/TableInfoMapper.java new file mode 100644 index 0000000..8a222de --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/mapper/TableInfoMapper.java @@ -0,0 +1,17 @@ +package com.thing.tools.codegenerator.mapper; + +import com.mybatisflex.core.BaseMapper; +import com.thing.tools.codegenerator.entity.TableInfoEntity; +import org.apache.ibatis.annotations.Mapper; + +/** + * 列 + * + * @author Mark sunlightcs@gmail.com + */ +@Mapper +public interface TableInfoMapper extends BaseMapper { + TableInfoEntity getByTableName(String tableName); + + void deleteByTableName(String tableName); +} diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/mapper/TemplateMapper.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/mapper/TemplateMapper.java new file mode 100644 index 0000000..b8576a2 --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/mapper/TemplateMapper.java @@ -0,0 +1,18 @@ +package com.thing.tools.codegenerator.mapper; + +import com.mybatisflex.core.BaseMapper; +import com.thing.tools.codegenerator.entity.TemplateEntity; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Map; + +/** + * 模板管理 + * + * @author Mark sunlightcs@gmail.com + */ +@Mapper +public interface TemplateMapper extends BaseMapper { + + int updateStatusBatch(Map map); +} \ No newline at end of file diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/BaseClassService.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/BaseClassService.java new file mode 100644 index 0000000..fe342c3 --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/BaseClassService.java @@ -0,0 +1,20 @@ +package com.thing.tools.codegenerator.service; + +import com.thing.common.core.web.response.PageData; +import com.thing.common.orm.service.IBaseService; +import com.thing.tools.codegenerator.entity.BaseClassEntity; + +import java.util.List; +import java.util.Map; + +/** + * 基类管理 + * + * @author Mark sunlightcs@gmail.com + */ +public interface BaseClassService extends IBaseService { + + PageData page(Map params); + + List list(); +} \ No newline at end of file diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/DataSourceService.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/DataSourceService.java new file mode 100644 index 0000000..d58ddc0 --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/DataSourceService.java @@ -0,0 +1,20 @@ +package com.thing.tools.codegenerator.service; + +import com.thing.common.core.web.response.PageData; +import com.thing.common.orm.service.IBaseService; +import com.thing.tools.codegenerator.entity.DataSourceEntity; + +import java.util.List; +import java.util.Map; + +/** + * 数据源管理 + * + * @author Mark sunlightcs@gmail.com + */ +public interface DataSourceService extends IBaseService { + + PageData page(Map params); + + List list(); +} \ No newline at end of file diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/FieldTypeService.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/FieldTypeService.java new file mode 100644 index 0000000..ba9cba0 --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/FieldTypeService.java @@ -0,0 +1,26 @@ + + +package com.thing.tools.codegenerator.service; + +import com.thing.common.core.web.response.PageData; +import com.thing.common.orm.service.IBaseService; +import com.thing.tools.codegenerator.entity.FieldTypeEntity; + +import java.util.Map; +import java.util.Set; + +/** + * 字段类型管理 + * + * @author Mark sunlightcs@gmail.com + */ +public interface FieldTypeService extends IBaseService { + PageData page(Map params); + + Map getMap(); + + /** + * 根据tableId,获取包列表 + */ + Set getPackageListByTableId(Long tableId); +} \ No newline at end of file diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/GeneratorService.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/GeneratorService.java new file mode 100644 index 0000000..3cf3b2b --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/GeneratorService.java @@ -0,0 +1,26 @@ +package com.thing.tools.codegenerator.service; + +import com.thing.tools.codegenerator.config.DataSourceInfo; +import com.thing.tools.codegenerator.entity.MenuEntity; +import com.thing.tools.codegenerator.entity.TableFieldEntity; +import com.thing.tools.codegenerator.entity.TableInfoEntity; + +import java.util.List; + +/** + * 代码生成 + * + * @author Mark sunlightcs@gmail.com + */ +public interface GeneratorService { + + DataSourceInfo getDataSourceInfo(Long datasourceId); + + void datasourceTable(TableInfoEntity tableInfo); + + void updateTableField(Long tableId, List tableFieldList); + + void generatorCode(TableInfoEntity tableInfo); + + void generatorMenu(MenuEntity menu); +} diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/TableFieldService.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/TableFieldService.java new file mode 100644 index 0000000..c5dd8cf --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/TableFieldService.java @@ -0,0 +1,20 @@ +package com.thing.tools.codegenerator.service; + +import com.thing.common.orm.service.IBaseService; +import com.thing.tools.codegenerator.entity.TableFieldEntity; + +import java.util.List; + +/** + * 列 + * + * @author Mark sunlightcs@gmail.com + */ +public interface TableFieldService extends IBaseService { + + List getByTableName(String tableName); + + void deleteByTableName(String tableName); + + void deleteBatchTableIds(Long[] tableIds); +} \ No newline at end of file diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/TableInfoService.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/TableInfoService.java new file mode 100644 index 0000000..52332d9 --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/TableInfoService.java @@ -0,0 +1,23 @@ +package com.thing.tools.codegenerator.service; + +import com.thing.common.core.web.response.PageData; +import com.thing.common.orm.service.IBaseService; +import com.thing.tools.codegenerator.entity.TableInfoEntity; + +import java.util.Map; + +/** + * 表 + * + * @author Mark sunlightcs@gmail.com + */ +public interface TableInfoService extends IBaseService { + + PageData page(Map params); + + TableInfoEntity getByTableName(String tableName); + + void deleteByTableName(String tableName); + + void deleteBatchIds(Long[] ids); +} \ No newline at end of file diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/TemplateService.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/TemplateService.java new file mode 100644 index 0000000..a2f6f83 --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/TemplateService.java @@ -0,0 +1,24 @@ +package com.thing.tools.codegenerator.service; + + +import com.thing.common.core.web.response.PageData; +import com.thing.common.orm.service.IBaseService; +import com.thing.tools.codegenerator.entity.TemplateEntity; + +import java.util.List; +import java.util.Map; + +/** + * 模板管理 + * + * @author Mark sunlightcs@gmail.com + */ +public interface TemplateService extends IBaseService { + + PageData page(Map params); + + List list(); + + void updateStatusBatch(Long[] ids, int status); + +} \ No newline at end of file diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/impl/BaseClassServiceImpl.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/impl/BaseClassServiceImpl.java new file mode 100644 index 0000000..e2e8052 --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/impl/BaseClassServiceImpl.java @@ -0,0 +1,43 @@ +package com.thing.tools.codegenerator.service.impl; + +import com.mybatisflex.core.query.QueryWrapper; +import com.thing.common.core.web.response.PageData; +import com.thing.common.orm.service.impl.BaseServiceImpl; +import com.thing.tools.codegenerator.mapper.BaseClassMapper; +import com.thing.tools.codegenerator.entity.BaseClassEntity; +import com.thing.tools.codegenerator.service.BaseClassService; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; + +/** + * 基类管理 + * + * @author Mark sunlightcs@gmail.com + */ +@Service +public class BaseClassServiceImpl extends BaseServiceImpl implements BaseClassService { + + @Override + public QueryWrapper getWrapper(Map params){ + String code = (String)params.get("code"); + QueryWrapper wrapper = new QueryWrapper(); + wrapper.like("code", code, StringUtils.isNotEmpty(code)); + return wrapper; + } + + @Override + public PageData page(Map params) { + return getPageData(params); + } + + @Override + public List list() { + return mapper.selectAll(); + } + + +} \ No newline at end of file diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/impl/DataSourceServiceImpl.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/impl/DataSourceServiceImpl.java new file mode 100644 index 0000000..7e1615e --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/impl/DataSourceServiceImpl.java @@ -0,0 +1,43 @@ +package com.thing.tools.codegenerator.service.impl; + +import com.mybatisflex.core.query.QueryWrapper; +import com.thing.common.core.web.response.PageData; +import com.thing.common.orm.service.impl.BaseServiceImpl; +import com.thing.tools.codegenerator.mapper.DataSourceMapper; +import com.thing.tools.codegenerator.entity.DataSourceEntity; +import com.thing.tools.codegenerator.service.DataSourceService; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; + +/** + * 数据源管理 + * + * @author Mark sunlightcs@gmail.com + */ +@Service +public class DataSourceServiceImpl extends BaseServiceImpl implements DataSourceService { + + public QueryWrapper getWrapper(Map params){ + String connName = (String)params.get("connName"); + String dbType = (String)params.get("dbType"); + QueryWrapper wrapper = new QueryWrapper(); + wrapper.like("conn_name", connName, StringUtils.isNotEmpty(connName)); + wrapper.eq("db_type", dbType, StringUtils.isNotEmpty(dbType)); + return wrapper; + } + + @Override + public PageData page(Map params) { + return getPageData(params); + } + + @Override + public List list() { + return mapper.selectListByQuery(QueryWrapper.create().eq(DataSourceEntity::getStatus, 0)); + } + +} \ No newline at end of file diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/impl/FieldTypeServiceImpl.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/impl/FieldTypeServiceImpl.java new file mode 100644 index 0000000..c0e161b --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/impl/FieldTypeServiceImpl.java @@ -0,0 +1,57 @@ +package com.thing.tools.codegenerator.service.impl; + +import com.mybatisflex.core.query.QueryWrapper; +import com.thing.common.core.web.response.PageData; +import com.thing.common.orm.service.impl.BaseServiceImpl; +import com.thing.tools.codegenerator.mapper.FieldTypeMapper; +import com.thing.tools.codegenerator.entity.FieldTypeEntity; +import com.thing.tools.codegenerator.service.FieldTypeService; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * 字段类型管理 + * + * @author Mark sunlightcs@gmail.com + */ +@Service +public class FieldTypeServiceImpl extends BaseServiceImpl implements FieldTypeService { + + public QueryWrapper getWrapper(Map params){ + String attrType = (String)params.get("attrType"); + String columnType = (String)params.get("columnType"); + + QueryWrapper wrapper = new QueryWrapper(); + wrapper.like("attr_type", attrType, StringUtils.isNotEmpty(attrType)); + wrapper.like("column_type", columnType, StringUtils.isNotEmpty(columnType)); + + return wrapper; + } + + @Override + public PageData page(Map params) { + return getPageData(params); + } + + @Override + public Map getMap() { + List list = mapper.selectAll(); + Map map = new LinkedHashMap<>(list.size()); + for(FieldTypeEntity entity : list){ + map.put(entity.getColumnType().toLowerCase(), entity); + } + return map; + } + + @Override + public Set getPackageListByTableId(Long tableId) { + return mapper.getPackageListByTableId(tableId); + } + +} \ No newline at end of file diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/impl/GeneratorServiceImpl.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/impl/GeneratorServiceImpl.java new file mode 100644 index 0000000..aef0271 --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/impl/GeneratorServiceImpl.java @@ -0,0 +1,342 @@ +package com.thing.tools.codegenerator.service.impl; + +import cn.hutool.core.io.FileUtil; +import com.mybatisflex.core.keygen.impl.SnowFlakeIDKeyGenerator; + +import com.mybatisflex.core.query.QueryWrapper; +import com.thing.common.core.constants.Constant; +import com.thing.common.core.exception.SysException; +import com.thing.common.core.utils.DateTimeUtils; +import com.thing.sys.biz.service.SysParamsService; +import com.thing.tools.codegenerator.config.DataSourceInfo; +import com.thing.tools.codegenerator.mapper.GeneratorMenuMapper; +import com.thing.tools.codegenerator.entity.*; +import com.thing.tools.codegenerator.service.*; +import com.thing.tools.codegenerator.utils.DbUtils; +import com.thing.tools.codegenerator.utils.GenUtils; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.File; +import java.sql.SQLException; +import java.util.*; +import java.util.stream.Collectors; + +import javax.sql.DataSource; + +/** + * 代码生成 + * + * @author Mark sunlightcs@gmail.com + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class GeneratorServiceImpl implements GeneratorService { + private final TableInfoService tableInfoService; + private final TableFieldService tableFieldService; + private final DataSourceService datasourceService; + private final FieldTypeService fieldTypeService; + private final BaseClassService baseClassService; + private final TemplateService templateService; + private final SysParamsService sysParamsService; + private final GeneratorMenuMapper generatorMenuMapper; + private final DataSource dataSource; + + @Override + public DataSourceInfo getDataSourceInfo(Long datasourceId) { + //初始化配置信息 + DataSourceInfo info = null; + if (datasourceId.intValue() == 0) { + try { + info = new DataSourceInfo(dataSource.getConnection()); + } catch (SQLException e) { + log.error("connect error: ", e); + } + } else { + info = new DataSourceInfo(datasourceService.getById(datasourceId)); + } + + return info; + } + + + @Override + public void datasourceTable(TableInfoEntity tableInfo) { + //初始化配置信息 + DataSourceInfo info = getDataSourceInfo(tableInfo.getDatasourceId()); + + TableInfoEntity table = tableInfoService.getByTableName(tableInfo.getTableName()); + //表存在 + if(table != null){ + throw new SysException(tableInfo.getTableName() + "数据表已存在"); + } + + table = DbUtils.getTablesInfo(info, tableInfo.getTableName()); + + //代码生成器参数 + GenParam param = sysParamsService.getValueObject(Constant.DEV_TOOLS_PARAM_KEY, GenParam.class); + + //保存表信息 + assert table != null; + table.setPackageName(param.getPackageName()); + table.setVersion(param.getVersion()); + table.setAuthor(param.getAuthor()); + table.setEmail(param.getEmail()); + table.setBackendPath(param.getBackendPath()); + table.setFrontendPath(param.getFrontendPath()); + table.setCreateDate(System.currentTimeMillis()); + tableInfoService.save(table); + + //获取原生列数据 + List tableFieldList = DbUtils.getTableColumns(info, table.getId(), tableInfo.getTableName()); + //初始化列数据 + initFieldList(tableFieldList); + //批量保存列数据 + tableFieldService.saveBatch(tableFieldList); + + try { + //释放数据源 + info.getConnection().close(); + }catch (SQLException e){ + log.error(e.getMessage()); + } + } + + @Override + public void updateTableField(Long tableId, List tableFieldList){ + //删除旧列信息 + tableFieldService.deleteBatchTableIds(new Long[]{tableId}); + + //保存新列数据 + int sort = 0; + for(TableFieldEntity tableField : tableFieldList){ + tableField.setSort(sort++); + tableFieldService.save(tableField); + } + + } + + /** + * 初始化列数据 + */ + private void initFieldList(List tableFieldList){ + //字段类型、属性类型映射 + Map fieldTypeMap = fieldTypeService.getMap(); + int index = 0; + for(TableFieldEntity tableField : tableFieldList){ + tableField.setAttrName(StringUtils.uncapitalize(GenUtils.columnToJava(tableField.getColumnName()))); + //获取字段对应的类型 + FieldTypeEntity fieldTypeMapping = fieldTypeMap.get(tableField.getColumnType().toLowerCase()); + if(fieldTypeMapping == null){ + //没找到对应的类型,则为Object类型 + tableField.setAttrType("Object"); + }else { + tableField.setAttrType(fieldTypeMapping.getAttrType()); + tableField.setPackageName(fieldTypeMapping.getPackageName()); + } + + tableField.setList(true); + tableField.setForm(true); + + tableField.setQueryType("="); + tableField.setFormType("text"); + + tableField.setSort(index++); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void generatorCode(TableInfoEntity tableInfo) { + //删除旧表信息 + tableInfoService.deleteByTableName(tableInfo.getTableName()); + //删除旧列信息 + tableFieldService.deleteByTableName(tableInfo.getTableName()); + + //保存新表信息 + tableInfoService.save(tableInfo); + //保存新列信息 + tableFieldService.saveBatch(tableInfo.getFields()); + + //数据模型 + Map dataModel = new HashMap<>(); + //项目信息 + dataModel.put("package", tableInfo.getPackageName()); + dataModel.put("packagePath", tableInfo.getPackageName().replace(".", File.separator)); + dataModel.put("version", tableInfo.getVersion()); + dataModel.put("moduleName", tableInfo.getModuleName()); + + String subModuleName = tableInfo.getSubModuleName(); + if(StringUtils.isBlank(subModuleName)){ + subModuleName = null; + } + dataModel.put("subModuleName", subModuleName); + dataModel.put("backendPath", tableInfo.getBackendPath()); + dataModel.put("frontendPath", tableInfo.getFrontendPath()); + //开发者信息 + dataModel.put("author", tableInfo.getAuthor()); + dataModel.put("email", tableInfo.getEmail()); + dataModel.put("datetime", DateTimeUtils.format(new Date(), DateTimeUtils.DATE_TIME_PATTERN_STR)); + dataModel.put("date", DateTimeUtils.format(new Date(), DateTimeUtils.DATE_PATTERN_STR)); + //表信息 + dataModel.put("tableName", tableInfo.getTableName()); + dataModel.put("tableComment", tableInfo.getTableComment()); + dataModel.put("ClassName", tableInfo.getClassName()); + dataModel.put("className", StringUtils.uncapitalize(tableInfo.getClassName())); + dataModel.put("classname", tableInfo.getClassName().toLowerCase()); + dataModel.put("columnList", tableInfo.getFields()); + //是否包含tenant_code,用于模板判断是否需要@DataFilter + dataModel.put("needDataFilter", tableInfo.getFields() != null && tableInfo.getFields().stream().anyMatch(item -> StringUtils.equals(item.getColumnName(), "tenant_code"))); + + //主键 + for(TableFieldEntity tableField : tableInfo.getFields()){ + if(tableField.isPk()){ + dataModel.put("pk", tableField); + break; + } + } + + //导入的包列表 + Set imports = fieldTypeService.getPackageListByTableId(tableInfo.getId()); + //过滤为空的数据 + imports = imports.stream().filter(StringUtils::isNotBlank).collect(Collectors.toSet()); + dataModel.put("imports", imports); + + //基类 + if(tableInfo.getBaseclassId() != null){ + QueryWrapper queryWrapper = QueryWrapper.create().eq(BaseClassEntity::getId, tableInfo.getBaseclassId()); + BaseClassEntity baseClassEntity = baseClassService.getMapper().selectOneByQuery(queryWrapper); + baseClassEntity.setPackageName(GenUtils.getTemplateContent(baseClassEntity.getPackageName(), dataModel)); + dataModel.put("baseClassEntity", baseClassEntity); + } + + //获取模板 + List templateList = templateService.list(); + + //渲染模板并输出 + for(TemplateEntity template : templateList){ + dataModel.put("templateName", template.getName()); + String content = GenUtils.getTemplateContent(template.getContent(), dataModel); + String path = GenUtils.getTemplateContent(template.getPath(), dataModel) + File.separator + + GenUtils.getTemplateContent(template.getFileName(), dataModel); + FileUtil.writeUtf8String(content, path); + System.out.println(path); + } + } + + @Override + public void generatorMenu(MenuEntity menu) { + Map params = new HashMap<>(); + params.put("pid", menu.getPid()); + params.put("name", menu.getName()); + params.put("icon", menu.getIcon()); + params.put("type", 0); + int sort = 0; + params.put("sort", sort); + params.put("url", menu.getModuleName() + "/" + menu.getClassName().toLowerCase()); + params.put("now", new Date()); + //权限标识 + String permission = menu.getModuleName() + ":" + menu.getClassName().toLowerCase(); + //菜单id + Long menuId = new SnowFlakeIDKeyGenerator().nextId(); + + //菜单 + params.put("id", menuId); + generatorMenuMapper.generatorMenu(params); + params.put("language", "en-US"); + generatorMenuMapper.generatorMenuLanguage(params); + params.put("language", "zh-CN"); + generatorMenuMapper.generatorMenuLanguage(params); + params.put("language", "zh-TW"); + generatorMenuMapper.generatorMenuLanguage(params); + + //查看 + params.put("id", new SnowFlakeIDKeyGenerator().nextId()); + params.put("pid", menuId); + params.put("permissions", permission + ":page," + permission + ":info"); + params.put("icon", null); + params.put("type", 1); + params.put("sort", sort); + generatorMenuMapper.generatorMenu(params); + params.put("name", "View"); + params.put("language", "en-US"); + generatorMenuMapper.generatorMenuLanguage(params); + params.put("name", "查看"); + params.put("language", "zh-CN"); + generatorMenuMapper.generatorMenuLanguage(params); + params.put("name", "查看"); + params.put("language", "zh-TW"); + generatorMenuMapper.generatorMenuLanguage(params); + + //新增 + params.put("id", new SnowFlakeIDKeyGenerator().nextId()); + params.put("pid", menuId); + params.put("permissions", permission + ":save"); + params.put("sort", ++sort); + generatorMenuMapper.generatorMenu(params); + params.put("name", "Add"); + params.put("language", "en-US"); + generatorMenuMapper.generatorMenuLanguage(params); + params.put("name", "新增"); + params.put("language", "zh-CN"); + generatorMenuMapper.generatorMenuLanguage(params); + params.put("name", "新增"); + params.put("language", "zh-TW"); + generatorMenuMapper.generatorMenuLanguage(params); + + //修改 + params.put("id", new SnowFlakeIDKeyGenerator().nextId()); + params.put("pid", menuId); + params.put("permissions", permission + ":update"); + params.put("sort", ++sort); + generatorMenuMapper.generatorMenu(params); + params.put("name", "Edit"); + params.put("language", "en-US"); + generatorMenuMapper.generatorMenuLanguage(params); + params.put("name", "修改"); + params.put("language", "zh-CN"); + generatorMenuMapper.generatorMenuLanguage(params); + params.put("name", "修改"); + params.put("language", "zh-TW"); + generatorMenuMapper.generatorMenuLanguage(params); + + //删除 + params.put("id", new SnowFlakeIDKeyGenerator().nextId()); + params.put("pid", menuId); + params.put("permissions", permission + ":delete"); + params.put("sort", ++sort); + generatorMenuMapper.generatorMenu(params); + params.put("name", "Delete"); + params.put("language", "en-US"); + generatorMenuMapper.generatorMenuLanguage(params); + params.put("name", "删除"); + params.put("language", "zh-CN"); + generatorMenuMapper.generatorMenuLanguage(params); + params.put("name", "删除"); + params.put("language", "zh-TW"); + generatorMenuMapper.generatorMenuLanguage(params); + + //导出 + params.put("id", new SnowFlakeIDKeyGenerator().nextId()); + params.put("pid", menuId); + params.put("permissions", permission + ":export"); + params.put("sort", ++sort); + generatorMenuMapper.generatorMenu(params); + params.put("name", "Export"); + params.put("language", "en-US"); + generatorMenuMapper.generatorMenuLanguage(params); + params.put("name", "导出"); + params.put("language", "zh-CN"); + generatorMenuMapper.generatorMenuLanguage(params); + params.put("name", "導出"); + params.put("language", "zh-TW"); + generatorMenuMapper.generatorMenuLanguage(params); + } + +} \ No newline at end of file diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/impl/TableFieldServiceImpl.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/impl/TableFieldServiceImpl.java new file mode 100644 index 0000000..7901026 --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/impl/TableFieldServiceImpl.java @@ -0,0 +1,43 @@ + + +package com.thing.tools.codegenerator.service.impl; + +import com.mybatisflex.core.query.QueryWrapper; +import com.thing.common.orm.service.impl.BaseServiceImpl; +import com.thing.tools.codegenerator.mapper.TableFieldMapper; +import com.thing.tools.codegenerator.entity.TableFieldEntity; +import com.thing.tools.codegenerator.service.TableFieldService; + +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; + +/** + * 表 + * + * @author Mark sunlightcs@gmail.com + */ +@Service +public class TableFieldServiceImpl extends BaseServiceImpl implements TableFieldService { + + @Override + public QueryWrapper getWrapper(Map params) { + return null; + } + + @Override + public List getByTableName(String tableName) { + return mapper.getByTableName(tableName); + } + + @Override + public void deleteByTableName(String tableName) { + mapper.deleteByTableName(tableName); + } + + @Override + public void deleteBatchTableIds(Long[] tableIds) { + mapper.deleteBatchTableIds(tableIds); + } +} \ No newline at end of file diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/impl/TableInfoServiceImpl.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/impl/TableInfoServiceImpl.java new file mode 100644 index 0000000..3ba55c1 --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/impl/TableInfoServiceImpl.java @@ -0,0 +1,58 @@ +package com.thing.tools.codegenerator.service.impl; + +import com.mybatisflex.core.query.QueryWrapper; +import com.thing.common.core.web.response.PageData; +import com.thing.common.orm.service.impl.BaseServiceImpl; +import com.thing.tools.codegenerator.mapper.TableInfoMapper; +import com.thing.tools.codegenerator.entity.TableInfoEntity; +import com.thing.tools.codegenerator.service.TableFieldService; +import com.thing.tools.codegenerator.service.TableInfoService; + +import lombok.RequiredArgsConstructor; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.util.Map; + +/** + * 表 + * + * @author Mark sunlightcs@gmail.com + */ +@Service +@RequiredArgsConstructor +public class TableInfoServiceImpl extends BaseServiceImpl implements TableInfoService { + private final TableFieldService tableFieldService; + + @Override + public PageData page(Map params) { + return getPageData(params); + } + + public QueryWrapper getWrapper(Map params){ + String tableName = (String)params.get("tableName"); + QueryWrapper wrapper = new QueryWrapper(); + wrapper.like( "table_name", tableName, StringUtils.isNotEmpty(tableName)); + return wrapper; + } + + @Override + public TableInfoEntity getByTableName(String tableName) { + return mapper.getByTableName(tableName); + } + + @Override + public void deleteByTableName(String tableName) { + mapper.deleteByTableName(tableName); + } + + @Override + public void deleteBatchIds(Long[] ids) { + //删除表 + batchDelete(ids); + + //删除列 + tableFieldService.deleteBatchTableIds(ids); + } +} \ No newline at end of file diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/impl/TemplateServiceImpl.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/impl/TemplateServiceImpl.java new file mode 100644 index 0000000..01525e1 --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/service/impl/TemplateServiceImpl.java @@ -0,0 +1,51 @@ +package com.thing.tools.codegenerator.service.impl; + +import com.mybatisflex.core.query.QueryWrapper; +import com.thing.common.core.web.response.PageData; +import com.thing.common.orm.service.impl.BaseServiceImpl; +import com.thing.tools.codegenerator.mapper.TemplateMapper; +import com.thing.tools.codegenerator.entity.TemplateEntity; +import com.thing.tools.codegenerator.service.TemplateService; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 模板管理 + * + * @author Mark sunlightcs@gmail.com + */ +@Service +public class TemplateServiceImpl extends BaseServiceImpl + implements TemplateService { + + @Override + public QueryWrapper getWrapper(Map params) { + String name = (String) params.get("name"); + QueryWrapper wrapper = new QueryWrapper(); + wrapper.like("name", name, StringUtils.isNotEmpty(name)); + return wrapper; + } + + @Override + public PageData page(Map params) { + return getPageData(params); + } + + @Override + public List list() { + return mapper.selectListByQuery(QueryWrapper.create().eq(TemplateEntity::getStatus, 0)); + } + + @Override + public void updateStatusBatch(Long[] ids, int status) { + Map map = new HashMap<>(2); + map.put("ids", ids); + map.put("status", status); + mapper.updateStatusBatch(map); + } +} diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/utils/DbType.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/utils/DbType.java new file mode 100644 index 0000000..f00105f --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/utils/DbType.java @@ -0,0 +1,28 @@ + + +package com.thing.tools.codegenerator.utils; + +/** + * 数据库类型 + * + * @author Mark sunlightcs@gmail.com + */ +public enum DbType { + /** + * 支持MySQL、Oracle、SQLServer、PostgreSQL + */ + MySQL("com.mysql.cj.jdbc.Driver"), + Oracle("oracle.jdbc.driver.OracleDriver"), + SQLServer("com.microsoft.sqlserver.jdbc.SQLServerDriver"), + PostgreSQL("org.postgresql.Driver"); + + private final String driverClass; + + DbType(String driverClass) { + this.driverClass = driverClass; + } + + public String getDriverClass() { + return driverClass; + } +} \ No newline at end of file diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/utils/DbUtils.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/utils/DbUtils.java new file mode 100644 index 0000000..f47d711 --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/utils/DbUtils.java @@ -0,0 +1,148 @@ + + +package com.thing.tools.codegenerator.utils; + +import com.thing.tools.codegenerator.config.DataSourceInfo; +import com.thing.tools.codegenerator.config.query.AbstractQuery; +import com.thing.tools.codegenerator.entity.TableFieldEntity; +import com.thing.tools.codegenerator.entity.TableInfoEntity; + +import lombok.extern.slf4j.Slf4j; + +import org.apache.commons.lang3.StringUtils; + +import java.sql.*; +import java.util.ArrayList; +import java.util.List; + +/** + * DB工具类 + * + * @author Mark sunlightcs@gmail.com + */ +@Slf4j +public class DbUtils { + private static final int CONNECTION_TIMEOUTS_SECONDS = 6; + + /** + * 获得数据库连接 + * + * @param info + * @return + * @throws ClassNotFoundException + * @throws SQLException + */ + public static Connection getConnection(DataSourceInfo info) throws ClassNotFoundException, SQLException { + DriverManager.setLoginTimeout(CONNECTION_TIMEOUTS_SECONDS); + + Class.forName(info.getDbType().getDriverClass()); + + return DriverManager.getConnection(info.getConnUrl(), info.getUsername(), info.getPassword()); + /* 使用oracle时放开 + Connection connection = DriverManager.getConnection(info.getConnUrl(), info.getUsername(), info.getPassword()); + if(info.getDbType() == DbType.Oracle){ + ((OracleConnection)connection).setRemarksReporting(true); + } + + return connection;*/ + } + + + /** + * 获取数据库表信息 + */ + public static TableInfoEntity getTablesInfo(DataSourceInfo info, String tableName) { + try { + AbstractQuery dbQuery = info.getDbQuery(); + + //查询数据 + PreparedStatement preparedStatement = info.getConnection().prepareStatement(dbQuery.tablesSql(tableName)); + ResultSet rs = preparedStatement.executeQuery(); + if (rs.next()) { + TableInfoEntity tableInfo = new TableInfoEntity(); + tableInfo.setTableName(rs.getString(dbQuery.tableName())); + tableInfo.setClassName(GenUtils.columnToJava(tableInfo.getTableName())); + tableInfo.setTableComment(rs.getString(dbQuery.tableComment())); + tableInfo.setDatasourceId(info.getId()); + return tableInfo; + } + }catch (Exception e){ + e.printStackTrace(); + } + + return null; + } + + /** + * 获取所有的数据库表 + */ + public static List getTablesInfoList(DataSourceInfo info) { + List tableInfoList = new ArrayList<>(); + try { + AbstractQuery dbQuery = info.getDbQuery(); + + //查询数据 + PreparedStatement preparedStatement = info.getConnection().prepareStatement(dbQuery.tablesSql(null)); + ResultSet rs = preparedStatement.executeQuery(); + while (rs.next()) { + TableInfoEntity tableInfo = new TableInfoEntity(); + tableInfo.setTableName(rs.getString(dbQuery.tableName())); + tableInfo.setClassName(GenUtils.columnToJava(tableInfo.getTableName())); + tableInfo.setTableComment(rs.getString(dbQuery.tableComment())); + tableInfo.setDatasourceId(info.getId()); + tableInfoList.add(tableInfo); + } + + info.getConnection().close(); + }catch (Exception e){ + e.printStackTrace(); + } + + return tableInfoList; + } + + + /** + * 获取表的列属性 + * + * @param info 数据库配置文件 + * @param tableName 表名 + */ + public static List getTableColumns(DataSourceInfo info, Long tableId, String tableName) { + List tableFieldList = new ArrayList<>(); + + try { + AbstractQuery dbQuery = info.getDbQuery(); + String tableFieldsSql = dbQuery.tableFieldsSql(); + if (info.getDbType() == DbType.Oracle) { + DatabaseMetaData md = info.getConnection().getMetaData(); + tableFieldsSql = String.format(tableFieldsSql.replace("#schema", md.getUserName()), tableName); + } else { + tableFieldsSql = String.format(tableFieldsSql, tableName); + } + PreparedStatement preparedStatement = info.getConnection().prepareStatement(tableFieldsSql); + ResultSet rs = preparedStatement.executeQuery(); + while (rs.next()) { + TableFieldEntity field = new TableFieldEntity(); + field.setTableId(tableId); + field.setTableName(tableName); + field.setColumnName(rs.getString(dbQuery.fieldName())); + String columnType = rs.getString(dbQuery.fieldType()); + if(columnType.indexOf(" ") != -1){ + columnType = columnType.substring(0, columnType.indexOf(" ")); + } + field.setColumnType(columnType); + field.setColumnComment(rs.getString(dbQuery.fieldComment())); + String key = rs.getString(dbQuery.fieldKey()); + field.setPk(StringUtils.isNotBlank(key) && "PRI".equals(key.toUpperCase())); + + tableFieldList.add(field); + } + }catch (Exception e){ + e.printStackTrace(); + } + + return tableFieldList; + } + +} \ No newline at end of file diff --git a/tools/code-generator/src/main/java/com/thing/tools/codegenerator/utils/GenUtils.java b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/utils/GenUtils.java new file mode 100644 index 0000000..c77e696 --- /dev/null +++ b/tools/code-generator/src/main/java/com/thing/tools/codegenerator/utils/GenUtils.java @@ -0,0 +1,56 @@ + + +package com.thing.tools.codegenerator.utils; + +import cn.hutool.core.map.MapUtil; + +import com.thing.common.core.exception.SysException; + +import freemarker.template.Template; + +import org.apache.commons.lang3.text.WordUtils; +import org.apache.tomcat.util.http.fileupload.IOUtils; + +import java.io.StringReader; +import java.io.StringWriter; +import java.util.Map; + +/** + * 代码生成器工具类 + * + * @author Mark sunlightcs@gmail.com + */ +public class GenUtils { + + /** + * 列名转换成Java属性名 + */ + public static String columnToJava(String columnName) { + return WordUtils.capitalizeFully(columnName, new char[]{'_'}).replace("_", ""); + } + + /** + * 获取模板渲染后的内容 + * @param content 模板内容 + * @param dataModel 数据模型 + */ + public static String getTemplateContent(String content, Map dataModel) { + if(MapUtil.isEmpty(dataModel)){ + return content; + } + StringReader reader = new StringReader(content); + StringWriter sw = new StringWriter(); + try { + //渲染模板 + String templateName = dataModel.getOrDefault("templateName", "generator").toString(); + Template template = new Template(templateName, reader, null, "utf-8"); + template.process(dataModel, sw); + } catch (Exception e) { + throw new SysException("渲染模板失败,请检查模板语法", e); + } + content = sw.toString(); + IOUtils.closeQuietly(reader); + IOUtils.closeQuietly(sw); + return content; + } +} \ No newline at end of file diff --git a/tools/code-generator/src/main/resources/mapper/codegenerator/FieldTypeMapper.xml b/tools/code-generator/src/main/resources/mapper/codegenerator/FieldTypeMapper.xml new file mode 100644 index 0000000..bb61919 --- /dev/null +++ b/tools/code-generator/src/main/resources/mapper/codegenerator/FieldTypeMapper.xml @@ -0,0 +1,13 @@ + + + + + + + + \ No newline at end of file diff --git a/tools/code-generator/src/main/resources/mapper/codegenerator/GeneratorMenuMapper.xml b/tools/code-generator/src/main/resources/mapper/codegenerator/GeneratorMenuMapper.xml new file mode 100644 index 0000000..365dda1 --- /dev/null +++ b/tools/code-generator/src/main/resources/mapper/codegenerator/GeneratorMenuMapper.xml @@ -0,0 +1,18 @@ + + + + + + + + INSERT INTO sys_menu(id, pid, url, permissions, type, open_style, icon, sort, creator, create_date, updater, update_date) + VALUES (#{id}, #{pid}, #{url}, #{permissions}, #{type}, 0, #{icon}, #{sort}, 1067246875800000001, #{now}, 1067246875800000001, #{now}) + + + + + INSERT INTO sys_language(table_name, table_id, field_name, field_value, language) + VALUES ('sys_menu', #{id}, 'name', #{name}, #{language}) + + + \ No newline at end of file diff --git a/tools/code-generator/src/main/resources/mapper/codegenerator/TableFieldMapper.xml b/tools/code-generator/src/main/resources/mapper/codegenerator/TableFieldMapper.xml new file mode 100644 index 0000000..9932134 --- /dev/null +++ b/tools/code-generator/src/main/resources/mapper/codegenerator/TableFieldMapper.xml @@ -0,0 +1,20 @@ + + + + + + + + + delete from gen_table_field where table_name = #{value} + + + + delete from gen_table_field where table_id in + + #{tableId} + + + \ No newline at end of file diff --git a/tools/code-generator/src/main/resources/mapper/codegenerator/TableInfoMapper.xml b/tools/code-generator/src/main/resources/mapper/codegenerator/TableInfoMapper.xml new file mode 100644 index 0000000..5a1af5a --- /dev/null +++ b/tools/code-generator/src/main/resources/mapper/codegenerator/TableInfoMapper.xml @@ -0,0 +1,14 @@ + + + + + + + + + delete from gen_table_info where table_name = #{value} + + + \ No newline at end of file diff --git a/tools/code-generator/src/main/resources/mapper/codegenerator/TemplateMapper.xml b/tools/code-generator/src/main/resources/mapper/codegenerator/TemplateMapper.xml new file mode 100644 index 0000000..302072f --- /dev/null +++ b/tools/code-generator/src/main/resources/mapper/codegenerator/TemplateMapper.xml @@ -0,0 +1,13 @@ + + + + + + + update gen_template set status = #{status} where id in + + #{id} + + + + \ No newline at end of file diff --git a/tools/pom.xml b/tools/pom.xml new file mode 100644 index 0000000..fa0144c --- /dev/null +++ b/tools/pom.xml @@ -0,0 +1,23 @@ + + + 4.0.0 + + com.thing + thingbi + 5.1 + + pom + + + code-generator + system-monitor + + + tools + ThingBI Server tools + + ${basedir}/.. + + diff --git a/tools/system-monitor/pom.xml b/tools/system-monitor/pom.xml new file mode 100644 index 0000000..2484cd8 --- /dev/null +++ b/tools/system-monitor/pom.xml @@ -0,0 +1,45 @@ + + + 4.0.0 + + com.thing + tools + 5.1 + ../pom.xml + + + com.thing.tools + system-monitor + jar + ThingBI Server Modules system-monitor + + + 17 + 17 + UTF-8 + + + + + + org.springframework.boot + spring-boot-starter-actuator + + + + + io.micrometer + micrometer-core + + + + + io.micrometer + micrometer-registry-prometheus + + + + + \ No newline at end of file diff --git a/tools/system-monitor/src/main/java/com/thing/tools/monitor/config/.gitkeep b/tools/system-monitor/src/main/java/com/thing/tools/monitor/config/.gitkeep new file mode 100644 index 0000000..e69de29