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 0000000..dea688e Binary files /dev/null and b/application/src/main/resources/static/favicon.ico differ 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