This commit is contained in:
kk
2026-07-07 18:05:54 +08:00
commit d4ef46bf97
743 changed files with 159169 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
FROM bladex/alpine-java:openjdk17_cn_slim
LABEL maintainer="bladejava@qq.com"
RUN mkdir -p /blade/admin
WORKDIR /blade/admin
EXPOSE 7002
COPY ./target/blade-admin.jar ./app.jar
ENTRYPOINT ["java", "--add-opens", "java.base/java.lang=ALL-UNNAMED", "--add-opens", "java.base/java.lang.reflect=ALL-UNNAMED", "-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar"]
CMD ["--spring.profiles.active=test"]

View File

@@ -0,0 +1,21 @@
## SDK下载
#### Java SDK 下载
下载SDK: https://open-doc.dingtalk.com/microapp/faquestions/vzbp02
## 配置项
#### bootstrap.yml
```
# 监控的相关配置
monitor:
ding-talk:
enabled: false
# 用于自定义域名,默认会自动填充为 http://ip:port
link: http://localhost:${server.port}
# 钉钉配置的令牌
access-token: xxx
# 如果采用密钥形式,需要添加,否则需要去掉该参数
secret: xxx
```

View File

@@ -0,0 +1,109 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>blade-ops</artifactId>
<groupId>org.springblade</groupId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>blade-admin</artifactId>
<name>${project.artifactId}</name>
<packaging>jar</packaging>
<dependencies>
<!--Blade-->
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-common</artifactId>
<exclusions>
<exclusion>
<groupId>org.springblade</groupId>
<artifactId>blade-core-launch</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-core-launch</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-starter-prometheus</artifactId>
</dependency>
<!-- Nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<exclusions>
<exclusion>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<exclusions>
<exclusion>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
</dependency>
<!--Admin-Server-->
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
</dependency>
<!--Security-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!--<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
</dependency>-->
<!--Taobao-Sdk-->
<dependency>
<groupId>com.taobao</groupId>
<artifactId>taobao-sdk</artifactId>
<version>20201116</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<configuration>
<skip>${docker.fabric.skip}</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,48 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.admin;
import de.codecentric.boot.admin.server.config.EnableAdminServer;
import org.springblade.core.launch.BladeApplication;
import org.springblade.core.launch.constant.AppConstant;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* admin启动器
*
* @author Chill
*/
@EnableAdminServer
@EnableDiscoveryClient
@SpringBootApplication
public class AdminApplication {
public static void main(String[] args) {
BladeApplication.run(AppConstant.APPLICATION_ADMIN_NAME, AdminApplication.class, args);
}
}

View File

@@ -0,0 +1,41 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.admin.config;
import org.springblade.admin.dingtalk.MonitorProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* 启动器
*
* @author Chill
*/
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(MonitorProperties.class)
public class AdminConfiguration {
}

View File

@@ -0,0 +1,61 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: DreamLu (596392912@qq.com)
*/
package org.springblade.admin.config;
import de.codecentric.boot.admin.server.domain.entities.InstanceRepository;
import org.springblade.admin.dingtalk.DingTalkNotifier;
import org.springblade.admin.dingtalk.DingTalkService;
import org.springblade.admin.dingtalk.MonitorProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.web.reactive.function.client.WebClient;
/**
* 钉钉自动配置
*
* @author L.cm
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(value = "monitor.ding-talk.enabled", havingValue = "true")
public class DingTalkConfiguration {
@Bean
public DingTalkService dingTalkService(MonitorProperties properties,
WebClient.Builder builder) {
return new DingTalkService(properties, builder.build());
}
@Bean
public DingTalkNotifier dingTalkNotifier(MonitorProperties properties,
DingTalkService dingTalkService,
InstanceRepository repository,
Environment environment) {
return new DingTalkNotifier(dingTalkService, properties, environment, repository);
}
}

View File

@@ -0,0 +1,96 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: DreamLu (596392912@qq.com)
*/
package org.springblade.admin.config;
import de.codecentric.boot.admin.server.config.AdminServerProperties;
import org.springblade.admin.security.InternalAuthorizationManager;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.authentication.RedirectServerAuthenticationSuccessHandler;
import java.net.URI;
/**
* 监控安全配置
*
* @author L.cm
*/
@EnableWebFluxSecurity
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(AdminServerProperties.class)
public class SecurityConfiguration {
private final String contextPath;
public SecurityConfiguration(AdminServerProperties adminServerProperties) {
this.contextPath = adminServerProperties.getContextPath();
}
@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
// @formatter:off
RedirectServerAuthenticationSuccessHandler successHandler = new RedirectServerAuthenticationSuccessHandler();
successHandler.setLocation(URI.create(contextPath + "/"));
return http
// 明确调用headers()方法进行配置
.headers(headers -> headers
// 禁用frameOptions
.frameOptions(ServerHttpSecurity.HeaderSpec.FrameOptionsSpec::disable)
)
// 配置授权规则
.authorizeExchange(exchanges -> exchanges
.pathMatchers(
contextPath + "/assets/**",
contextPath + "/login",
contextPath + "/v1/agent/**",
contextPath + "/v1/catalog/**",
contextPath + "/v1/health/**"
).permitAll()
.pathMatchers(contextPath + "/actuator", contextPath + "/actuator/**")
.access(new InternalAuthorizationManager())
.anyExchange().authenticated()
)
// 配置表单登录
.formLogin(formLogin -> formLogin
.loginPage(contextPath + "/login")
.authenticationSuccessHandler(successHandler)
)
// 配置登出
.logout(logout -> logout
.logoutUrl(contextPath + "/logout")
)
// 禁用HTTP Basic认证
.httpBasic(ServerHttpSecurity.HttpBasicSpec::disable)
// 禁用CSRF
.csrf(ServerHttpSecurity.CsrfSpec::disable)
.build();
// @formatter:on
}
}

View File

@@ -0,0 +1,114 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: DreamLu (596392912@qq.com)
*/
package org.springblade.admin.dingtalk;
import de.codecentric.boot.admin.server.domain.entities.Instance;
import de.codecentric.boot.admin.server.domain.entities.InstanceRepository;
import de.codecentric.boot.admin.server.domain.events.InstanceEvent;
import de.codecentric.boot.admin.server.domain.events.InstanceStatusChangedEvent;
import de.codecentric.boot.admin.server.domain.values.Registration;
import de.codecentric.boot.admin.server.domain.values.StatusInfo;
import de.codecentric.boot.admin.server.notify.AbstractEventNotifier;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.env.Environment;
import org.springframework.lang.NonNull;
import reactor.core.publisher.Mono;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
/**
* 服务上下线告警
*
* <p>
* 注意AbstractStatusChangeNotifier 这个事件有毛病
* </p>
*
* @author L.cm
*/
@Slf4j
public class DingTalkNotifier extends AbstractEventNotifier {
private final DingTalkService dingTalkService;
private final MonitorProperties properties;
private final Environment environment;
public static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
public DingTalkNotifier(DingTalkService dingTalkService, MonitorProperties properties,
Environment environment, InstanceRepository repository) {
super(repository);
this.dingTalkService = dingTalkService;
this.properties = properties;
this.environment = environment;
}
@NonNull
@Override
protected Mono<Void> doNotify(@NonNull InstanceEvent event, @NonNull Instance instance) {
if (event instanceof InstanceStatusChangedEvent) {
// 构造请求结构
return createAndPushMsg(event, instance);
}
return Mono.empty();
}
private Mono<Void> createAndPushMsg(InstanceEvent event, Instance instance) {
Registration registration = instance.getRegistration();
// 服务名
String appName = registration.getName();
// 服务地址
String serviceUrl = registration.getServiceUrl();
StatusInfo status = instance.getStatusInfo();
// 时间
LocalDateTime localDateTime = LocalDateTime.ofInstant(event.getTimestamp(), ZoneId.systemDefault());
MonitorProperties.DingTalk dingTalk = properties.getDingTalk();
String title = dingTalk.getService().getTitle();
String message = "## **" + title + "**\n" +
"#### **【服务】** " + appName + "\n" +
"#### **【环境】** " + environment.getActiveProfiles()[0] + "\n" +
"#### **【地址】** " + serviceUrl + "\n" +
"#### **【状态】** " + statusCn(status) + "\n" +
"#### **【时间】** " + DATETIME_FORMATTER.format(localDateTime) + "\n" +
"#### **【详情】** " + dingTalk.getLink() + "\n";
return dingTalkService.pushMsg(title, message);
}
private String statusCn(StatusInfo status) {
if (status.isUp()) {
return "应用上线IS UP";
} else if (status.isDown()) {
return "应用宕机IS DOWN";
} else if (status.isOffline()) {
return "应用掉线IS OFFLINE";
} else if (status.isUnknown()) {
return "未知状态UNKNOWN";
} else {
return "异常状态";
}
}
}

View File

@@ -0,0 +1,119 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: DreamLu (596392912@qq.com)
*/
package org.springblade.admin.dingtalk;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.util.StringUtils;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.util.UriUtils;
import reactor.core.publisher.Mono;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
/**
* 钉钉 服务
*
* @author L.cm
*/
@Slf4j
@RequiredArgsConstructor
public class DingTalkService {
private static final String DING_TALK_ROBOT_URL = "https://oapi.dingtalk.com/robot/send?access_token=";
private final MonitorProperties properties;
private final WebClient webClient;
/**
* 发送消息
*
* @param title title
* @param text 消息
*/
public Mono<Void> pushMsg(String title, String text) {
log.info("钉钉消息:[创建消息体]title:{}, text:{}", title, text);
HashMap<String, String> params = new HashMap<>(2);
params.put("title", title);
params.put("text", text);
Map<String, Object> body = new HashMap<>(2);
body.put("msgtype", "markdown");
body.put("markdown", params);
log.info("创建消息体 json{}", body);
MonitorProperties.DingTalk dingTalk = properties.getDingTalk();
String accessToken = dingTalk.getAccessToken();
if (!StringUtils.hasText(accessToken)) {
log.error("DingTalk alert config accessToken ${monitor.ding-talk.access-token} is blank.");
return Mono.empty();
}
String urlString = DING_TALK_ROBOT_URL + dingTalk.getAccessToken();
// 有私钥要签名
String secret = dingTalk.getSecret();
if (StringUtils.hasText(secret)) {
long timestamp = System.currentTimeMillis();
urlString += String.format("&timestamp=%s&sign=%s", timestamp, getSign(secret, timestamp));
}
return webClient.post()
.uri(URI.create(urlString))
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(body))
.retrieve()
.bodyToMono(String.class)
.doOnSuccess((result) -> log.info("钉钉消息:[消息返回]result:{}", result))
.then();
}
private static String getSign(String secret, long timestamp) {
String stringToSign = timestamp + "\n" + secret;
byte[] hmacSha256Bytes = digestHmac(stringToSign, secret);
return UriUtils.encode(Base64.getEncoder().encodeToString(hmacSha256Bytes), StandardCharsets.UTF_8);
}
public static byte[] digestHmac(String data, String key) {
SecretKey secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
try {
Mac mac = Mac.getInstance(secretKey.getAlgorithm());
mac.init(secretKey);
return mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
throw new RuntimeException(e.getMessage());
}
}
}

View File

@@ -0,0 +1,76 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: DreamLu (596392912@qq.com)
*/
package org.springblade.admin.dingtalk;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
/**
* 监控配置
*
* @author L.cm
*/
@Getter
@Setter
@RefreshScope
@ConfigurationProperties("monitor")
public class MonitorProperties {
private DingTalk dingTalk = new DingTalk();
@Getter
@Setter
public static class DingTalk {
/**
* 启用钉钉告警,默认为 true
*/
private boolean enabled = false;
/**
* 钉钉机器人 token
*/
private String accessToken;
/**
* 签名:如果有 secret 则进行签名,兼容老接口
*/
private String secret;
/**
* 地址配置
*/
private String link;
private Service service = new Service();
}
@Getter
@Setter
public static class Service {
/**
* 服务 状态 title
*/
private String title = "服务状态通知";
}
}

View File

@@ -0,0 +1,84 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: DreamLu (596392912@qq.com)
*/
package org.springblade.admin.security;
import org.springblade.core.launch.utils.INetUtil;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.ReactiveAuthorizationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.server.authorization.AuthorizationContext;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.net.InetSocketAddress;
import java.util.Optional;
/**
* 内网认证管理,内网放行,外网认证
*
* @author L.cm
*/
public class InternalAuthorizationManager implements ReactiveAuthorizationManager<AuthorizationContext> {
private static final String HEADER_X_FORWARDED_FOR = "X-Forwarded-For";
@Override
public Mono<AuthorizationDecision> check(Mono<Authentication> authentication, AuthorizationContext context) {
return Mono.just(getAuthorizationDecision(context));
}
private static AuthorizationDecision getAuthorizationDecision(AuthorizationContext context) {
return new AuthorizationDecision(isInternalNet(context));
}
/**
* 判断是否内网 ip 请求
*
* @param context AuthorizationContext
* @return 是否内网 ip
*/
private static boolean isInternalNet(AuthorizationContext context) {
ServerHttpRequest request = Optional.ofNullable(context)
.map(AuthorizationContext::getExchange)
.map(ServerWebExchange::getRequest)
.orElse(null);
if (request == null) {
return false;
}
HttpHeaders headers = request.getHeaders();
// 如果没有 X-Forwarded-For 代表为 admin 拉取
if (!headers.containsKey(HEADER_X_FORWARDED_FOR)) {
return true;
}
return Optional.of(request)
.map(ServerHttpRequest::getRemoteAddress)
.map(InetSocketAddress::getAddress)
.map(INetUtil::isInternalIp)
.orElse(false);
}
}

View File

@@ -0,0 +1,59 @@
server:
port: 7002
undertow:
threads:
# 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程
io: 16
# 阻塞任务线程池, 当执行类似servlet请求阻塞操作, undertow会从这个线程池中取得线程,它的值设置取决于系统的负载
worker: 400
# 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
buffer-size: 1024
# 是否分配的直接内存
direct-buffers: true
spring:
boot:
admin:
# 忽略服务名
discovery:
ignored-services:
- consul
- serverAddr
# 自定义UI界面
ui:
# Nginx反代后的外网地址
#public-url: http://localhost:${server.port}/
# 自定义的标题
title: BladeX Monitor
# 自定义的网址
external-views:
- label: 架构官网
url: https://bladex.cn/
order: 1
iframe: true
# 用于内网安全,判断 admin proxy
instance-proxy:
ignored-headers: "X-Forwarded-For"
# 自定义登录用户名密码
security:
user:
name: blade
password: blade
# 监控的相关配置
monitor:
ding-talk:
enabled: false
# 用于自定义域名,默认会自动填充为 http://ip:port
link: http://localhost:${server.port}
# 钉钉配置的令牌
access-token: xxx
# 如果采用密钥形式,需要添加,否则需要去掉该参数
secret:
# 关闭端点
management:
endpoints:
web:
discovery:
enabled: false

View File

@@ -0,0 +1,59 @@
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springblade</groupId>
<artifactId>blade-ops</artifactId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>blade-develop</artifactId>
<name>${project.artifactId}</name>
<packaging>jar</packaging>
<dependencies>
<!--Blade-->
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-core-boot</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-starter-develop</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-starter-swagger</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-starter-excel</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-common</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-dict-api</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-develop-api</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,45 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.develop;
import org.springblade.core.cloud.client.BladeCloudApplication;
import org.springblade.core.launch.BladeApplication;
import org.springblade.core.launch.constant.AppConstant;
/**
* Develop启动器
*
* @author Chill
*/
@BladeCloudApplication
public class DevelopApplication {
public static void main(String[] args) {
BladeApplication.run(AppConstant.APPLICATION_DEVELOP_NAME, DevelopApplication.class, args);
}
}

View File

@@ -0,0 +1,150 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.develop.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.IsAdministrator;
import org.springblade.core.tenant.annotation.NonDS;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.develop.pojo.dto.GeneratorDTO;
import org.springblade.develop.pojo.entity.Code;
import org.springblade.develop.service.ICodeService;
import org.springblade.develop.service.IGenerateService;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
/**
* 控制器
*
* @author Chill
*/
@NonDS
@RestController
@AllArgsConstructor
@IsAdministrator
@RequestMapping("/code")
@Tag(name = "代码生成", description = "代码生成")
public class CodeController extends BladeController {
private final ICodeService codeService;
private final IGenerateService generateService;
/**
* 详情
*/
@GetMapping("/detail")
@ApiOperationSupport(order = 1)
@Operation(summary = "详情", description = "传入code")
public R<Code> detail(Code code) {
Code detail = codeService.getOne(Condition.getQueryWrapper(code));
return R.data(detail);
}
/**
* 分页
*/
@GetMapping("/list")
@Parameters({
@Parameter(name = "codeName", description = "模块名", in = ParameterIn.QUERY, schema = @Schema(type = "string")),
@Parameter(name = "tableName", description = "表名", in = ParameterIn.QUERY, schema = @Schema(type = "string")),
@Parameter(name = "modelName", description = "实体名", in = ParameterIn.QUERY, schema = @Schema(type = "string"))
})
@ApiOperationSupport(order = 2)
@Operation(summary = "分页", description = "传入code")
public R<IPage<Code>> list(@Parameter(hidden = true) @RequestParam Map<String, Object> code, Query query) {
IPage<Code> pages = codeService.page(Condition.getPage(query), Condition.getQueryWrapper(code, Code.class));
return R.data(pages);
}
/**
* 新增或修改
*/
@PostMapping("/submit")
@ApiOperationSupport(order = 3)
@Operation(summary = "新增或修改", description = "传入code")
public R submit(@Valid @RequestBody Code code) {
return R.status(codeService.submit(code));
}
/**
* 删除
*/
@PostMapping("/remove")
@ApiOperationSupport(order = 4)
@Operation(summary = "删除", description = "传入ids")
public R remove(@Parameter(description = "主键集合", required = true) @RequestParam String ids) {
return R.status(codeService.removeByIds(Func.toLongList(ids)));
}
/**
* 复制
*/
@PostMapping("/copy")
@ApiOperationSupport(order = 5)
@Operation(summary = "复制", description = "传入id")
public R copy(@Parameter(description = "主键", required = true) @RequestParam Long id) {
Code code = codeService.getById(id);
code.setId(null);
code.setCodeName(code.getCodeName() + "-copy");
return R.status(codeService.save(code));
}
/**
* 代码生成
*/
@PostMapping("/gen-code")
@ApiOperationSupport(order = 6)
@Operation(summary = "代码生成", description = "传入ids")
public R genCode(@Parameter(description = "主键集合", required = true) @RequestParam String ids) {
return R.status(generateService.code(Func.toLongList(ids)));
}
/**
* 代码生成
*/
@PostMapping("/gen-code-fast")
@ApiOperationSupport(order = 7)
@Operation(summary = "代码快速生成", description = "传入配置集合")
public R genCodeFast(@Parameter(description = "主键集合", required = true) @RequestBody GeneratorDTO dto) {
return R.status(generateService.codeFast(dto));
}
}

View File

@@ -0,0 +1,180 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.develop.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.IsAdministrator;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.constant.BladeConstant;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.xss.annotation.XssIgnore;
import org.springblade.develop.pojo.entity.CodeSetting;
import org.springblade.develop.service.ICodeSettingService;
import org.springblade.develop.service.IModelPrototypeService;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
/**
* 代码生成器配置表 控制器
*
* @author BladeX
*/
@RestController
@AllArgsConstructor
@IsAdministrator
@RequestMapping("/code-setting")
@Tag(name = "代码生成器配置表", description = "代码生成器配置表接口")
public class CodeSettingController extends BladeController {
private final ICodeSettingService codeSettingService;
private final IModelPrototypeService modelPrototypeService;
/**
* 代码生成器配置表 详情
*/
@GetMapping("/detail")
@ApiOperationSupport(order = 1)
@Operation(summary = "详情", description = "传入codeSetting")
public R<CodeSetting> detail(CodeSetting codeSetting) {
CodeSetting detail = codeSettingService.getOne(Condition.getQueryWrapper(codeSetting));
return R.data(detail);
}
/**
* 代码生成器配置表 分页
*/
@GetMapping("/list")
@ApiOperationSupport(order = 2)
@Operation(summary = "分页", description = "传入codeSetting")
public R<IPage<CodeSetting>> list(@Parameter(hidden = true) @RequestParam Map<String, Object> codeSetting, Query query) {
IPage<CodeSetting> pages = codeSettingService.page(Condition.getPage(query), Condition.getQueryWrapper(codeSetting, CodeSetting.class).orderByDesc("id"));
return R.data(pages);
}
/**
* 代码生成器配置表 新增
*/
@PostMapping("/save")
@ApiOperationSupport(order = 3)
@Operation(summary = "新增", description = "传入codeSetting")
public R save(@Valid @RequestBody CodeSetting codeSetting) {
return R.status(codeSettingService.save(codeSetting));
}
/**
* 代码生成器配置表 修改
*/
@PostMapping("/update")
@ApiOperationSupport(order = 4)
@Operation(summary = "修改", description = "传入codeSetting")
public R update(@Valid @RequestBody CodeSetting codeSetting) {
return R.status(codeSettingService.updateById(codeSetting));
}
@XssIgnore
@PostMapping("/submit")
@ApiOperationSupport(order = 5)
@Operation(summary = "新增或修改", description = "传入codeSetting")
public R submit(@Valid @RequestBody CodeSetting codeSetting) {
boolean temp = codeSettingService.saveOrUpdate(codeSetting);
if (temp) {
return R.data(codeSetting);
} else {
return R.status(Boolean.FALSE);
}
}
/**
* 代码生成器配置表 删除
*/
@PostMapping("/remove")
@ApiOperationSupport(order = 6)
@Operation(summary = "删除", description = "传入ids")
public R remove(@Parameter(description = "主键集合", required = true) @RequestParam String ids) {
return R.status(codeSettingService.removeByIds(Func.toLongList(ids)));
}
/**
* 代码生成器配置表 启用
*/
@PostMapping("/enable")
@ApiOperationSupport(order = 7)
@Operation(summary = "配置启用", description = "传入id")
public R enable(@Parameter(description = "主键", required = true) @RequestParam Long id) {
return R.status(codeSettingService.enable(id));
}
/**
* 代码生成器配置表 启用详情
*/
@GetMapping("/enable-detail")
@ApiOperationSupport(order = 8)
@Operation(summary = "详情", description = "传入codeSetting")
public R<CodeSetting> enableDetail() {
CodeSetting detail = codeSettingService.getOne(Wrappers.<CodeSetting>lambdaQuery().eq(CodeSetting::getStatus, BladeConstant.DB_STATUS_2).eq(CodeSetting::getIsDeleted, BladeConstant.DB_NOT_DELETED));
return R.data(detail);
}
/**
* 表单设计器选择
*/
@GetMapping("/table-form")
@ApiOperationSupport(order = 9)
@Operation(summary = "表单设计器选择", description = "tableName")
public R<List<CodeSetting>> formSelect(String tableName) {
return R.data(codeSettingService.list(Wrappers.<CodeSetting>lambdaQuery().eq(CodeSetting::getCode, tableName).eq(CodeSetting::getCategory, 2)));
}
/**
* 获取字段信息
*/
@GetMapping("/table-prototype")
@ApiOperationSupport(order = 10)
@Operation(summary = "物理表字段信息", description = "传入tableName与datasourceId")
public R tablePrototype(String tableName, Long datasourceId) {
TableInfo tableInfo = modelPrototypeService.getTableInfo(tableName, datasourceId);
if (tableInfo != null) {
return R.data(tableInfo.getFields());
} else {
return R.fail("未获得相关表信息");
}
}
}

View File

@@ -0,0 +1,144 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.develop.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.IsAdministrator;
import org.springblade.core.tenant.annotation.NonDS;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.core.xss.annotation.XssIgnore;
import org.springblade.develop.pojo.entity.Datasource;
import org.springblade.develop.service.IDatasourceService;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 数据源配置表 控制器
*
* @author Chill
*/
@NonDS
@RestController
@AllArgsConstructor
@IsAdministrator
@RequestMapping("/datasource")
@Tag(name = "数据源配置表", description = "数据源配置表接口")
public class DatasourceController extends BladeController {
private final IDatasourceService datasourceService;
/**
* 详情
*/
@GetMapping("/detail")
@ApiOperationSupport(order = 1)
@Operation(summary = "详情", description = "传入datasource")
public R<Datasource> detail(Datasource datasource) {
Datasource detail = datasourceService.getOne(Condition.getQueryWrapper(datasource));
return R.data(detail);
}
/**
* 分页 数据源配置表
*/
@GetMapping("/list")
@ApiOperationSupport(order = 2)
@Operation(summary = "分页", description = "传入datasource")
public R<IPage<Datasource>> list(Datasource datasource, Query query) {
IPage<Datasource> pages = datasourceService.page(Condition.getPage(query), Condition.getQueryWrapper(datasource));
return R.data(pages);
}
/**
* 新增 数据源配置表
*/
@PostMapping("/save")
@ApiOperationSupport(order = 4)
@Operation(summary = "新增", description = "传入datasource")
public R save(@Valid @RequestBody Datasource datasource) {
return R.status(datasourceService.save(datasource));
}
/**
* 修改 数据源配置表
*/
@PostMapping("/update")
@ApiOperationSupport(order = 5)
@Operation(summary = "修改", description = "传入datasource")
public R update(@Valid @RequestBody Datasource datasource) {
return R.status(datasourceService.updateById(datasource));
}
/**
* 新增或修改 数据源配置表
*/
@XssIgnore
@PostMapping("/submit")
@ApiOperationSupport(order = 6)
@Operation(summary = "新增或修改", description = "传入datasource")
public R submit(@Valid @RequestBody Datasource datasource) {
if (StringUtil.isNotBlank(datasource.getUrl())) {
datasource.setUrl(datasource.getUrl().replace("&amp;", "&"));
}
return R.status(datasourceService.saveOrUpdate(datasource));
}
/**
* 删除 数据源配置表
*/
@PostMapping("/remove")
@ApiOperationSupport(order = 7)
@Operation(summary = "逻辑删除", description = "传入ids")
public R remove(@Parameter(description = "主键集合", required = true) @RequestParam String ids) {
return R.status(datasourceService.deleteLogic(Func.toLongList(ids)));
}
/**
* 数据源列表
*/
@GetMapping("/select")
@ApiOperationSupport(order = 8)
@Operation(summary = "下拉数据源", description = "查询列表")
public R<List<Datasource>> select() {
List<Datasource> list = datasourceService.list();
return R.data(list);
}
}

View File

@@ -0,0 +1,205 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.develop.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.IsAdministrator;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringPool;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.develop.pojo.entity.Datasource;
import org.springblade.develop.pojo.entity.Model;
import org.springblade.develop.pojo.entity.ModelPrototype;
import org.springblade.develop.service.IDatasourceService;
import org.springblade.develop.service.IModelPrototypeService;
import org.springblade.develop.service.IModelService;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.stream.Collectors;
/**
* 数据模型表 控制器
*
* @author Chill
*/
@RestController
@AllArgsConstructor
@IsAdministrator
@RequestMapping("/model")
@Tag(name = "数据模型表", description = "数据模型表接口")
public class ModelController extends BladeController {
private final IModelService modelService;
private final IModelPrototypeService modelPrototypeService;
private final IDatasourceService datasourceService;
/**
* 详情
*/
@GetMapping("/detail")
@ApiOperationSupport(order = 1)
@Operation(summary = "详情", description = "传入model")
public R<Model> detail(Model model) {
Model detail = modelService.getOne(Condition.getQueryWrapper(model));
return R.data(detail);
}
/**
* 分页 数据模型表
*/
@GetMapping("/list")
@ApiOperationSupport(order = 2)
@Operation(summary = "分页", description = "传入model")
public R<IPage<Model>> list(Model model, Query query) {
IPage<Model> pages = modelService.page(Condition.getPage(query), Condition.getQueryWrapper(model));
return R.data(pages);
}
/**
* 新增 数据模型表
*/
@PostMapping("/save")
@ApiOperationSupport(order = 3)
@Operation(summary = "新增", description = "传入model")
public R save(@Valid @RequestBody Model model) {
return R.status(modelService.save(model));
}
/**
* 修改 数据模型表
*/
@PostMapping("/update")
@ApiOperationSupport(order = 4)
@Operation(summary = "修改", description = "传入model")
public R update(@Valid @RequestBody Model model) {
return R.status(modelService.updateById(model));
}
/**
* 新增或修改 数据模型表
*/
@PostMapping("/submit")
@ApiOperationSupport(order = 5)
@Operation(summary = "新增或修改", description = "传入model")
public R submit(@Valid @RequestBody Model model) {
boolean temp = modelService.saveOrUpdate(model);
if (temp) {
return R.data(model);
} else {
return R.status(Boolean.FALSE);
}
}
/**
* 删除 数据模型表
*/
@PostMapping("/remove")
@ApiOperationSupport(order = 6)
@Operation(summary = "逻辑删除", description = "传入ids")
public R remove(@Parameter(description = "主键集合", required = true) @RequestParam String ids) {
return R.status(modelService.delete(Func.toLongList(ids)));
}
/**
* 模型列表
*/
@GetMapping("/select")
@ApiOperationSupport(order = 7)
@Operation(summary = "模型列表", description = "模型列表")
public R<List<Model>> select() {
List<Model> list = modelService.list();
list.forEach(model -> model.setModelName(model.getModelTable() + StringPool.COLON + StringPool.SPACE + model.getModelName()));
return R.data(list);
}
/**
* 获取物理表列表
*/
@GetMapping("/table-list")
@ApiOperationSupport(order = 8)
@Operation(summary = "物理表列表", description = "传入datasourceId")
public R<List<TableInfo>> tableList(Long datasourceId) {
Datasource datasource = datasourceService.getById(datasourceId);
ConfigBuilder config = modelPrototypeService.getConfigBuilder(datasource);
List<TableInfo> tableInfoList = config.getTableInfoList().stream()
.filter(tableInfo -> !StringUtil.startsWithIgnoreCase(tableInfo.getName(), "ACT_") && !StringUtil.startsWithIgnoreCase(tableInfo.getName(), "FLW_"))
.map(tableInfo -> tableInfo.setComment(tableInfo.getName() + StringPool.COLON + tableInfo.getComment()))
.collect(Collectors.toList());
return R.data(tableInfoList);
}
/**
* 获取物理表信息
*/
@GetMapping("/table-info")
@ApiOperationSupport(order = 9)
@Operation(summary = "物理表信息", description = "传入model信息")
public R<TableInfo> tableInfo(Long modelId, String tableName, Long datasourceId) {
if (StringUtil.isBlank(tableName)) {
Model model = modelService.getById(modelId);
tableName = model.getModelTable();
}
TableInfo tableInfo = modelPrototypeService.getTableInfo(tableName, datasourceId);
return R.data(tableInfo);
}
/**
* 获取字段信息
*/
@GetMapping("/model-prototype")
@ApiOperationSupport(order = 10)
@Operation(summary = "物理表字段信息", description = "传入modelId与datasourceId")
public R modelPrototype(Long modelId, Long datasourceId) {
List<ModelPrototype> modelPrototypeList = modelPrototypeService.list(Wrappers.<ModelPrototype>query().lambda().eq(ModelPrototype::getModelId, modelId));
if (!modelPrototypeList.isEmpty()) {
return R.data(modelPrototypeList);
}
Model model = modelService.getById(modelId);
String tableName = model.getModelTable();
TableInfo tableInfo = modelPrototypeService.getTableInfo(tableName, datasourceId);
if (tableInfo != null) {
return R.data(tableInfo.getFields());
} else {
return R.fail("未获得相关表信息");
}
}
}

View File

@@ -0,0 +1,147 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.develop.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.IsAdministrator;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringPool;
import org.springblade.develop.pojo.entity.ModelPrototype;
import org.springblade.develop.service.IModelPrototypeService;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 数据原型表 控制器
*
* @author Chill
*/
@RestController
@AllArgsConstructor
@IsAdministrator
@RequestMapping("/model-prototype")
@Tag(name = "数据原型表", description = "数据原型表接口")
public class ModelPrototypeController extends BladeController {
private final IModelPrototypeService modelPrototypeService;
/**
* 详情
*/
@GetMapping("/detail")
@ApiOperationSupport(order = 1)
@Operation(summary = "详情", description = "传入modelPrototype")
public R<ModelPrototype> detail(ModelPrototype modelPrototype) {
ModelPrototype detail = modelPrototypeService.getOne(Condition.getQueryWrapper(modelPrototype));
return R.data(detail);
}
/**
* 分页 数据原型表
*/
@GetMapping("/list")
@ApiOperationSupport(order = 2)
@Operation(summary = "分页", description = "传入modelPrototype")
public R<IPage<ModelPrototype>> list(ModelPrototype modelPrototype, Query query) {
IPage<ModelPrototype> pages = modelPrototypeService.page(Condition.getPage(query), Condition.getQueryWrapper(modelPrototype));
return R.data(pages);
}
/**
* 新增 数据原型表
*/
@PostMapping("/save")
@ApiOperationSupport(order = 4)
@Operation(summary = "新增", description = "传入modelPrototype")
public R save(@Valid @RequestBody ModelPrototype modelPrototype) {
return R.status(modelPrototypeService.save(modelPrototype));
}
/**
* 修改 数据原型表
*/
@PostMapping("/update")
@ApiOperationSupport(order = 5)
@Operation(summary = "修改", description = "传入modelPrototype")
public R update(@Valid @RequestBody ModelPrototype modelPrototype) {
return R.status(modelPrototypeService.updateById(modelPrototype));
}
/**
* 新增或修改 数据原型表
*/
@PostMapping("/submit")
@ApiOperationSupport(order = 6)
@Operation(summary = "新增或修改", description = "传入modelPrototype")
public R submit(@Valid @RequestBody ModelPrototype modelPrototype) {
return R.status(modelPrototypeService.saveOrUpdate(modelPrototype));
}
/**
* 批量新增或修改 数据原型表
*/
@PostMapping("/submit-list")
@ApiOperationSupport(order = 7)
@Operation(summary = "批量新增或修改", description = "传入modelPrototype集合")
public R submitList(@Valid @RequestBody List<ModelPrototype> modelPrototypes) {
return R.status(modelPrototypeService.submitList(modelPrototypes));
}
/**
* 删除 数据原型表
*/
@PostMapping("/remove")
@ApiOperationSupport(order = 8)
@Operation(summary = "逻辑删除", description = "传入ids")
public R remove(@Parameter(description = "主键集合", required = true) @RequestParam String ids) {
return R.status(modelPrototypeService.deleteLogic(Func.toLongList(ids)));
}
/**
* 数据原型列表
*/
@GetMapping("/select")
@ApiOperationSupport(order = 9)
@Operation(summary = "数据原型列表", description = "数据原型列表")
public R<List<ModelPrototype>> select(@Parameter(description = "数据模型Id", required = true) @RequestParam Long modelId) {
List<ModelPrototype> list = modelPrototypeService.list(Wrappers.<ModelPrototype>query().lambda().eq(ModelPrototype::getModelId, modelId));
list.forEach(prototype -> prototype.setJdbcComment(prototype.getJdbcName() + StringPool.COLON + StringPool.SPACE + prototype.getJdbcComment()));
return R.data(list);
}
}

View File

@@ -0,0 +1,71 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.develop.feign;
import lombok.AllArgsConstructor;
import org.springblade.core.tenant.annotation.NonDS;
import org.springblade.core.tool.api.R;
import org.springblade.develop.pojo.entity.Datasource;
import org.springblade.develop.service.IDatasourceService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 数据源远程调用服务
*
* @author Chill
*/
@NonDS
@RestController
@AllArgsConstructor
public class DatasourceClient implements IDatasourceClient {
private final IDatasourceService datasourceService;
/**
* 获取数据源详情
*/
@GetMapping(GET_DETAIL)
public R<Datasource> detail(@RequestParam("id") Long id) {
Datasource datasource = datasourceService.getById(id);
if (datasource == null) {
return R.fail("数据源不存在");
}
return R.data(datasource);
}
/**
* 获取所有数据源列表
*/
@GetMapping(GET_LIST)
public R<List<Datasource>> list() {
return R.data(datasourceService.list());
}
}

View File

@@ -0,0 +1,38 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.develop.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springblade.develop.pojo.entity.Code;
/**
* Mapper 接口
*
* @author Chill
*/
public interface CodeMapper extends BaseMapper<Code> {
}

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.springblade.develop.mapper.CodeMapper">
<!-- 通用查询映射结果 -->
<resultMap id="codeResultMap" type="org.springblade.develop.pojo.entity.Code">
<id column="id" property="id"/>
<result column="model_id" property="modelId"/>
<result column="menu_id" property="menuId"/>
<result column="service_name" property="serviceName"/>
<result column="code_name" property="codeName"/>
<result column="table_name" property="tableName"/>
<result column="pk_name" property="pkName"/>
<result column="base_mode" property="baseMode"/>
<result column="wrap_mode" property="wrapMode"/>
<result column="table_prefix" property="tablePrefix"/>
<result column="package_name" property="packageName"/>
<result column="api_path" property="apiPath"/>
<result column="web_path" property="webPath"/>
<result column="is_deleted" property="isDeleted"/>
</resultMap>
</mapper>

View File

@@ -0,0 +1,38 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.develop.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springblade.develop.pojo.entity.CodeSetting;
/**
* 代码生成器配置表 Mapper 接口
*
* @author BladeX
*/
public interface CodeSettingMapper extends BaseMapper<CodeSetting> {
}

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.springblade.develop.mapper.CodeSettingMapper">
<!-- 通用查询映射结果 -->
<resultMap id="codeSettingResultMap" type="org.springblade.develop.pojo.entity.CodeSetting">
<result column="id" property="id"/>
<result column="name" property="name"/>
<result column="code" property="code"/>
<result column="category" property="category"/>
<result column="settings" property="settings"/>
<result column="status" property="status"/>
<result column="is_deleted" property="isDeleted"/>
</resultMap>
</mapper>

View File

@@ -0,0 +1,38 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.develop.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springblade.develop.pojo.entity.Datasource;
/**
* 数据源配置表 Mapper 接口
*
* @author Chill
*/
public interface DatasourceMapper extends BaseMapper<Datasource> {
}

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.springblade.develop.mapper.DatasourceMapper">
<!-- 通用查询映射结果 -->
<resultMap id="datasourceResultMap" type="org.springblade.develop.pojo.entity.Datasource">
<result column="id" property="id"/>
<result column="create_user" property="createUser"/>
<result column="create_dept" property="createDept"/>
<result column="create_time" property="createTime"/>
<result column="update_user" property="updateUser"/>
<result column="update_time" property="updateTime"/>
<result column="status" property="status"/>
<result column="is_deleted" property="isDeleted"/>
<result column="driver_class" property="driverClass"/>
<result column="url" property="url"/>
<result column="username" property="username"/>
<result column="password" property="password"/>
<result column="remark" property="remark"/>
</resultMap>
</mapper>

View File

@@ -0,0 +1,38 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.develop.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springblade.develop.pojo.entity.Model;
/**
* 数据模型表 Mapper 接口
*
* @author Chill
*/
public interface ModelMapper extends BaseMapper<Model> {
}

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.springblade.develop.mapper.ModelMapper">
<!-- 通用查询映射结果 -->
<resultMap id="modelResultMap" type="org.springblade.develop.pojo.entity.Model">
<id column="id" property="id"/>
<result column="create_user" property="createUser"/>
<result column="create_time" property="createTime"/>
<result column="update_user" property="updateUser"/>
<result column="update_time" property="updateTime"/>
<result column="status" property="status"/>
<result column="is_deleted" property="isDeleted"/>
<result column="datasource_id" property="datasourceId"/>
<result column="model_name" property="modelName"/>
<result column="model_code" property="modelCode"/>
<result column="model_table" property="modelTable"/>
<result column="model_class" property="modelClass"/>
<result column="model_remark" property="modelRemark"/>
</resultMap>
<select id="selectModelPage" resultMap="modelResultMap">
select * from blade_model where is_deleted = 0
</select>
</mapper>

View File

@@ -0,0 +1,38 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.develop.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springblade.develop.pojo.entity.ModelPrototype;
/**
* 数据原型表 Mapper 接口
*
* @author Chill
*/
public interface ModelPrototypeMapper extends BaseMapper<ModelPrototype> {
}

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.springblade.develop.mapper.ModelPrototypeMapper">
<!-- 通用查询映射结果 -->
<resultMap id="modelPrototypeResultMap" type="org.springblade.develop.pojo.entity.ModelPrototype">
<id column="id" property="id"/>
<result column="create_user" property="createUser"/>
<result column="create_time" property="createTime"/>
<result column="update_user" property="updateUser"/>
<result column="update_time" property="updateTime"/>
<result column="status" property="status"/>
<result column="is_deleted" property="isDeleted"/>
<result column="jdbc_name" property="jdbcName"/>
<result column="jdbc_type" property="jdbcType"/>
<result column="jdbc_comment" property="jdbcComment"/>
<result column="property_type" property="propertyType"/>
<result column="property_entity" property="propertyEntity"/>
<result column="property_name" property="propertyName"/>
<result column="is_form" property="isForm"/>
<result column="is_row" property="isRow"/>
<result column="component_type" property="componentType"/>
<result column="dict_code" property="dictCode"/>
<result column="is_required" property="isRequired"/>
<result column="is_list" property="isList"/>
<result column="is_query" property="isQuery"/>
<result column="query_type" property="queryType"/>
</resultMap>
<select id="selectModelPrototypePage" resultMap="modelPrototypeResultMap">
select * from blade_model_prototype where is_deleted = 0
</select>
</mapper>

View File

@@ -0,0 +1,47 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.develop.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.springblade.develop.pojo.entity.Code;
/**
* 服务类
*
* @author Chill
*/
public interface ICodeService extends IService<Code> {
/**
* 提交
*
* @param code
* @return
*/
boolean submit(Code code);
}

View File

@@ -0,0 +1,45 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.develop.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.springblade.develop.pojo.entity.CodeSetting;
/**
* 代码生成器配置表 服务类
*
* @author BladeX
*/
public interface ICodeSettingService extends IService<CodeSetting> {
/**
* 启动配置
*
* @param id
* @return
*/
boolean enable(Long id);
}

View File

@@ -0,0 +1,38 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.develop.service;
import org.springblade.core.mp.base.BaseService;
import org.springblade.develop.pojo.entity.Datasource;
/**
* 数据源配置表 服务类
*
* @author Chill
*/
public interface IDatasourceService extends BaseService<Datasource> {
}

View File

@@ -0,0 +1,56 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.develop.service;
import org.springblade.develop.pojo.dto.GeneratorDTO;
import java.util.List;
/**
* 服务类
*
* @author Chill
*/
public interface IGenerateService {
/**
* 生成代码
*
* @param ids 主键集合
* @return boolean
*/
boolean code(List<Long> ids);
/**
* 快速生成代码
*
* @param dto 配置参数
* @return boolean
*/
boolean codeFast(GeneratorDTO dto);
}

View File

@@ -0,0 +1,84 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.develop.service;
import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import org.springblade.core.mp.base.BaseService;
import org.springblade.develop.pojo.entity.Datasource;
import org.springblade.develop.pojo.entity.ModelPrototype;
import java.util.List;
/**
* 数据原型表 服务类
*
* @author Chill
*/
public interface IModelPrototypeService extends BaseService<ModelPrototype> {
/**
* 批量提交
*
* @param modelPrototypes 原型集合
* @return boolean
*/
boolean submitList(List<ModelPrototype> modelPrototypes);
/**
* 原型列表
*
* @param modelId 模型ID
* @return List<ModelPrototype>
*/
List<ModelPrototype> prototypeList(Long modelId);
/**
* 获取表信息
*
* @param tableName 表名
* @param datasourceId 数据源主键
*/
TableInfo getTableInfo(String tableName, Long datasourceId);
/**
* 获取表配置信息
*
* @param datasource 数据源信息
*/
default ConfigBuilder getConfigBuilder(Datasource datasource) {
return getConfigBuilder(datasource, null);
}
/**
* 获取表配置信息
*
* @param datasource 数据源信息
* @param tableName 表名
*/
ConfigBuilder getConfigBuilder(Datasource datasource, String tableName);
}

View File

@@ -0,0 +1,48 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.develop.service;
import org.springblade.core.mp.base.BaseService;
import org.springblade.develop.pojo.entity.Model;
import java.util.List;
/**
* 数据模型表 服务类
*
* @author Chill
*/
public interface IModelService extends BaseService<Model> {
/**
* 删除模型
*
* @param ids 主键集合
* @return boolean
*/
boolean delete(List<Long> ids);
}

View File

@@ -0,0 +1,48 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.develop.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springblade.core.tool.constant.BladeConstant;
import org.springblade.develop.pojo.entity.Code;
import org.springblade.develop.mapper.CodeMapper;
import org.springblade.develop.service.ICodeService;
import org.springframework.stereotype.Service;
/**
* 服务实现类
*
* @author Chill
*/
@Service
public class CodeServiceImpl extends ServiceImpl<CodeMapper, Code> implements ICodeService {
@Override
public boolean submit(Code code) {
code.setIsDeleted(BladeConstant.DB_NOT_DELETED);
return saveOrUpdate(code);
}
}

View File

@@ -0,0 +1,53 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.develop.service.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springblade.core.tool.constant.BladeConstant;
import org.springblade.develop.mapper.CodeSettingMapper;
import org.springblade.develop.pojo.entity.CodeSetting;
import org.springblade.develop.service.ICodeSettingService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* 代码生成器配置表 服务实现类
*
* @author BladeX
*/
@Service
public class CodeSettingServiceImpl extends ServiceImpl<CodeSettingMapper, CodeSetting> implements ICodeSettingService {
@Override
@Transactional(rollbackFor = Exception.class)
public boolean enable(Long id) {
// 先禁用
boolean temp1 = this.update(Wrappers.<CodeSetting>update().lambda().set(CodeSetting::getStatus, BladeConstant.DB_STATUS_1));
// 在启用
boolean temp2 = this.update(Wrappers.<CodeSetting>update().lambda().set(CodeSetting::getStatus, BladeConstant.DB_STATUS_2).eq(CodeSetting::getId, id));
return temp1 && temp2;
}
}

View File

@@ -0,0 +1,42 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.develop.service.impl;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.develop.pojo.entity.Datasource;
import org.springblade.develop.mapper.DatasourceMapper;
import org.springblade.develop.service.IDatasourceService;
import org.springframework.stereotype.Service;
/**
* 数据源配置表 服务实现类
*
* @author Chill
*/
@Service
public class DatasourceServiceImpl extends BaseServiceImpl<DatasourceMapper, Datasource> implements IDatasourceService {
}

View File

@@ -0,0 +1,199 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.develop.service.impl;
import com.baomidou.mybatisplus.generator.config.po.TableField;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import lombok.RequiredArgsConstructor;
import org.springblade.core.tool.jackson.JsonUtil;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.develop.constant.DevelopConstant;
import org.springblade.develop.pojo.dto.GeneratorDTO;
import org.springblade.develop.pojo.entity.*;
import org.springblade.develop.service.*;
import org.springblade.develop.support.BladeCodeGenerator;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* 服务实现类
*
* @author Chill
*/
@Service
@RequiredArgsConstructor
public class GenerateServiceImpl implements IGenerateService {
private final ICodeService codeService;
private final ICodeSettingService codeSettingService;
private final IDatasourceService datasourceService;
private final IModelService modelService;
private final IModelPrototypeService modelPrototypeService;
@Override
@Transactional(rollbackFor = Exception.class)
public boolean code(List<Long> ids) {
Collection<Code> codes = codeService.listByIds(ids);
codes.forEach(code -> {
// 创建代码生成器
BladeCodeGenerator generator = new BladeCodeGenerator();
// 设置菜单数据
this.generateMenu(generator, code);
// 设置配置信息
this.generateTemplate(generator, code);
// 设置基础模型
Model model = modelService.getById(code.getModelId());
this.generateModel(generator, code, model);
// 设置数据源
this.generateDatasource(generator, model);
// 启动代码生成
generator.run();
});
return true;
}
@Override
public boolean codeFast(GeneratorDTO dto) {
// 创建代码生成器
BladeCodeGenerator generator = new BladeCodeGenerator();
Code code = Objects.requireNonNull(BeanUtil.copyProperties(dto, Code.class));
Model model = Objects.requireNonNull(BeanUtil.copyProperties(dto, Model.class));
String modelForm = dto.getModelForm();
// 设置菜单数据
this.generateMenu(generator, code);
// 设置配置信息
this.generateForm(generator, modelForm);
this.generateTemplate(generator, code);
this.generateModel(generator, code, model);
// 设置数据源
this.generateDatasource(generator, model);
// 启动代码生成
generator.run();
return true;
}
private void generateMenu(BladeCodeGenerator generator, Code code) {
// 设置上级菜单id
generator.setMenuId(String.valueOf(code.getMenuId()));
// 设置是否生成菜单sql
generator.setHasMenuSql(Boolean.TRUE);
}
private void generateForm(BladeCodeGenerator generator, String modelForm) {
if (StringUtil.isNotBlank(modelForm)) {
CodeSetting codeSetting = codeSettingService.getById(Func.toLong(modelForm));
if (codeSetting != null) {
generator.setModelFormOption(codeSetting.getSettings());
}
}
}
private void generateTemplate(BladeCodeGenerator generator, Code code) {// 设置基础配置
generator.setCodeStyle(code.getCodeStyle());
generator.setCodeName(code.getCodeName());
generator.setServiceName(code.getServiceName());
generator.setPackageName(code.getPackageName());
generator.setPackageDir(code.getApiPath());
generator.setPackageWebDir(code.getWebPath());
generator.setTablePrefix(Func.toStrArray(code.getTablePrefix()));
generator.setIncludeTables(Func.toStrArray(code.getTableName()));
// 设置模版信息
generator.setTemplateType(Func.toStr(code.getTemplateType(), DevelopConstant.TEMPLATE_CRUD));
generator.setAuthor(code.getAuthor());
generator.setSubModelId(code.getSubModelId());
generator.setSubFkId(code.getSubFkId());
generator.setTreeId(code.getTreeId());
generator.setTreePid(code.getTreePid());
generator.setTreeName(code.getTreeName());
// 设置是否继承基础业务字段
generator.setHasSuperEntity(code.getBaseMode() == 2);
// 设置是否开启包装器模式
generator.setHasWrapper(code.getWrapMode() == 2);
// 设置是否开启远程调用模式
generator.setHasFeign(code.getFeignMode() == 2);
// 设置控制器服务名前缀
generator.setHasServiceName(Boolean.FALSE);
}
private void generateModel(BladeCodeGenerator generator, Code code, Model model) {
generator.setModelCode(model.getModelCode());
generator.setModelClass(model.getModelClass());
generator.setModel(JsonUtil.readMap(JsonUtil.toJson(model)));
// 设置模型集合
if (Func.isNotEmpty(model.getId())) {
List<ModelPrototype> prototypes = modelPrototypeService.prototypeList(model.getId());
generator.setPrototypes(JsonUtil.readListMap(JsonUtil.toJson(prototypes)));
if (StringUtil.isNotBlank(code.getSubModelId()) && StringUtil.equals(code.getTemplateType(), DevelopConstant.TEMPLATE_SUB)) {
Model subModel = modelService.getById(Func.toLong(code.getSubModelId()));
List<ModelPrototype> subPrototypes = modelPrototypeService.prototypeList(subModel.getId());
generator.setSubModel(JsonUtil.readMap(JsonUtil.toJson(subModel)));
generator.setSubPrototypes(JsonUtil.readListMap(JsonUtil.toJson(subPrototypes)));
}
} else {
TableInfo tableInfo = modelPrototypeService.getTableInfo(model.getModelTable(), model.getDatasourceId());
List<TableField> fields = tableInfo.getFields();
List<ModelPrototype> prototypes = convertPrototypes(fields);
generator.setPrototypes(JsonUtil.readListMap(JsonUtil.toJson(prototypes)));
}
}
private void generateDatasource(BladeCodeGenerator generator, Model model) {
Datasource datasource = datasourceService.getById(model.getDatasourceId());
generator.setDriverName(datasource.getDriverClass());
generator.setUrl(datasource.getUrl());
generator.setUsername(datasource.getUsername());
generator.setPassword(datasource.getPassword());
}
/**
* 将 TableField 列表转换为 ModelPrototype 列表
*
* @param tableFields 输入的 TableField 列表
* @return 转换后的 ModelPrototype 列表
*/
public static List<ModelPrototype> convertPrototypes(List<TableField> tableFields) {
return tableFields.stream().map(tableField -> {
ModelPrototype prototype = new ModelPrototype();
prototype.setJdbcName(tableField.getName());
if (tableField.getColumnType() != null) {
prototype.setJdbcType(tableField.getColumnType().getType());
prototype.setPropertyType(tableField.getColumnType().getType());
}
prototype.setJdbcComment(tableField.getComment());
prototype.setPropertyName(tableField.getPropertyName());
prototype.setComponentType("input");
return prototype;
}).collect(Collectors.toList());
}
}

View File

@@ -0,0 +1,115 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.develop.service.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import lombok.RequiredArgsConstructor;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.tool.utils.StringPool;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.develop.mapper.ModelPrototypeMapper;
import org.springblade.develop.pojo.entity.Datasource;
import org.springblade.develop.pojo.entity.ModelPrototype;
import org.springblade.develop.service.IDatasourceService;
import org.springblade.develop.service.IModelPrototypeService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Iterator;
import java.util.List;
/**
* 数据原型表 服务实现类
*
* @author Chill
*/
@Service
@RequiredArgsConstructor
public class ModelPrototypeServiceImpl extends BaseServiceImpl<ModelPrototypeMapper, ModelPrototype> implements IModelPrototypeService {
private final IDatasourceService datasourceService;
@Override
@Transactional(rollbackFor = Exception.class)
public boolean submitList(List<ModelPrototype> modelPrototypes) {
modelPrototypes.forEach(modelPrototype -> {
if (modelPrototype.getId() == null) {
this.save(modelPrototype);
} else {
this.updateById(modelPrototype);
}
});
return true;
}
@Override
public List<ModelPrototype> prototypeList(Long modelId) {
return this.list(Wrappers.<ModelPrototype>lambdaQuery().eq(ModelPrototype::getModelId, modelId));
}
@Override
public TableInfo getTableInfo(String tableName, Long datasourceId) {
Datasource datasource = datasourceService.getById(datasourceId);
ConfigBuilder config = getConfigBuilder(datasource, tableName);
List<TableInfo> tableInfoList = config.getTableInfoList();
TableInfo tableInfo = null;
Iterator<TableInfo> iterator = tableInfoList.stream().filter(table -> table.getName().equals(tableName)).toList().iterator();
if (iterator.hasNext()) {
tableInfo = iterator.next();
if (tableName.contains(StringPool.UNDERSCORE)) {
String entityPrefix = StringUtil.firstCharToUpper(tableName.split(StringPool.UNDERSCORE)[0]);
String entityName = StringUtil.removePrefix(tableInfo.getEntityName(), entityPrefix);
tableInfo.setEntityName(entityName);
} else {
tableInfo.setEntityName(StringUtil.firstCharToUpper(tableName));
}
}
return tableInfo;
}
@Override
public ConfigBuilder getConfigBuilder(Datasource datasource, String tableName) {
StrategyConfig.Builder builder = new StrategyConfig.Builder();
//表前缀过滤目前官方仅支持一个前缀可自行修改为sys_或tb_或其他业务表前缀
//builder.likeTable(new LikeTable("blade_", SqlLike.RIGHT));
if (StringUtil.isNotBlank(tableName)) {
builder.addInclude(tableName);
}
StrategyConfig strategyConfig = builder.entityBuilder()
.naming(NamingStrategy.underline_to_camel)
.columnNaming(NamingStrategy.underline_to_camel).build();
DataSourceConfig datasourceConfig = new DataSourceConfig.Builder(
datasource.getUrl(), datasource.getUsername(), datasource.getPassword()
).build();
return new ConfigBuilder(null, datasourceConfig, strategyConfig, null, null, null);
}
}

View File

@@ -0,0 +1,77 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.develop.service.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.develop.pojo.entity.Code;
import org.springblade.develop.pojo.entity.Model;
import org.springblade.develop.pojo.entity.ModelPrototype;
import org.springblade.develop.mapper.ModelMapper;
import org.springblade.develop.service.ICodeService;
import org.springblade.develop.service.IModelPrototypeService;
import org.springblade.develop.service.IModelService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* 数据模型表 服务实现类
*
* @author Chill
*/
@Service
@RequiredArgsConstructor
public class ModelServiceImpl extends BaseServiceImpl<ModelMapper, Model> implements IModelService {
private final IModelPrototypeService modelPrototypeService;
private final ICodeService codeService;
@Override
@Transactional(rollbackFor = Exception.class)
public boolean delete(List<Long> ids) {
boolean modelTemp = this.deleteLogic(ids);
if (modelTemp) {
if (modelPrototypeService.count(Wrappers.<ModelPrototype>lambdaQuery().in(ModelPrototype::getModelId, ids)) > 0) {
boolean prototypeTemp = modelPrototypeService.remove(Wrappers.<ModelPrototype>lambdaQuery().in(ModelPrototype::getModelId, ids));
if (!prototypeTemp) {
throw new ServiceException("删除数据模型成功,关联数据原型删除失败");
}
}
if (codeService.count(Wrappers.<Code>lambdaQuery().in(Code::getModelId, ids)) > 0) {
boolean codeTemp = codeService.remove(Wrappers.<Code>lambdaQuery().in(Code::getModelId, ids));
if (!codeTemp) {
throw new ServiceException("删除数据模型成功,关联代码生成配置删除失败");
}
}
}
return true;
}
}

View File

@@ -0,0 +1,10 @@
#服务器端口
server:
port: 7007
#数据源配置
spring:
datasource:
url: ${blade.datasource.dev.url}
username: ${blade.datasource.dev.username}
password: ${blade.datasource.dev.password}

View File

@@ -0,0 +1,11 @@
#服务器端口
server:
port: 7007
#数据源配置
spring:
datasource:
url: ${blade.datasource.prod.url}
username: ${blade.datasource.prod.username}
password: ${blade.datasource.prod.password}

View File

@@ -0,0 +1,10 @@
#服务器端口
server:
port: 7007
#数据源配置
spring:
datasource:
url: ${blade.datasource.test.url}
username: ${blade.datasource.test.username}
password: ${blade.datasource.test.password}

View File

@@ -0,0 +1,5 @@
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/bladex?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true
spring.datasource.username=root
spring.datasource.password=root
author=BladeX

View File

@@ -0,0 +1,88 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.test;
import org.springblade.develop.constant.DevelopConstant;
import org.springblade.develop.support.BladeFastCodeGenerator;
public class CodeGenerator {
/**
* 代码生成的系统类型(Boot/Cloud)
*/
public static String SYSTEM_NAME = DevelopConstant.CLOUD_NAME;
/**
* 代码生成的模块名
*/
public static String CODE_NAME = "自定义模块";
/**
* 代码所在服务名
*/
public static String SERVICE_NAME = "blade-desk";
/**
* 代码生成的包名
*/
public static String PACKAGE_NAME = "org.springblade.desk";
/**
* 需要去掉的表前缀
*/
public static String[] TABLE_PREFIX = {"blade_"};
/**
* 需要生成的表名(两者只能取其一)
*/
public static String[] INCLUDE_TABLES = {"blade_notice"};
/**
* 需要排除的表名(两者只能取其一)
*/
public static String[] EXCLUDE_TABLES = {};
/**
* 是否包含基础业务字段
*/
public static Boolean HAS_SUPER_ENTITY = Boolean.TRUE;
/**
* 基础业务字段
*/
public static String[] SUPER_ENTITY_COLUMNS = {"id", "create_time", "create_user", "create_dept", "update_time", "update_user", "status", "is_deleted"};
/**
* RUN THIS
*/
public static void main(String[] args) {
BladeFastCodeGenerator generator = new BladeFastCodeGenerator();
generator.setSystemName(SYSTEM_NAME);
generator.setCodeName(CODE_NAME);
generator.setServiceName(SERVICE_NAME);
generator.setPackageName(PACKAGE_NAME);
generator.setTablePrefix(TABLE_PREFIX);
generator.setIncludeTables(INCLUDE_TABLES);
generator.setExcludeTables(EXCLUDE_TABLES);
generator.setHasSuperEntity(HAS_SUPER_ENTITY);
generator.setSuperEntityColumns(SUPER_ENTITY_COLUMNS);
generator.run();
}
}

View File

@@ -0,0 +1,212 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package ${package.Controller};
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import lombok.AllArgsConstructor;
import jakarta.validation.Valid;
import org.springblade.core.secure.BladeUser;
import org.springblade.core.secure.annotation.IsAdmin;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springframework.web.bind.annotation.*;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import ${packageName!}.pojo.entity.${entityKey!}Entity;
import ${packageName!}.pojo.vo.${entityKey!}VO;
import ${packageName!}.excel.${entityKey!}Excel;
#if(hasWrapper) {
import ${packageName!}.wrapper.${entityKey!}Wrapper;
#}
import ${packageName!}.service.${table.serviceName!};
#if(isNotEmpty(superControllerClassPackage)){
import ${superControllerClassPackage!};
#}
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.excel.util.ExcelUtil;
import org.springblade.core.tool.constant.BladeConstant;
import java.util.Map;
import java.util.List;
import jakarta.servlet.http.HttpServletResponse;
/**
* ${table.comment!} 控制器
*
* @author ${author!}
* @since ${date!}
*/
@RestController
@AllArgsConstructor
#if(hasServiceName) {
@RequestMapping("${serviceName!}/${entityKeyPath!}")
#}else{
@RequestMapping("/${entityKeyPath!}")
#}
@Tag(name = "${table.comment!}", description = "${table.comment!}接口")
#if(isNotEmpty(superControllerClass)){
public class ${table.controllerName!} extends ${superControllerClass!} {
#}
#else{
public class ${table.controllerName!} {
#}
private final ${table.serviceName!} ${entityKeyPath!}Service;
#if(hasWrapper){
/**
* ${table.comment!} 详情
*/
@GetMapping("/detail")
@ApiOperationSupport(order = 1)
@Operation(summary = "详情", description = "传入${entityKeyPath!}")
public R<${entityKey!}VO> detail(${entityKey!}Entity ${entityKeyPath!}) {
${entityKey!}Entity detail = ${entityKeyPath!}Service.getOne(Condition.getQueryWrapper(${entityKeyPath!}));
return R.data(${entityKey!}Wrapper.build().entityVO(detail));
}
/**
* ${table.comment!} 分页
*/
@GetMapping("/list")
@ApiOperationSupport(order = 2)
@Operation(summary = "分页", description = "传入${entityKeyPath!}")
public R<IPage<${entityKey!}VO>> list(@Parameter(hidden = true) @RequestParam Map<String, Object> ${entityKeyPath!}, Query query) {
IPage<${entityKey!}Entity> pages = ${entityKeyPath!}Service.page(Condition.getPage(query), Condition.getQueryWrapper(${entityKeyPath!}, ${entityKey!}Entity.class));
return R.data(${entityKey!}Wrapper.build().pageVO(pages));
}
#}else{
/**
* ${table.comment!} 详情
*/
@GetMapping("/detail")
@ApiOperationSupport(order = 1)
@Operation(summary = "详情", description = "传入${entityKeyPath!}")
public R<${entityKey!}Entity> detail(${entityKey!}Entity ${entityKeyPath!}) {
${entityKey!}Entity detail = ${entityKeyPath!}Service.getOne(Condition.getQueryWrapper(${entityKeyPath!}));
return R.data(detail);
}
/**
* ${table.comment!} 分页
*/
@GetMapping("/list")
@ApiOperationSupport(order = 2)
@Operation(summary = "分页", description = "传入${entityKeyPath!}")
public R<IPage<${entityKey!}Entity>> list(@Parameter(hidden = true) @RequestParam Map<String, Object> ${entityKeyPath!}, Query query) {
IPage<${entityKey!}Entity> pages = ${entityKeyPath!}Service.page(Condition.getPage(query), Condition.getQueryWrapper(${entityKeyPath!}, ${entityKey!}Entity.class));
return R.data(pages);
}
#}
/**
* ${table.comment!} 自定义分页
*/
@GetMapping("/page")
@ApiOperationSupport(order = 3)
@Operation(summary = "分页", description = "传入${entityKeyPath!}")
public R<IPage<${entityKey!}VO>> page(${entityKey!}VO ${entityKeyPath!}, Query query) {
IPage<${entityKey!}VO> pages = ${entityKeyPath!}Service.select${entityKey!}Page(Condition.getPage(query), ${entityKeyPath!});
return R.data(pages);
}
/**
* ${table.comment!} 新增
*/
@PostMapping("/save")
@ApiOperationSupport(order = 4)
@Operation(summary = "新增", description = "传入${entityKeyPath!}")
public R save(@Valid @RequestBody ${entityKey!}Entity ${entityKeyPath!}) {
return R.status(${entityKeyPath!}Service.save(${entityKeyPath!}));
}
/**
* ${table.comment!} 修改
*/
@PostMapping("/update")
@ApiOperationSupport(order = 5)
@Operation(summary = "修改", description = "传入${entityKeyPath!}")
public R update(@Valid @RequestBody ${entityKey!}Entity ${entityKeyPath!}) {
return R.status(${entityKeyPath!}Service.updateById(${entityKeyPath!}));
}
/**
* ${table.comment!} 新增或修改
*/
@PostMapping("/submit")
@ApiOperationSupport(order = 6)
@Operation(summary = "新增或修改", description = "传入${entityKeyPath!}")
public R submit(@Valid @RequestBody ${entityKey!}Entity ${entityKeyPath!}) {
return R.status(${entityKeyPath!}Service.saveOrUpdate(${entityKeyPath!}));
}
#if(hasSuperEntity){
/**
* ${table.comment!} 删除
*/
@PostMapping("/remove")
@ApiOperationSupport(order = 7)
@Operation(summary = "逻辑删除", description = "传入ids")
public R remove(@Parameter(description = "主键集合", required = true) @RequestParam String ids) {
return R.status(${entityKeyPath!}Service.deleteLogic(Func.toLongList(ids)));
}
#}else{
/**
* ${table.comment!} 删除
*/
@PostMapping("/remove")
@ApiOperationSupport(order = 7)
@Operation(summary = "删除", description = "传入ids")
public R remove(@Parameter(description = "主键集合", required = true) @RequestParam String ids) {
return R.status(${entityKeyPath!}Service.removeByIds(Func.toLongList(ids)));
}
#}
/**
* 导出数据
*/
@IsAdmin
@GetMapping("/export-${entityKeyPath!}")
@ApiOperationSupport(order = 8)
@Operation(summary = "导出数据", description = "传入${entityKeyPath!}")
public void export${entityKey!}(@Parameter(hidden = true) @RequestParam Map<String, Object> ${entityKeyPath!}, BladeUser bladeUser, HttpServletResponse response) {
QueryWrapper<${entityKey!}Entity> queryWrapper = Condition.getQueryWrapper(${entityKeyPath!}, ${entityKey!}Entity.class);
//if (!AuthUtil.isAdministrator()) {
// queryWrapper.lambda().eq(${entity!}::getTenantId, bladeUser.getTenantId());
//}
//queryWrapper.lambda().eq(${entityKey!}Entity::getIsDeleted, BladeConstant.DB_NOT_DELETED);
List<${entityKey!}Excel> list = ${entityKeyPath!}Service.export${entityKey!}(queryWrapper);
ExcelUtil.export(response, "${table.comment!}数据" + DateUtil.time(), "${table.comment!}数据表", list, ${entityKey!}Excel.class);
}
}

View File

@@ -0,0 +1,100 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package ${package.Entity!};
import lombok.Data;
import io.swagger.v3.oas.annotations.media.Schema;
#for(x in table.importPackages){
#if(isNotEmpty(x)){
#if(hasSuperEntity&&!strutil.contain(x,"Serializable")){
import ${x!};
#}
#if(!hasSuperEntity&&!strutil.contain(x,"TenantEntity")){
import ${x!};
#}
#}
#}
#if(hasSuperEntity){
import lombok.EqualsAndHashCode;
#}else{
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
#}
import java.io.Serial;
/**
* ${table.comment!} 实体类
*
* @author ${author!}
* @since ${date!}
*/
@Data
@TableName("${table.name!}")
@Schema(description = "${entity!}对象")
#if(hasSuperEntity){
@EqualsAndHashCode(callSuper = true)
public class ${entityKey!}Entity extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
#}else{
public class ${entityKey!}Entity implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@JsonSerialize(using = ToStringSerializer.class)
@Schema(description = "主键")
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
#}
#for(x in table.fields) {
#if(hasSuperEntity){
#if(x.propertyName!="id"&&x.propertyName!="createUser"&&x.propertyName!="createDept"&&x.propertyName!="createTime"&&x.propertyName!="updateUser"&&x.propertyName!="updateTime"&&x.propertyName!="status"&&x.propertyName!="isDeleted"&&x.propertyName!="tenantId"){
/**
* ${x.comment!}
*/
@Schema(description = "${x.comment!}")
private ${x.propertyType!} ${x.propertyName!};
#}
#}else{
#if(x.propertyName!="id"){
/**
* ${x.comment!}
*/
@Schema(description = "${x.comment!}")
private ${x.propertyType!} ${x.propertyName!};
#}
#}
#}
}

View File

@@ -0,0 +1,45 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package ${strutil.replace(package.Entity,"entity","dto")};
import ${packageName!}.pojo.entity.${entityKey!}Entity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
/**
* ${table.comment!} 数据传输对象实体类
*
* @author ${author!}
* @since ${date!}
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class ${entityKey!}DTO extends ${entityKey!}Entity {
@Serial
private static final long serialVersionUID = 1L;
}

View File

@@ -0,0 +1,69 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package ${strutil.replace(package.Entity,"pojo.entity","excel")};
import lombok.Data;
#for(x in table.importPackages){
#if(isNotEmpty(x)&&!strutil.contain(x,"TableName")&&!strutil.contain(x,"TenantEntity")){
import ${x!};
#}
#}
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.write.style.ColumnWidth;
import cn.idev.excel.annotation.write.style.ContentRowHeight;
import cn.idev.excel.annotation.write.style.HeadRowHeight;
import java.io.Serial;
/**
* ${table.comment!} Excel实体类
*
* @author ${author!}
* @since ${date!}
*/
@Data
@ColumnWidth(25)
@HeadRowHeight(20)
@ContentRowHeight(18)
public class ${entityKey!}Excel implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
#for(x in table.fields) {
#if(x.propertyName!="createUser"&&x.propertyName!="createDept"&&x.propertyName!="createTime"&&x.propertyName!="updateUser"&&x.propertyName!="updateTime"){
/**
* ${x.comment!}
*/
@ColumnWidth(20)
@ExcelProperty("${x.comment!}")
private ${x.propertyType!} ${x.propertyName!};
#}
#}
}

View File

@@ -0,0 +1,45 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package ${strutil.replace(package.Entity,"entity","vo")};
import ${packageName!}.pojo.entity.${entityKey!}Entity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
/**
* ${table.comment!} 视图实体类
*
* @author ${author!}
* @since ${date!}
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class ${entityKey!}VO extends ${entityKey!}Entity {
@Serial
private static final long serialVersionUID = 1L;
}

View File

@@ -0,0 +1,62 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package ${package.Mapper!};
import ${packageName!}.pojo.entity.${entityKey!}Entity;
import ${packageName!}.pojo.vo.${entityKey!}VO;
import ${packageName!}.excel.${entityKey!}Excel;
import ${superMapperClassPackage!};
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* ${table.comment!} Mapper 接口
*
* @author ${author!}
* @since ${date!}
*/
public interface ${table.mapperName!} extends ${superMapperClass!}<${entityKey!}Entity> {
/**
* 自定义分页
*
* @param page 分页参数
* @param ${entityKeyPath!} 查询参数
* @return List<${entityKey!}VO>
*/
List<${entityKey!}VO> select${entityKey!}Page(IPage page, ${entityKey!}VO ${entityKeyPath!});
/**
* 获取导出数据
*
* @param queryWrapper 查询条件
* @return List<${entityKey!}Excel>
*/
List<${entityKey!}Excel> export${entityKey!}(@Param("ew") Wrapper<${entityKey!}Entity> queryWrapper);
}

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="${package.Mapper!}.${table.mapperName!}">
#if(enableCache){
<!-- 开启二级缓存 -->
<cache type="org.mybatis.caches.ehcache.LoggingEhcache"/>
#}
<!-- 通用查询映射结果 -->
<resultMap id="${entityKeyPath!}ResultMap" type="${package.Entity!}.${entityKey!}Entity">
#for(x in table.fields) {
<result column="${x.name!}" property="${x.propertyName!}"/>
#}
</resultMap>
<select id="select${entityKey!}Page" resultMap="${entityKeyPath!}ResultMap">
select * from ${table.name} where is_deleted = 0
</select>
<select id="export${entityKey!}" resultType="${packageName!}.excel.${entityKey!}Excel">
SELECT * FROM ${table.name!} \${ew.customSqlSegment}
</select>
</mapper>

View File

@@ -0,0 +1,68 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package ${package.Service!};
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import ${packageName!}.pojo.entity.${entityKey!}Entity;
import ${packageName!}.pojo.vo.${entityKey!}VO;
import ${packageName!}.excel.${entityKey!}Excel;
import com.baomidou.mybatisplus.core.metadata.IPage;
#if(hasSuperEntity){
import ${superServiceClassPackage!};
#}else{
import com.baomidou.mybatisplus.extension.service.IService;
#}
import java.util.List;
/**
* ${table.comment!} 服务类
*
* @author ${author!}
* @since ${date!}
*/
#if(hasSuperEntity){
public interface ${table.serviceName!} extends ${superServiceClass!}<${entity!}> {
#}else{
public interface ${table.serviceName!} extends IService<${entity!}> {
#}
/**
* 自定义分页
*
* @param page 分页参数
* @param ${entityKeyPath!} 查询参数
* @return IPage<${entityKey!}VO>
*/
IPage<${entityKey!}VO> select${entityKey!}Page(IPage<${entityKey!}VO> page, ${entityKey!}VO ${entityKeyPath!});
/**
* 导出数据
*
* @param queryWrapper 查询条件
* @return List<${entityKey!}Excel>
*/
List<${entityKey!}Excel> export${entityKey!}(Wrapper<${entityKey!}Entity> queryWrapper);
}

View File

@@ -0,0 +1,70 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package ${package.ServiceImpl!};
import ${packageName!}.pojo.entity.${entityKey!}Entity;
import ${packageName!}.pojo.vo.${entityKey!}VO;
import ${packageName!}.excel.${entityKey!}Excel;
import ${packageName!}.mapper.${table.mapperName!};
import ${packageName!}.service.${table.serviceName!};
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
#if(hasSuperEntity){
import ${superServiceImplClassPackage!};
#}else{
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
#}
import java.util.List;
/**
* ${table.comment!} 服务实现类
*
* @author ${author!}
* @since ${date!}
*/
@Service
#if(hasSuperEntity){
public class ${table.serviceImplName!} extends ${superServiceImplClass!}<${table.mapperName!}, ${entity!}> implements ${table.serviceName!} {
#}else{
public class ${table.serviceImplName!} extends ServiceImpl<${table.mapperName!}, ${entity!}> implements ${table.serviceName!} {
#}
@Override
public IPage<${entityKey!}VO> select${entityKey!}Page(IPage<${entityKey!}VO> page, ${entityKey!}VO ${entityKeyPath!}) {
return page.setRecords(baseMapper.select${entityKey!}Page(page, ${entityKeyPath!}));
}
@Override
public List<${entityKey!}Excel> export${entityKey!}(Wrapper<${entityKey!}Entity> queryWrapper) {
List<${entityKey!}Excel> ${entityKeyPath!}List = baseMapper.export${entityKey!}(queryWrapper);
//${entityKeyPath!}List.forEach(${entityKeyPath!} -> {
// ${entityKeyPath!}.setTypeName(DictCache.getValue(DictEnum.YES_NO, ${entity!}.getType()));
//});
return ${entityKeyPath!}List;
}
}

View File

@@ -0,0 +1,58 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package ${strutil.replace(package.Entity,"pojo.entity","wrapper")};
import org.springblade.core.mp.support.BaseEntityWrapper;
import org.springblade.core.tool.utils.BeanUtil;
import ${packageName!}.pojo.entity.${entityKey!}Entity;
import ${packageName!}.pojo.vo.${entityKey!}VO;
import java.util.Objects;
/**
* ${table.comment!} 包装类,返回视图层所需的字段
*
* @author ${author!}
* @since ${date!}
*/
public class ${entityKey!}Wrapper extends BaseEntityWrapper<${entityKey!}Entity, ${entityKey!}VO> {
public static ${entityKey!}Wrapper build() {
return new ${entityKey!}Wrapper();
}
@Override
public ${entityKey!}VO entityVO(${entityKey!}Entity ${entityKeyPath!}) {
${entityKey!}VO ${entityKeyPath!}VO = Objects.requireNonNull(BeanUtil.copyProperties(${entityKeyPath!}, ${entityKey!}VO.class));
//User createUser = UserCache.getUser(${entityKeyPath!}.getCreateUser());
//User updateUser = UserCache.getUser(${entityKeyPath!}.getUpdateUser());
//${entityKeyPath!}VO.setCreateUserName(createUser.getName());
//${entityKeyPath!}VO.setUpdateUserName(updateUser.getName());
return ${entityKeyPath!}VO;
}
}

View File

@@ -0,0 +1,5 @@
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/bladex?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true
spring.datasource.username=root
spring.datasource.password=root
author=BladeX

View File

@@ -0,0 +1,15 @@
FROM bladex/alpine-java:openjdk17_cn_slim
LABEL maintainer="bladejava@qq.com"
RUN mkdir -p /blade/flow
WORKDIR /blade/flow
EXPOSE 8008
COPY ./target/blade-flow.jar ./app.jar
ENTRYPOINT ["java", "--add-opens", "java.base/java.lang=ALL-UNNAMED", "--add-opens", "java.base/java.lang.reflect=ALL-UNNAMED", "-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar"]
CMD ["--spring.profiles.active=test"]

View File

@@ -0,0 +1,45 @@
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
#driver-class-name: org.postgresql.Driver
#driver-class-name: oracle.jdbc.OracleDriver
#driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
#driver-class-name: dm.jdbc.driver.DmDriver
druid:
# MySql、PostgreSQL、SqlServer、DaMeng校验
validation-query: select 1
# Oracle校验
#validation-query: select 1 from dual
#项目模块集中配置
blade:
#多租户配置
tenant:
#关闭动态数据源功能
dynamic-datasource: false
#关闭动态数据源全局扫描
dynamic-global: false
#工作流模块开发生产环境数据库地址
datasource:
flow:
dev:
# MySql
url: jdbc:mysql://localhost:3306/bladex_flow?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&allowMultiQueries=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true
username: root
password: root
# PostgreSQL
#url: jdbc:postgresql://127.0.0.1:5432/bladex_flow
#username: postgres
#password: 123456
# Oracle
#url: jdbc:oracle:thin:@127.0.0.1:1521:orcl
#username: BLADEX_FLOW
#password: BLADEX_FLOW
# SqlServer
#url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=bladex_flow
#username: bladex_flow
#password: bladex_flow
# DaMeng
#url: jdbc:dm://127.0.0.1:5236/BLADEX_FLOW?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8
#username: BLADEX_FLOW
#password: BLADEX_FLOW

View File

@@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>blade-ops</artifactId>
<groupId>org.springblade</groupId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>blade-flow</artifactId>
<name>${project.artifactId}</name>
<packaging>jar</packaging>
<dependencies>
<!-- Blade -->
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-common</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-core-boot</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-starter-swagger</artifactId>
</dependency>
<!--<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-starter-transaction</artifactId>
</dependency>-->
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-dict-api</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-scope-api</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-core-auto</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-user-api</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-flow-api</artifactId>
</dependency>
<!-- 工作流 -->
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-starter-flowable</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-core-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<configuration>
<skip>${docker.fabric.skip}</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,46 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.flow;
import org.springblade.core.cloud.client.BladeCloudApplication;
import org.springblade.core.launch.BladeApplication;
import org.springblade.core.launch.constant.AppConstant;
/**
* Flowable启动器
*
* @author Chill
*/
//@SeataCloudApplication
@BladeCloudApplication
public class FlowApplication {
public static void main(String[] args) {
BladeApplication.run(AppConstant.APPLICATION_FLOW_NAME, FlowApplication.class, args);
}
}

View File

@@ -0,0 +1,155 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.flow.business.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.flowable.engine.TaskService;
import org.springblade.core.launch.constant.AppConstant;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.tool.api.R;
import org.springblade.flow.business.service.FlowBusinessService;
import org.springblade.flow.core.pojo.entity.BladeFlow;
import org.springblade.flow.core.utils.TaskUtil;
import org.springblade.flow.engine.entity.FlowProcess;
import org.springblade.flow.engine.service.FlowEngineService;
import org.springframework.web.bind.annotation.*;
/**
* 流程事务通用接口
*
* @author Chill
*/
@RestController
@AllArgsConstructor
@RequestMapping("/work")
@Tag(name = "流程事务通用接口", description = "流程事务通用接口")
public class WorkController {
private final TaskService taskService;
private final FlowEngineService flowEngineService;
private final FlowBusinessService flowBusinessService;
/**
* 发起事务列表页
*/
@GetMapping("start-list")
@ApiOperationSupport(order = 1)
@Operation(summary = "发起事务列表页", description = "传入流程类型")
public R<IPage<FlowProcess>> startList(@Parameter(description = "流程类型") String category, Query query, @RequestParam(required = false, defaultValue = "1") Integer mode) {
IPage<FlowProcess> pages = flowEngineService.selectProcessPage(Condition.getPage(query), category, mode);
return R.data(pages);
}
/**
* 待签事务列表页
*/
@GetMapping("claim-list")
@ApiOperationSupport(order = 2)
@Operation(summary = "待签事务列表页", description = "传入流程信息")
public R<IPage<BladeFlow>> claimList(@Parameter(description = "流程信息") BladeFlow bladeFlow, Query query) {
IPage<BladeFlow> pages = flowBusinessService.selectClaimPage(Condition.getPage(query), bladeFlow);
return R.data(pages);
}
/**
* 待办事务列表页
*/
@GetMapping("todo-list")
@ApiOperationSupport(order = 3)
@Operation(summary = "待办事务列表页", description = "传入流程信息")
public R<IPage<BladeFlow>> todoList(@Parameter(description = "流程信息") BladeFlow bladeFlow, Query query) {
IPage<BladeFlow> pages = flowBusinessService.selectTodoPage(Condition.getPage(query), bladeFlow);
return R.data(pages);
}
/**
* 已发事务列表页
*/
@GetMapping("send-list")
@ApiOperationSupport(order = 4)
@Operation(summary = "已发事务列表页", description = "传入流程信息")
public R<IPage<BladeFlow>> sendList(@Parameter(description = "流程信息") BladeFlow bladeFlow, Query query) {
IPage<BladeFlow> pages = flowBusinessService.selectSendPage(Condition.getPage(query), bladeFlow);
return R.data(pages);
}
/**
* 办结事务列表页
*/
@GetMapping("done-list")
@ApiOperationSupport(order = 5)
@Operation(summary = "办结事务列表页", description = "传入流程信息")
public R<IPage<BladeFlow>> doneList(@Parameter(description = "流程信息") BladeFlow bladeFlow, Query query) {
IPage<BladeFlow> pages = flowBusinessService.selectDonePage(Condition.getPage(query), bladeFlow);
return R.data(pages);
}
/**
* 签收事务
*
* @param taskId 任务id
*/
@PostMapping("claim-task")
@ApiOperationSupport(order = 6)
@Operation(summary = "签收事务", description = "传入流程信息")
public R claimTask(@Parameter(description = "任务id") String taskId) {
taskService.claim(taskId, TaskUtil.getTaskUser());
return R.success("签收事务成功");
}
/**
* 完成任务
*
* @param flow 请假信息
*/
@PostMapping("complete-task")
@ApiOperationSupport(order = 7)
@Operation(summary = "完成任务", description = "传入流程信息")
public R completeTask(@Parameter(description = "任务信息") @RequestBody BladeFlow flow) {
return R.status(flowBusinessService.completeTask(flow));
}
/**
* 删除任务
*
* @param taskId 任务id
* @param reason 删除原因
*/
@PostMapping("delete-task")
@ApiOperationSupport(order = 8)
@Operation(summary = "删除任务", description = "传入流程信息")
public R deleteTask(@Parameter(description = "任务id") String taskId, @Parameter(description = "删除原因") String reason) {
taskService.deleteTask(taskId, reason);
return R.success("删除任务成功");
}
}

View File

@@ -0,0 +1,116 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.flow.business.feign;
import lombok.AllArgsConstructor;
import org.flowable.engine.IdentityService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.runtime.ProcessInstance;
import org.springblade.core.tenant.annotation.NonDS;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.support.Kv;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.flow.core.pojo.entity.BladeFlow;
import org.springblade.flow.core.feign.IFlowClient;
import org.springblade.flow.core.utils.TaskUtil;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
/**
* 流程远程调用实现类
*
* @author Chill
*/
@NonDS
@RestController
@AllArgsConstructor
public class FlowClient implements IFlowClient {
private final RuntimeService runtimeService;
private final IdentityService identityService;
private final TaskService taskService;
@Override
@PostMapping(START_PROCESS_INSTANCE_BY_ID)
public R<BladeFlow> startProcessInstanceById(String processDefinitionId, String businessKey, @RequestBody Map<String, Object> variables) {
// 设置流程启动用户
identityService.setAuthenticatedUserId(TaskUtil.getTaskUser());
// 开启流程
ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinitionId, businessKey, variables);
// 组装流程通用类
BladeFlow flow = new BladeFlow();
flow.setProcessInstanceId(processInstance.getId());
return R.data(flow);
}
@Override
@PostMapping(START_PROCESS_INSTANCE_BY_KEY)
public R<BladeFlow> startProcessInstanceByKey(String processDefinitionKey, String businessKey, @RequestBody Map<String, Object> variables) {
// 设置流程启动用户
identityService.setAuthenticatedUserId(TaskUtil.getTaskUser());
// 开启流程
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey, businessKey, variables);
// 组装流程通用类
BladeFlow flow = new BladeFlow();
flow.setProcessInstanceId(processInstance.getId());
return R.data(flow);
}
@Override
@PostMapping(COMPLETE_TASK)
public R completeTask(String taskId, String processInstanceId, String comment, @RequestBody Map<String, Object> variables) {
// 增加评论
if (StringUtil.isNoneBlank(processInstanceId, comment)) {
taskService.addComment(taskId, processInstanceId, comment);
}
// 非空判断
if (Func.isEmpty(variables)) {
variables = Kv.create();
}
// 完成任务
taskService.complete(taskId, variables);
return R.success("流程提交成功");
}
@Override
@GetMapping(TASK_VARIABLE)
public R<Object> taskVariable(String taskId, String variableName) {
return R.data(taskService.getVariable(taskId, variableName));
}
@Override
@GetMapping(TASK_VARIABLES)
public R<Map<String, Object>> taskVariables(String taskId) {
return R.data(taskService.getVariables(taskId));
}
}

View File

@@ -0,0 +1,81 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.flow.business.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.flow.core.pojo.entity.BladeFlow;
/**
* 流程业务类
*
* @author Chill
*/
public interface FlowBusinessService {
/**
* 流程待签列表
*
* @param page 分页工具
* @param bladeFlow 流程类
* @return
*/
IPage<BladeFlow> selectClaimPage(IPage<BladeFlow> page, BladeFlow bladeFlow);
/**
* 流程待办列表
*
* @param page 分页工具
* @param bladeFlow 流程类
* @return
*/
IPage<BladeFlow> selectTodoPage(IPage<BladeFlow> page, BladeFlow bladeFlow);
/**
* 流程已发列表
*
* @param page 分页工具
* @param bladeFlow 流程类
* @return
*/
IPage<BladeFlow> selectSendPage(IPage<BladeFlow> page, BladeFlow bladeFlow);
/**
* 流程办结列表
*
* @param page 分页工具
* @param bladeFlow 流程类
* @return
*/
IPage<BladeFlow> selectDonePage(IPage<BladeFlow> page, BladeFlow bladeFlow);
/**
* 完成任务
*
* @param leave 请假信息
* @return boolean
*/
boolean completeTask(BladeFlow leave);
}

View File

@@ -0,0 +1,342 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.flow.business.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.AllArgsConstructor;
import org.flowable.engine.HistoryService;
import org.flowable.engine.TaskService;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.history.HistoricProcessInstanceQuery;
import org.flowable.task.api.TaskQuery;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.task.api.history.HistoricTaskInstanceQuery;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.support.Kv;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringPool;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.flow.business.service.FlowBusinessService;
import org.springblade.flow.core.constant.ProcessConstant;
import org.springblade.flow.core.pojo.entity.BladeFlow;
import org.springblade.flow.core.utils.TaskUtil;
import org.springblade.flow.engine.constant.FlowEngineConstant;
import org.springblade.flow.engine.entity.FlowProcess;
import org.springblade.flow.engine.utils.FlowCache;
import org.springframework.stereotype.Service;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* 流程业务实现类
*
* @author Chill
*/
@Service
@AllArgsConstructor
public class FlowBusinessServiceImpl implements FlowBusinessService {
private final TaskService taskService;
private final HistoryService historyService;
@Override
public IPage<BladeFlow> selectClaimPage(IPage<BladeFlow> page, BladeFlow bladeFlow) {
String taskUser = TaskUtil.getTaskUser();
String taskGroup = TaskUtil.getCandidateGroup();
List<BladeFlow> flowList = new LinkedList<>();
// 个人等待签收的任务
TaskQuery claimUserQuery = taskService.createTaskQuery().taskCandidateUser(taskUser)
.includeProcessVariables().active().orderByTaskCreateTime().desc();
// 定制流程等待签收的任务
TaskQuery claimRoleWithTenantIdQuery = taskService.createTaskQuery().taskTenantId(AuthUtil.getTenantId()).taskCandidateGroupIn(Func.toStrList(taskGroup))
.includeProcessVariables().active().orderByTaskCreateTime().desc();
// 通用流程等待签收的任务
TaskQuery claimRoleWithoutTenantIdQuery = taskService.createTaskQuery().taskWithoutTenantId().taskCandidateGroupIn(Func.toStrList(taskGroup))
.includeProcessVariables().active().orderByTaskCreateTime().desc();
// 构建列表数据
buildFlowTaskList(bladeFlow, flowList, claimUserQuery, FlowEngineConstant.STATUS_CLAIM);
buildFlowTaskList(bladeFlow, flowList, claimRoleWithTenantIdQuery, FlowEngineConstant.STATUS_CLAIM);
buildFlowTaskList(bladeFlow, flowList, claimRoleWithoutTenantIdQuery, FlowEngineConstant.STATUS_CLAIM);
// 计算总数
long count = claimUserQuery.count() + claimRoleWithTenantIdQuery.count() + claimRoleWithoutTenantIdQuery.count();
// 设置页数
page.setSize(count);
// 设置总数
page.setTotal(count);
// 设置数据
page.setRecords(flowList);
return page;
}
@Override
public IPage<BladeFlow> selectTodoPage(IPage<BladeFlow> page, BladeFlow bladeFlow) {
String taskUser = TaskUtil.getTaskUser();
List<BladeFlow> flowList = new LinkedList<>();
// 已签收的任务
TaskQuery todoQuery = taskService.createTaskQuery().taskAssignee(taskUser).active()
.includeProcessVariables().orderByTaskCreateTime().desc();
// 构建列表数据
buildFlowTaskList(bladeFlow, flowList, todoQuery, FlowEngineConstant.STATUS_TODO);
// 计算总数
long count = todoQuery.count();
// 设置页数
page.setSize(count);
// 设置总数
page.setTotal(count);
// 设置数据
page.setRecords(flowList);
return page;
}
@Override
public IPage<BladeFlow> selectSendPage(IPage<BladeFlow> page, BladeFlow bladeFlow) {
String taskUser = TaskUtil.getTaskUser();
List<BladeFlow> flowList = new LinkedList<>();
HistoricProcessInstanceQuery historyQuery = historyService.createHistoricProcessInstanceQuery().startedBy(taskUser).orderByProcessInstanceStartTime().desc();
if (bladeFlow.getCategory() != null) {
historyQuery.processDefinitionCategory(bladeFlow.getCategory());
}
if (bladeFlow.getProcessDefinitionName() != null) {
historyQuery.processDefinitionName(bladeFlow.getProcessDefinitionName());
}
if (bladeFlow.getBeginDate() != null) {
historyQuery.startedAfter(bladeFlow.getBeginDate());
}
if (bladeFlow.getEndDate() != null) {
historyQuery.startedBefore(bladeFlow.getEndDate());
}
// 查询列表
List<HistoricProcessInstance> historyList = historyQuery.listPage(Func.toInt((page.getCurrent() - 1) * page.getSize()), Func.toInt(page.getSize()));
historyList.forEach(historicProcessInstance -> {
BladeFlow flow = new BladeFlow();
// historicProcessInstance
flow.setCreateTime(historicProcessInstance.getStartTime());
flow.setEndTime(historicProcessInstance.getEndTime());
flow.setVariables(historicProcessInstance.getProcessVariables());
String[] businessKey = Func.toStrArray(StringPool.COLON, historicProcessInstance.getBusinessKey());
if (businessKey.length > 1) {
flow.setBusinessTable(businessKey[0]);
flow.setBusinessId(businessKey[1]);
}
flow.setHistoryActivityName(historicProcessInstance.getName());
flow.setProcessInstanceId(historicProcessInstance.getId());
flow.setHistoryProcessInstanceId(historicProcessInstance.getId());
// ProcessDefinition
FlowProcess processDefinition = FlowCache.getProcessDefinition(historicProcessInstance.getProcessDefinitionId());
flow.setProcessDefinitionId(processDefinition.getId());
flow.setProcessDefinitionName(processDefinition.getName());
flow.setProcessDefinitionVersion(processDefinition.getVersion());
flow.setProcessDefinitionKey(processDefinition.getKey());
flow.setCategory(processDefinition.getCategory());
flow.setCategoryName(FlowCache.getCategoryName(processDefinition.getCategory()));
flow.setProcessInstanceId(historicProcessInstance.getId());
// HistoricTaskInstance
List<HistoricTaskInstance> historyTasks = historyService.createHistoricTaskInstanceQuery().processInstanceId(historicProcessInstance.getId()).orderByHistoricTaskInstanceEndTime().desc().list();
if (Func.isNotEmpty(historyTasks)) {
HistoricTaskInstance historyTask = historyTasks.iterator().next();
flow.setTaskId(historyTask.getId());
flow.setTaskName(historyTask.getName());
flow.setTaskDefinitionKey(historyTask.getTaskDefinitionKey());
}
// Status
if (historicProcessInstance.getEndActivityId() != null) {
flow.setProcessIsFinished(FlowEngineConstant.STATUS_FINISHED);
} else {
flow.setProcessIsFinished(FlowEngineConstant.STATUS_UNFINISHED);
}
flow.setStatus(FlowEngineConstant.STATUS_FINISH);
flowList.add(flow);
});
// 计算总数
long count = historyQuery.count();
// 设置总数
page.setTotal(count);
page.setRecords(flowList);
return page;
}
@Override
public IPage<BladeFlow> selectDonePage(IPage<BladeFlow> page, BladeFlow bladeFlow) {
String taskUser = TaskUtil.getTaskUser();
List<BladeFlow> flowList = new LinkedList<>();
HistoricTaskInstanceQuery doneQuery = historyService.createHistoricTaskInstanceQuery().taskAssignee(taskUser).finished()
.includeProcessVariables().orderByHistoricTaskInstanceEndTime().desc();
if (bladeFlow.getCategory() != null) {
doneQuery.processCategoryIn(Func.toStrList(bladeFlow.getCategory()));
}
if (bladeFlow.getProcessDefinitionName() != null) {
doneQuery.processDefinitionName(bladeFlow.getProcessDefinitionName());
}
if (bladeFlow.getBeginDate() != null) {
doneQuery.taskCompletedAfter(bladeFlow.getBeginDate());
}
if (bladeFlow.getEndDate() != null) {
doneQuery.taskCompletedBefore(bladeFlow.getEndDate());
}
// 查询列表
List<HistoricTaskInstance> doneList = doneQuery.listPage(Func.toInt((page.getCurrent() - 1) * page.getSize()), Func.toInt(page.getSize()));
doneList.forEach(historicTaskInstance -> {
BladeFlow flow = new BladeFlow();
flow.setTaskId(historicTaskInstance.getId());
flow.setTaskDefinitionKey(historicTaskInstance.getTaskDefinitionKey());
flow.setTaskName(historicTaskInstance.getName());
flow.setAssignee(historicTaskInstance.getAssignee());
flow.setCreateTime(historicTaskInstance.getCreateTime());
flow.setExecutionId(historicTaskInstance.getExecutionId());
flow.setHistoryTaskEndTime(historicTaskInstance.getEndTime());
flow.setVariables(historicTaskInstance.getProcessVariables());
FlowProcess processDefinition = FlowCache.getProcessDefinition(historicTaskInstance.getProcessDefinitionId());
flow.setProcessDefinitionId(processDefinition.getId());
flow.setProcessDefinitionName(processDefinition.getName());
flow.setProcessDefinitionKey(processDefinition.getKey());
flow.setProcessDefinitionVersion(processDefinition.getVersion());
flow.setCategory(processDefinition.getCategory());
flow.setCategoryName(FlowCache.getCategoryName(processDefinition.getCategory()));
flow.setProcessInstanceId(historicTaskInstance.getProcessInstanceId());
flow.setHistoryProcessInstanceId(historicTaskInstance.getProcessInstanceId());
HistoricProcessInstance historicProcessInstance = getHistoricProcessInstance((historicTaskInstance.getProcessInstanceId()));
if (Func.isNotEmpty(historicProcessInstance)) {
String[] businessKey = Func.toStrArray(StringPool.COLON, historicProcessInstance.getBusinessKey());
flow.setBusinessTable(businessKey[0]);
flow.setBusinessId(businessKey[1]);
if (historicProcessInstance.getEndActivityId() != null) {
flow.setProcessIsFinished(FlowEngineConstant.STATUS_FINISHED);
} else {
flow.setProcessIsFinished(FlowEngineConstant.STATUS_UNFINISHED);
}
}
flow.setStatus(FlowEngineConstant.STATUS_FINISH);
flowList.add(flow);
});
// 计算总数
long count = doneQuery.count();
// 设置总数
page.setTotal(count);
page.setRecords(flowList);
return page;
}
@Override
public boolean completeTask(BladeFlow flow) {
String taskId = flow.getTaskId();
String processInstanceId = flow.getProcessInstanceId();
String comment = Func.toStr(flow.getComment(), ProcessConstant.PASS_COMMENT);
// 增加评论
if (StringUtil.isNoneBlank(processInstanceId, comment)) {
taskService.addComment(taskId, processInstanceId, comment);
}
// 创建变量
Map<String, Object> variables = flow.getVariables();
if (variables == null) {
variables = Kv.create();
}
variables.put(ProcessConstant.PASS_KEY, flow.isPass());
// 完成任务
taskService.complete(taskId, variables);
return true;
}
/**
* 构建流程
*
* @param bladeFlow 流程通用类
* @param flowList 流程列表
* @param taskQuery 任务查询类
* @param status 状态
*/
private void buildFlowTaskList(BladeFlow bladeFlow, List<BladeFlow> flowList, TaskQuery taskQuery, String status) {
if (bladeFlow.getCategory() != null) {
taskQuery.processCategoryIn(Func.toStrList(bladeFlow.getCategory()));
}
if (bladeFlow.getProcessDefinitionName() != null) {
taskQuery.processDefinitionName(bladeFlow.getProcessDefinitionName());
}
if (bladeFlow.getBeginDate() != null) {
taskQuery.taskCreatedAfter(bladeFlow.getBeginDate());
}
if (bladeFlow.getEndDate() != null) {
taskQuery.taskCreatedBefore(bladeFlow.getEndDate());
}
taskQuery.list().forEach(task -> {
BladeFlow flow = new BladeFlow();
flow.setTaskId(task.getId());
flow.setTaskDefinitionKey(task.getTaskDefinitionKey());
flow.setTaskName(task.getName());
flow.setAssignee(task.getAssignee());
flow.setCreateTime(task.getCreateTime());
flow.setClaimTime(task.getClaimTime());
flow.setExecutionId(task.getExecutionId());
flow.setVariables(task.getProcessVariables());
HistoricProcessInstance historicProcessInstance = getHistoricProcessInstance(task.getProcessInstanceId());
if (Func.isNotEmpty(historicProcessInstance)) {
String[] businessKey = Func.toStrArray(StringPool.COLON, historicProcessInstance.getBusinessKey());
flow.setBusinessTable(businessKey[0]);
flow.setBusinessId(businessKey[1]);
}
FlowProcess processDefinition = FlowCache.getProcessDefinition(task.getProcessDefinitionId());
flow.setCategory(processDefinition.getCategory());
flow.setCategoryName(FlowCache.getCategoryName(processDefinition.getCategory()));
flow.setProcessDefinitionId(processDefinition.getId());
flow.setProcessDefinitionName(processDefinition.getName());
flow.setProcessDefinitionKey(processDefinition.getKey());
flow.setProcessDefinitionVersion(processDefinition.getVersion());
flow.setProcessInstanceId(task.getProcessInstanceId());
flow.setStatus(status);
flowList.add(flow);
});
}
/**
* 获取历史流程
*
* @param processInstanceId 流程实例id
* @return HistoricProcessInstance
*/
private HistoricProcessInstance getHistoricProcessInstance(String processInstanceId) {
return historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
}
}

View File

@@ -0,0 +1,53 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.flow.engine.config;
import lombok.AllArgsConstructor;
import org.flowable.spring.SpringProcessEngineConfiguration;
import org.flowable.spring.boot.EngineConfigurationConfigurer;
import org.flowable.spring.boot.FlowableProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* Flowable配置类
*
* @author Chill
*/
@Configuration(proxyBeanMethods = false)
@AllArgsConstructor
@EnableConfigurationProperties(FlowableProperties.class)
public class FlowableConfiguration implements EngineConfigurationConfigurer<SpringProcessEngineConfiguration> {
private final FlowableProperties flowableProperties;
@Override
public void configure(SpringProcessEngineConfiguration engineConfiguration) {
engineConfiguration.setActivityFontName(flowableProperties.getActivityFontName());
engineConfiguration.setLabelFontName(flowableProperties.getLabelFontName());
engineConfiguration.setAnnotationFontName(flowableProperties.getAnnotationFontName());
}
}

View File

@@ -0,0 +1,61 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.flow.engine.constant;
/**
* 流程常量.
*
* @author zhuangqian
*/
public interface FlowEngineConstant {
String FLOWABLE_BASE_PACKAGES = "org.flowable.ui";
String SUFFIX = ".bpmn20.xml";
String ACTIVE = "active";
String SUSPEND = "suspend";
String STATUS_TODO = "todo";
String STATUS_CLAIM = "claim";
String STATUS_SEND = "send";
String STATUS_DONE = "done";
String STATUS_FINISHED = "finished";
String STATUS_UNFINISHED = "unfinished";
String STATUS_FINISH = "finish";
String START_EVENT = "startEvent";
String END_EVENT = "endEvent";
}

View File

@@ -0,0 +1,80 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.flow.engine.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import lombok.AllArgsConstructor;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.IsAdministrator;
import org.springblade.core.tenant.annotation.NonDS;
import org.springblade.core.tool.api.R;
import org.springblade.flow.engine.entity.FlowExecution;
import org.springblade.flow.engine.service.FlowEngineService;
import org.springframework.web.bind.annotation.*;
/**
* 流程状态控制器
*
* @author Chill
*/
@NonDS
@RestController
@RequestMapping("/follow")
@AllArgsConstructor
@IsAdministrator
@Hidden
public class FlowFollowController {
private final FlowEngineService flowEngineService;
/**
* 流程状态列表
*/
@GetMapping("list")
@ApiOperationSupport(order = 1)
@Operation(summary = "分页", description = "传入notice")
public R<IPage<FlowExecution>> list(Query query, @Parameter(description = "流程实例id") String processInstanceId, @Parameter(description = "流程key") String processDefinitionKey) {
IPage<FlowExecution> pages = flowEngineService.selectFollowPage(Condition.getPage(query), processInstanceId, processDefinitionKey);
return R.data(pages);
}
/**
* 删除流程实例
*/
@PostMapping("delete-process-instance")
@ApiOperationSupport(order = 2)
@Operation(summary = "删除", description = "传入主键集合")
public R deleteProcessInstance(@Parameter(description = "流程实例id") @RequestParam String processInstanceId, @Parameter(description = "删除原因") @RequestParam String deleteReason) {
boolean temp = flowEngineService.deleteProcessInstance(processInstanceId, deleteReason);
return R.status(temp);
}
}

View File

@@ -0,0 +1,132 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.flow.engine.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.IsAdministrator;
import org.springblade.core.tenant.annotation.NonDS;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.support.Kv;
import org.springblade.core.tool.utils.Func;
import org.springblade.flow.engine.constant.FlowEngineConstant;
import org.springblade.flow.engine.entity.FlowProcess;
import org.springblade.flow.engine.service.FlowEngineService;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
import java.util.Objects;
/**
* 流程管理接口
*
* @author Chill
*/
@NonDS
@RestController
@RequestMapping("/manager")
@AllArgsConstructor
@Tag(name = "流程管理接口", description = "流程管理接口")
@IsAdministrator
@Hidden
public class FlowManagerController {
private final FlowEngineService flowEngineService;
/**
* 分页
*/
@GetMapping("list")
@ApiOperationSupport(order = 1)
@Operation(summary = "分页", description = "传入流程类型")
public R<IPage<FlowProcess>> list(@Parameter(description = "流程类型") String category, Query query, @RequestParam(required = false, defaultValue = "1") Integer mode) {
IPage<FlowProcess> pages = flowEngineService.selectProcessPage(Condition.getPage(query), category, mode);
return R.data(pages);
}
/**
* 变更流程状态
*
* @param state 状态
* @param processId 流程id
*/
@PostMapping("change-state")
@ApiOperationSupport(order = 2)
@Operation(summary = "变更流程状态", description = "传入state,processId")
public R changeState(@RequestParam String state, @RequestParam String processId) {
String msg = flowEngineService.changeState(state, processId);
return R.success(msg);
}
/**
* 删除部署流程
*
* @param deploymentIds 部署流程id集合
*/
@PostMapping("delete-deployment")
@ApiOperationSupport(order = 3)
@Operation(summary = "删除部署流程", description = "部署流程id集合")
public R deleteDeployment(String deploymentIds) {
return R.status(flowEngineService.deleteDeployment(deploymentIds));
}
/**
* 检查流程文件格式
*
* @param file 流程文件
*/
@PostMapping("check-upload")
@ApiOperationSupport(order = 4)
@Operation(summary = "上传部署流程文件", description = "传入文件")
public R checkUpload(@RequestParam MultipartFile file) {
boolean temp = Objects.requireNonNull(file.getOriginalFilename()).endsWith(FlowEngineConstant.SUFFIX);
return R.data(Kv.create().set("name", file.getOriginalFilename()).set("success", temp));
}
/**
* 上传部署流程文件
*
* @param files 流程文件
* @param category 类型
*/
@PostMapping("deploy-upload")
@ApiOperationSupport(order = 5)
@Operation(summary = "上传部署流程文件", description = "传入文件")
public R deployUpload(@RequestParam List<MultipartFile> files,
@RequestParam String category,
@RequestParam(required = false, defaultValue = "") String tenantIds) {
return R.status(flowEngineService.deployUpload(files, category, Func.toStrList(tenantIds)));
}
}

View File

@@ -0,0 +1,131 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.flow.engine.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.IsAdministrator;
import org.springblade.core.tenant.annotation.NonDS;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.xss.annotation.XssIgnore;
import org.springblade.flow.engine.entity.FlowModel;
import org.springblade.flow.engine.service.FlowEngineService;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
/**
* 流程模型控制器
*
* @author Chill
*/
@NonDS
@RestController
@RequestMapping("/model")
@AllArgsConstructor
@IsAdministrator
@Hidden
public class FlowModelController {
private final FlowEngineService flowEngineService;
/**
* 分页
*/
@GetMapping("/list")
@Parameters({
@Parameter(name = "modelKey", description = "模型标识", in = ParameterIn.QUERY, schema = @Schema(type = "string")),
@Parameter(name = "name", description = "模型名称", in = ParameterIn.QUERY, schema = @Schema(type = "string"))
})
@ApiOperationSupport(order = 1)
@Operation(summary = "分页", description = "传入notice")
public R<IPage<FlowModel>> list(@Parameter(hidden = true) @RequestParam Map<String, Object> flow, Query query) {
IPage<FlowModel> pages = flowEngineService.page(Condition.getPage(query), Condition.getQueryWrapper(flow, FlowModel.class)
.select("id,model_key modelKey,name,description,version,created,last_updated lastUpdated")
.orderByDesc("last_updated"));
return R.data(pages);
}
/**
* 删除
*/
@PostMapping("/remove")
@ApiOperationSupport(order = 2)
@Operation(summary = "删除", description = "传入主键集合")
public R remove(@Parameter(description = "主键集合") @RequestParam String ids) {
boolean temp = flowEngineService.removeByIds(Func.toStrList(ids));
return R.status(temp);
}
/**
* 部署
*/
@PostMapping("/deploy")
@ApiOperationSupport(order = 3)
@Operation(summary = "部署", description = "传入模型id和分类")
public R deploy(@Parameter(description = "模型id") @RequestParam String modelId,
@Parameter(description = "工作流分类") @RequestParam String category,
@Parameter(description = "租户ID") @RequestParam(required = false, defaultValue = "") String tenantIds) {
boolean temp = flowEngineService.deployModel(modelId, category, Func.toStrList(tenantIds));
return R.status(temp);
}
@XssIgnore
@PostMapping("submit")
@ApiOperationSupport(order = 4)
@Operation(summary = "保存/编辑")
@Parameters({
@Parameter(name = "id", description = "模型id"),
@Parameter(name = "name", description = "模型名称", required = true),
@Parameter(name = "modelKey", description = "模型key", required = true),
@Parameter(name = "description", description = "模型描述"),
@Parameter(name = "xml", description = "模型xml", required = true),
})
public R<FlowModel> submit(@RequestBody @Parameter(hidden = true) FlowModel model) {
return R.data(flowEngineService.submitModel(model));
}
@GetMapping("detail")
@Operation(summary = "详情")
@ApiOperationSupport(order = 5)
@Parameters({
@Parameter(name = "id", description = "模型id", required = true),
})
public R<FlowModel> detail(String id) {
return R.data(flowEngineService.getById(id));
}
}

View File

@@ -0,0 +1,107 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.flow.engine.controller;
import io.swagger.v3.oas.annotations.Hidden;
import jakarta.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.launch.constant.AppConstant;
import org.springblade.core.tenant.annotation.NonDS;
import org.springblade.core.tool.api.R;
import org.springblade.flow.core.pojo.entity.BladeFlow;
import org.springblade.flow.engine.service.FlowEngineService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 流程通用控制器
*
* @author Chill
*/
@NonDS
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/process")
@Hidden
public class FlowProcessController {
private static final String IMAGE_NAME = "image";
private final FlowEngineService flowEngineService;
/**
* 获取流转历史列表
*
* @param processInstanceId 流程实例id
* @param startActivityId 开始节点id
* @param endActivityId 结束节点id
*/
@GetMapping(value = "history-flow-list")
public R<List<BladeFlow>> historyFlowList(@RequestParam String processInstanceId, String startActivityId, String endActivityId) {
return R.data(flowEngineService.historyFlowList(processInstanceId, startActivityId, endActivityId));
}
/**
* 流程节点进程图
*
* @param processDefinitionId 流程id
* @param processInstanceId 流程实例id
*/
@GetMapping(value = "model-view")
public R modelView(String processDefinitionId, String processInstanceId) {
return R.data(flowEngineService.modelView(processDefinitionId, processInstanceId));
}
/**
* 流程节点进程图
*
* @param processInstanceId 流程实例id
* @param httpServletResponse http响应
*/
@GetMapping(value = "diagram-view")
public void diagramView(String processInstanceId, HttpServletResponse httpServletResponse) {
flowEngineService.diagramView(processInstanceId, httpServletResponse);
}
/**
* 流程图展示
*
* @param processDefinitionId 流程id
* @param processInstanceId 实例id
* @param resourceType 资源类型
* @param response 响应
*/
@GetMapping("resource-view")
public void resourceView(@RequestParam String processDefinitionId, String processInstanceId, @RequestParam(defaultValue = IMAGE_NAME) String resourceType, HttpServletResponse response) {
flowEngineService.resourceView(processDefinitionId, processInstanceId, resourceType, response);
}
}

View File

@@ -0,0 +1,61 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.flow.engine.entity;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 运行实体类
*
* @author Chill
*/
@Data
public class FlowExecution implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private String id;
private String name;
private String startUserId;
private String startUser;
private Date startTime;
private String taskDefinitionId;
private String taskDefinitionKey;
private String category;
private String categoryName;
private String processInstanceId;
private String processDefinitionId;
private String processDefinitionKey;
private String activityId;
private int suspensionState;
private String executionId;
}

View File

@@ -0,0 +1,69 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.flow.engine.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 流程模型
*
* @author Chill
*/
@Data
@TableName("ACT_DE_MODEL")
public class FlowModel implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
public static final int MODEL_TYPE_BPMN = 0;
public static final int MODEL_TYPE_FORM = 2;
public static final int MODEL_TYPE_APP = 3;
public static final int MODEL_TYPE_DECISION_TABLE = 4;
public static final int MODEL_TYPE_CMMN = 5;
private String id;
private String name;
private String modelKey;
private String description;
private Date created;
private Date lastUpdated;
private String createdBy;
private String lastUpdatedBy;
private Integer version;
private String modelEditorJson;
private String modelComment;
private Integer modelType;
private String tenantId;
private byte[] thumbnail;
private String modelEditorXml;
}

View File

@@ -0,0 +1,74 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.flow.engine.entity;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.flowable.engine.impl.persistence.entity.ProcessDefinitionEntityImpl;
import org.springblade.flow.engine.utils.FlowCache;
import java.io.Serializable;
import java.util.Date;
/**
* FlowProcess
*
* @author Chill
*/
@Data
@NoArgsConstructor
public class FlowProcess implements Serializable {
private String id;
private String tenantId;
private String name;
private String key;
private String category;
private String categoryName;
private Integer version;
private String deploymentId;
private String resourceName;
private String diagramResourceName;
private Integer suspensionState;
private Date deploymentTime;
public FlowProcess(ProcessDefinitionEntityImpl entity) {
if (entity != null) {
this.id = entity.getId();
this.tenantId = entity.getTenantId();
this.name = entity.getName();
this.key = entity.getKey();
this.category = entity.getCategory();
this.categoryName = FlowCache.getCategoryName(entity.getCategory());
this.version = entity.getVersion();
this.deploymentId = entity.getDeploymentId();
this.resourceName = entity.getResourceName();
this.diagramResourceName = entity.getDiagramResourceName();
this.suspensionState = entity.getSuspensionState();
}
}
}

View File

@@ -0,0 +1,55 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.flow.engine.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.flow.engine.entity.FlowModel;
import java.util.List;
/**
* FlowMapper.
*
* @author Chill
*/
public interface FlowMapper extends BaseMapper<FlowModel> {
/**
* 自定义分页
* @param page
* @param flowModel
* @return
*/
List<FlowModel> selectFlowPage(IPage page, FlowModel flowModel);
/**
* 获取模型
* @param parentModelId
* @return
*/
List<FlowModel> findByParentModelId(String parentModelId);
}

View File

@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.springblade.flow.engine.mapper.FlowMapper">
<!-- 通用查询映射结果 -->
<resultMap id="flowModelResultMap" type="org.springblade.flow.engine.entity.FlowModel">
<result column="id" property="id"/>
<result column="name" property="name"/>
<result column="model_key" property="modelKey"/>
<result column="description" property="description"/>
<result column="model_comment" property="modelComment"/>
<result column="created" property="created"/>
<result column="created_by" property="createdBy"/>
<result column="last_updated" property="lastUpdated"/>
<result column="last_updated_by" property="lastUpdatedBy"/>
<result column="version" property="version"/>
<result column="model_editor_json" property="modelEditorJson"/>
<result column="thumbnail" property="thumbnail"/>
<result column="model_type" property="modelType"/>
<result column="tenant_id" property="tenantId"/>
</resultMap>
<select id="selectFlowPage" resultMap="flowModelResultMap">
SELECT
a.id,
a.name,
a.model_key,
a.description,
a.model_comment,
a.created,
a.created_by,
a.last_updated,
a.last_updated_by,
a.version,
a.model_editor_json,
a.thumbnail,
a.model_type,
a.tenant_id
FROM
ACT_DE_MODEL a
WHERE
1 = 1
ORDER BY
a.created DESC
</select>
<select id="findByParentModelId" parameterType="string" resultMap="flowModelResultMap">
select model.* from ACT_DE_MODEL_RELATION modelrelation
inner join ACT_DE_MODEL model on modelrelation.model_id = model.id
where modelrelation.parent_model_id = #{_parameter}
</select>
</mapper>

View File

@@ -0,0 +1,174 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.flow.engine.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import jakarta.servlet.http.HttpServletResponse;
import org.springblade.flow.core.pojo.entity.BladeFlow;
import org.springblade.flow.engine.entity.FlowExecution;
import org.springblade.flow.engine.entity.FlowModel;
import org.springblade.flow.engine.entity.FlowProcess;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
import java.util.Map;
/**
* FlowEngineService
*
* @author Chill
*/
public interface FlowEngineService extends IService<FlowModel> {
/**
* 自定义分页
*
* @param page 分页工具
* @param flowModel 流程模型
* @return
*/
IPage<FlowModel> selectFlowPage(IPage<FlowModel> page, FlowModel flowModel);
/**
* 流程管理列表
*
* @param page 分页工具
* @param category 分类
* @param mode 形态
* @return
*/
IPage<FlowProcess> selectProcessPage(IPage<FlowProcess> page, String category, Integer mode);
/**
* 流程管理列表
*
* @param page 分页工具
* @param processInstanceId 流程实例id
* @param processDefinitionKey 流程key
* @return
*/
IPage<FlowExecution> selectFollowPage(IPage<FlowExecution> page, String processInstanceId, String processDefinitionKey);
/**
* 获取流转历史列表
*
* @param processInstanceId 流程实例id
* @param startActivityId 开始节点id
* @param endActivityId 结束节点id
* @return
*/
List<BladeFlow> historyFlowList(String processInstanceId, String startActivityId, String endActivityId);
/**
* 变更流程状态
*
* @param state 状态
* @param processId 流程ID
* @return
*/
String changeState(String state, String processId);
/**
* 删除部署流程
*
* @param deploymentIds 部署流程id集合
* @return
*/
boolean deleteDeployment(String deploymentIds);
/**
* 上传部署流程
*
* @param files 流程配置文件
* @param category 流程分类
* @param tenantIdList 租户id集合
* @return
*/
boolean deployUpload(List<MultipartFile> files, String category, List<String> tenantIdList);
/**
* 部署流程
*
* @param modelId 模型id
* @param category 分类
* @param tenantIdList 租户id集合
* @return
*/
boolean deployModel(String modelId, String category, List<String> tenantIdList);
/**
* 删除流程实例
*
* @param processInstanceId 流程实例id
* @param deleteReason 删除原因
* @return
*/
boolean deleteProcessInstance(String processInstanceId, String deleteReason);
/**
* 保存/更新模型
*
* @param model 模型
* @return 模型
*/
FlowModel submitModel(FlowModel model);
/**
* 流程节点进程图
*
* @param processDefinitionId
* @param processInstanceId
* @return
*/
Map<String, Object> modelView(String processDefinitionId, String processInstanceId);
/**
* 流程节点进程图
*
* @param processInstanceId
* @param httpServletResponse
*/
void diagramView(String processInstanceId, HttpServletResponse httpServletResponse);
/**
* 流程图展示
*
* @param processDefinitionId
* @param processInstanceId
* @param resourceType
* @param response
*/
void resourceView(String processDefinitionId, String processInstanceId, String resourceType, HttpServletResponse response);
/**
* 获取XML
*
* @param model
* @return
*/
byte[] getModelEditorXML(FlowModel model);
}

View File

@@ -0,0 +1,568 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.flow.engine.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import jakarta.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.converter.BpmnXMLConverter;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.Process;
import org.flowable.common.engine.impl.util.IoUtil;
import org.flowable.common.engine.impl.util.io.StringStreamSource;
import org.flowable.editor.language.json.converter.BpmnJsonConverter;
import org.flowable.editor.language.json.converter.BpmnJsonConverterContext;
import org.flowable.editor.language.json.converter.CustomBpmnJsonConverterContext;
import org.flowable.engine.*;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.impl.persistence.entity.ExecutionEntityImpl;
import org.flowable.engine.impl.persistence.entity.ProcessDefinitionEntityImpl;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.repository.ProcessDefinitionQuery;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.engine.runtime.ProcessInstanceQuery;
import org.flowable.engine.task.Comment;
import org.flowable.image.ProcessDiagramGenerator;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.FileUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.flow.core.pojo.entity.BladeFlow;
import org.springblade.flow.core.pojo.enums.FlowModeEnum;
import org.springblade.flow.core.utils.TaskUtil;
import org.springblade.flow.engine.constant.FlowEngineConstant;
import org.springblade.flow.engine.entity.FlowExecution;
import org.springblade.flow.engine.entity.FlowModel;
import org.springblade.flow.engine.entity.FlowProcess;
import org.springblade.flow.engine.mapper.FlowMapper;
import org.springblade.flow.engine.service.FlowEngineService;
import org.springblade.flow.engine.utils.FlowCache;
import org.springblade.system.cache.UserCache;
import org.springblade.system.pojo.entity.User;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.*;
/**
* 工作流服务实现类
*
* @author Chill
*/
@Slf4j
@Service
@AllArgsConstructor
public class FlowEngineServiceImpl extends ServiceImpl<FlowMapper, FlowModel> implements FlowEngineService {
private static final String ALREADY_IN_STATE = "already in state";
private static final String USR_TASK = "userTask";
private static final String IMAGE_NAME = "image";
private static final String XML_NAME = "xml";
private static final Integer INT_1024 = 1024;
private static final BpmnJsonConverter BPMN_JSON_CONVERTER = new BpmnJsonConverter();
private static final BpmnXMLConverter BPMN_XML_CONVERTER = new BpmnXMLConverter();
private final ObjectMapper objectMapper;
private final RepositoryService repositoryService;
private final RuntimeService runtimeService;
private final HistoryService historyService;
private final TaskService taskService;
private final ProcessEngine processEngine;
@Override
public IPage<FlowModel> selectFlowPage(IPage<FlowModel> page, FlowModel flowModel) {
return page.setRecords(baseMapper.selectFlowPage(page, flowModel));
}
@Override
public IPage<FlowProcess> selectProcessPage(IPage<FlowProcess> page, String category, Integer mode) {
ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery().latestVersion().orderByProcessDefinitionKey().asc();
// 通用流程
if (mode == FlowModeEnum.COMMON.getMode()) {
processDefinitionQuery.processDefinitionWithoutTenantId();
}
// 定制流程
else if (!AuthUtil.isAdministrator()) {
processDefinitionQuery.processDefinitionTenantId(AuthUtil.getTenantId());
}
if (StringUtils.isNotEmpty(category)) {
processDefinitionQuery.processDefinitionCategory(category);
}
List<ProcessDefinition> processDefinitionList = processDefinitionQuery.listPage(Func.toInt((page.getCurrent() - 1) * page.getSize()), Func.toInt(page.getSize()));
List<FlowProcess> flowProcessList = new ArrayList<>();
processDefinitionList.forEach(processDefinition -> {
String deploymentId = processDefinition.getDeploymentId();
Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult();
FlowProcess flowProcess = new FlowProcess((ProcessDefinitionEntityImpl) processDefinition);
flowProcess.setDeploymentTime(deployment.getDeploymentTime());
flowProcessList.add(flowProcess);
});
page.setTotal(processDefinitionQuery.count());
page.setRecords(flowProcessList);
return page;
}
@Override
public IPage<FlowExecution> selectFollowPage(IPage<FlowExecution> page, String processInstanceId, String processDefinitionKey) {
ProcessInstanceQuery processInstanceQuery = runtimeService.createProcessInstanceQuery();
if (StringUtil.isNotBlank(processInstanceId)) {
processInstanceQuery.processInstanceId(processInstanceId);
}
if (StringUtil.isNotBlank(processDefinitionKey)) {
processInstanceQuery.processDefinitionKey(processDefinitionKey);
}
List<FlowExecution> flowList = new ArrayList<>();
List<ProcessInstance> procInsList = processInstanceQuery.listPage(Func.toInt((page.getCurrent() - 1) * page.getSize()), Func.toInt(page.getSize()));
procInsList.forEach(processInstance -> {
ExecutionEntityImpl execution = (ExecutionEntityImpl) processInstance;
FlowExecution flowExecution = new FlowExecution();
flowExecution.setId(execution.getId());
flowExecution.setName(execution.getName());
flowExecution.setStartUserId(execution.getStartUserId());
User taskUser = UserCache.getUserByTaskUser(execution.getStartUserId());
if (taskUser != null) {
flowExecution.setStartUser(taskUser.getName());
}
flowExecution.setStartTime(execution.getStartTime());
flowExecution.setExecutionId(execution.getId());
flowExecution.setProcessInstanceId(execution.getProcessInstanceId());
flowExecution.setProcessDefinitionId(execution.getProcessDefinitionId());
flowExecution.setProcessDefinitionKey(execution.getProcessDefinitionKey());
flowExecution.setSuspensionState(execution.getSuspensionState());
FlowProcess processDefinition = FlowCache.getProcessDefinition(execution.getProcessDefinitionId());
flowExecution.setCategory(processDefinition.getCategory());
flowExecution.setCategoryName(FlowCache.getCategoryName(processDefinition.getCategory()));
flowList.add(flowExecution);
});
page.setTotal(processInstanceQuery.count());
page.setRecords(flowList);
return page;
}
@Override
public List<BladeFlow> historyFlowList(String processInstanceId, String startActivityId, String endActivityId) {
List<BladeFlow> flowList = new LinkedList<>();
List<HistoricActivityInstance> historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).orderByHistoricActivityInstanceStartTime().asc().orderByHistoricActivityInstanceEndTime().asc().list();
boolean start = false;
Map<String, Integer> activityMap = new HashMap<>(16);
for (int i = 0; i < historicActivityInstanceList.size(); i++) {
HistoricActivityInstance historicActivityInstance = historicActivityInstanceList.get(i);
// 过滤开始节点前的节点
if (StringUtil.isNotBlank(startActivityId) && startActivityId.equals(historicActivityInstance.getActivityId())) {
start = true;
}
if (StringUtil.isNotBlank(startActivityId) && !start) {
continue;
}
// 显示开始节点和结束节点,并且执行人不为空的任务
if (StringUtils.equals(USR_TASK, historicActivityInstance.getActivityType())
|| FlowEngineConstant.START_EVENT.equals(historicActivityInstance.getActivityType())
|| FlowEngineConstant.END_EVENT.equals(historicActivityInstance.getActivityType())) {
// 给节点增加序号
activityMap.computeIfAbsent(historicActivityInstance.getActivityId(), k -> activityMap.size());
BladeFlow flow = new BladeFlow();
flow.setHistoryActivityId(historicActivityInstance.getActivityId());
flow.setHistoryActivityName(historicActivityInstance.getActivityName());
flow.setCreateTime(historicActivityInstance.getStartTime());
flow.setEndTime(historicActivityInstance.getEndTime());
String durationTime = DateUtil.secondToTime(Func.toLong(historicActivityInstance.getDurationInMillis(), 0L) / 1000);
flow.setHistoryActivityDurationTime(durationTime);
// 获取流程发起人名称
if (FlowEngineConstant.START_EVENT.equals(historicActivityInstance.getActivityType())) {
List<HistoricProcessInstance> processInstanceList = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).orderByProcessInstanceStartTime().asc().list();
if (!processInstanceList.isEmpty()) {
if (StringUtil.isNotBlank(processInstanceList.get(0).getStartUserId())) {
String taskUser = processInstanceList.get(0).getStartUserId();
User user = UserCache.getUser(TaskUtil.getUserId(taskUser));
if (user != null) {
flow.setAssignee(historicActivityInstance.getAssignee());
flow.setAssigneeName(user.getName());
}
}
}
}
// 获取任务执行人名称
if (StringUtil.isNotBlank(historicActivityInstance.getAssignee())) {
User user = UserCache.getUser(TaskUtil.getUserId(historicActivityInstance.getAssignee()));
if (user != null) {
flow.setAssignee(historicActivityInstance.getAssignee());
flow.setAssigneeName(user.getName());
}
}
// 获取意见评论内容
if (StringUtil.isNotBlank(historicActivityInstance.getTaskId())) {
List<Comment> commentList = taskService.getTaskComments(historicActivityInstance.getTaskId());
if (!commentList.isEmpty()) {
flow.setComment(commentList.get(0).getFullMessage());
}
}
flowList.add(flow);
}
// 过滤结束节点后的节点
if (StringUtils.isNotBlank(endActivityId) && endActivityId.equals(historicActivityInstance.getActivityId())) {
boolean temp = false;
Integer activityNum = activityMap.get(historicActivityInstance.getActivityId());
// 该活动节点,后续节点是否在结束节点之前,在后续节点中是否存在
for (int j = i + 1; j < historicActivityInstanceList.size(); j++) {
HistoricActivityInstance hi = historicActivityInstanceList.get(j);
Integer activityNumA = activityMap.get(hi.getActivityId());
boolean numberTemp = activityNumA != null && activityNumA < activityNum;
boolean equalsTemp = StringUtils.equals(hi.getActivityId(), historicActivityInstance.getActivityId());
if (numberTemp || equalsTemp) {
temp = true;
}
}
if (!temp) {
break;
}
}
}
return flowList;
}
@Override
public String changeState(String state, String processId) {
try {
if (state.equals(FlowEngineConstant.ACTIVE)) {
repositoryService.activateProcessDefinitionById(processId, true, null);
return StringUtil.format("激活ID为 [{}] 的流程成功", processId);
} else if (state.equals(FlowEngineConstant.SUSPEND)) {
repositoryService.suspendProcessDefinitionById(processId, true, null);
return StringUtil.format("挂起ID为 [{}] 的流程成功", processId);
} else {
return "暂无流程变更";
}
} catch (Exception e) {
if (e.getMessage().contains(ALREADY_IN_STATE)) {
return StringUtil.format("ID为 [{}] 的流程已是此状态,无需操作", processId);
}
return e.getMessage();
}
}
@Override
public boolean deleteDeployment(String deploymentIds) {
Func.toStrList(deploymentIds).forEach(deploymentId -> repositoryService.deleteDeployment(deploymentId, true));
return true;
}
@Override
public boolean deployUpload(List<MultipartFile> files, String category, List<String> tenantIdList) {
files.forEach(file -> {
try {
String fileName = file.getOriginalFilename();
InputStream fileInputStream = file.getInputStream();
byte[] bytes = FileUtil.copyToByteArray(fileInputStream);
if (Func.isNotEmpty(tenantIdList)) {
tenantIdList.forEach(tenantId -> {
Deployment deployment = repositoryService.createDeployment().addBytes(fileName, bytes).tenantId(tenantId).deploy();
deploy(deployment, category);
});
} else {
Deployment deployment = repositoryService.createDeployment().addBytes(fileName, bytes).deploy();
deploy(deployment, category);
}
} catch (IOException e) {
e.printStackTrace();
}
});
return true;
}
@Override
public boolean deployModel(String modelId, String category, List<String> tenantIdList) {
FlowModel model = this.getById(modelId);
if (model == null) {
throw new ServiceException("未找到模型 id: " + modelId);
}
byte[] bytes = getBpmnXML(model);
String processName = model.getName();
if (!StringUtil.endsWithIgnoreCase(processName, FlowEngineConstant.SUFFIX)) {
processName += FlowEngineConstant.SUFFIX;
}
String finalProcessName = processName;
if (Func.isNotEmpty(tenantIdList)) {
tenantIdList.forEach(tenantId -> {
Deployment deployment = repositoryService.createDeployment().addBytes(finalProcessName, bytes).name(model.getName()).key(model.getModelKey()).tenantId(tenantId).deploy();
deploy(deployment, category);
});
} else {
Deployment deployment = repositoryService.createDeployment().addBytes(finalProcessName, bytes).name(model.getName()).key(model.getModelKey()).deploy();
deploy(deployment, category);
}
return true;
}
@Override
public boolean deleteProcessInstance(String processInstanceId, String deleteReason) {
runtimeService.deleteProcessInstance(processInstanceId, deleteReason);
return true;
}
private void deploy(Deployment deployment, String category) {
log.debug("流程部署--------deploy: " + deployment + " 分类---------->" + category);
List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).list();
StringBuilder logBuilder = new StringBuilder(500);
List<Object> logArgs = new ArrayList<>();
// 设置流程分类
for (ProcessDefinition processDefinition : list) {
if (StringUtil.isNotBlank(category)) {
repositoryService.setProcessDefinitionCategory(processDefinition.getId(), category);
}
logBuilder.append("部署成功,流程ID={} \n");
logArgs.add(processDefinition.getId());
}
if (list.isEmpty()) {
throw new ServiceException("部署失败,未找到流程");
} else {
log.info(logBuilder.toString(), logArgs.toArray());
}
}
@Override
public FlowModel submitModel(FlowModel model) {
FlowModel flowModel = new FlowModel();
flowModel.setId(model.getId());
flowModel.setVersion(Func.toInt(model.getVersion(), 0) + 1);
flowModel.setName(model.getName());
flowModel.setModelKey(model.getModelKey());
flowModel.setModelType(FlowModel.MODEL_TYPE_BPMN);
flowModel.setCreatedBy(TaskUtil.getTaskUser());
flowModel.setDescription(model.getDescription());
flowModel.setLastUpdated(Calendar.getInstance().getTime());
flowModel.setLastUpdatedBy(TaskUtil.getTaskUser());
flowModel.setTenantId(AuthUtil.getTenantId());
flowModel.setModelEditorXml(model.getModelEditorXml());
if (StringUtil.isBlank(model.getId())) {
flowModel.setCreated(Calendar.getInstance().getTime());
}
if (StringUtil.isNotBlank(model.getModelEditorXml())) {
flowModel.setModelEditorJson(getBpmnJson(model.getModelEditorXml()));
}
this.saveOrUpdate(flowModel);
return flowModel;
}
@Override
public Map<String, Object> modelView(String processDefinitionId, String processInstanceId) {
Map<String, Object> result = new HashMap<>();
// 节点标记
if (StringUtil.isNotBlank(processInstanceId)) {
result.put("flow", this.historyFlowList(processInstanceId, null, null));
HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery()
.processInstanceId(processInstanceId)
.singleResult();
processDefinitionId = processInstance.getProcessDefinitionId();
}
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
// 流程图展示
result.put("xml", new String(new BpmnXMLConverter().convertToXML(bpmnModel)));
return result;
}
@Override
public void diagramView(String processInstanceId, HttpServletResponse httpServletResponse) {
// 获得当前活动的节点
String processDefinitionId;
// 如果流程已经结束,则得到结束节点
if (this.isFinished(processInstanceId)) {
HistoricProcessInstance pi = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
processDefinitionId = pi.getProcessDefinitionId();
} else {
// 如果流程没有结束,则取当前活动节点
// 根据流程实例ID获得当前处于活动状态的ActivityId合集
ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
processDefinitionId = pi.getProcessDefinitionId();
}
List<String> highLightedActivities = new ArrayList<>();
// 获得活动的节点
List<HistoricActivityInstance> highLightedActivityList = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).orderByHistoricActivityInstanceStartTime().asc().list();
for (HistoricActivityInstance tempActivity : highLightedActivityList) {
String activityId = tempActivity.getActivityId();
highLightedActivities.add(activityId);
}
List<String> flows = new ArrayList<>();
// 获取流程图
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
ProcessEngineConfiguration engConf = processEngine.getProcessEngineConfiguration();
ProcessDiagramGenerator diagramGenerator = engConf.getProcessDiagramGenerator();
InputStream in = diagramGenerator.generateDiagram(bpmnModel, "bmp", highLightedActivities, flows, engConf.getActivityFontName(),
engConf.getLabelFontName(), engConf.getAnnotationFontName(), engConf.getClassLoader(), 1.0, true);
OutputStream out = null;
byte[] buf = new byte[1024];
int length;
try {
out = httpServletResponse.getOutputStream();
while ((length = in.read(buf)) != -1) {
out.write(buf, 0, length);
}
} catch (IOException e) {
log.error("操作异常", e);
} finally {
IoUtil.closeSilently(out);
IoUtil.closeSilently(in);
}
}
@Override
public void resourceView(String processDefinitionId, String processInstanceId, String resourceType, HttpServletResponse response) {
if (StringUtil.isAllBlank(processDefinitionId, processInstanceId)) {
return;
}
if (StringUtil.isBlank(processDefinitionId)) {
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
processDefinitionId = processInstance.getProcessDefinitionId();
}
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
String resourceName = "";
if (resourceType.equals(IMAGE_NAME)) {
resourceName = processDefinition.getDiagramResourceName();
} else if (resourceType.equals(XML_NAME)) {
resourceName = processDefinition.getResourceName();
}
try {
InputStream resourceAsStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), resourceName);
byte[] b = new byte[1024];
int len;
while ((len = resourceAsStream.read(b, 0, INT_1024)) != -1) {
response.getOutputStream().write(b, 0, len);
}
} catch (Exception exception) {
exception.printStackTrace();
}
}
@Override
public byte[] getModelEditorXML(FlowModel model) {
return getBpmnXML(model);
}
/**
* 是否已完结
*
* @param processInstanceId 流程实例id
* @return bool
*/
private boolean isFinished(String processInstanceId) {
return historyService.createHistoricProcessInstanceQuery().finished()
.processInstanceId(processInstanceId).count() > 0;
}
/**
* xml转bpmn json
*
* @param xml xml
* @return json
*/
private String getBpmnJson(String xml) {
return BPMN_JSON_CONVERTER.convertToJson(getBpmnModel(xml)).toString();
}
/**
* xml转bpmnModel
*
* @param xml xml
* @return bpmnModel
*/
private BpmnModel getBpmnModel(String xml) {
return BPMN_XML_CONVERTER.convertToBpmnModel(new StringStreamSource(xml), false, false);
}
private byte[] getBpmnXML(FlowModel model) {
BpmnModel bpmnModel = getBpmnModel(model);
return getBpmnXML(bpmnModel);
}
private byte[] getBpmnXML(BpmnModel bpmnModel) {
for (Process process : bpmnModel.getProcesses()) {
if (StringUtils.isNotEmpty(process.getId())) {
char firstCharacter = process.getId().charAt(0);
if (Character.isDigit(firstCharacter)) {
process.setId("a" + process.getId());
}
}
}
return BPMN_XML_CONVERTER.convertToXML(bpmnModel);
}
private BpmnModel getBpmnModel(FlowModel model) {
BpmnModel bpmnModel;
try {
Map<String, FlowModel> formMap = new HashMap<>(16);
Map<String, FlowModel> decisionTableMap = new HashMap<>(16);
List<FlowModel> referencedModels = baseMapper.findByParentModelId(model.getId());
for (FlowModel childModel : referencedModels) {
if (FlowModel.MODEL_TYPE_FORM == childModel.getModelType()) {
formMap.put(childModel.getId(), childModel);
} else if (FlowModel.MODEL_TYPE_DECISION_TABLE == childModel.getModelType()) {
decisionTableMap.put(childModel.getId(), childModel);
}
}
bpmnModel = getBpmnModel(model, formMap, decisionTableMap);
} catch (Exception e) {
log.error("Could not generate BPMN 2.0 model for {}", model.getId(), e);
throw new ServiceException("Could not generate BPMN 2.0 model");
}
return bpmnModel;
}
private BpmnModel getBpmnModel(FlowModel model, Map<String, FlowModel> formMap, Map<String, FlowModel> decisionTableMap) {
try {
ObjectNode editorJsonNode = (ObjectNode) objectMapper.readTree(model.getModelEditorJson());
Map<String, String> formKeyMap = new HashMap<>(16);
for (FlowModel formModel : formMap.values()) {
formKeyMap.put(formModel.getId(), formModel.getModelKey());
}
Map<String, String> decisionTableKeyMap = new HashMap<>(16);
for (FlowModel decisionTableModel : decisionTableMap.values()) {
decisionTableKeyMap.put(decisionTableModel.getId(), decisionTableModel.getModelKey());
}
BpmnJsonConverterContext converterContext = new CustomBpmnJsonConverterContext(formKeyMap, decisionTableKeyMap);
return BPMN_JSON_CONVERTER.convertToBpmnModel(editorJsonNode, converterContext);
} catch (Exception e) {
log.error("Could not generate BPMN 2.0 model for {}", model.getId(), e);
throw new ServiceException("Could not generate BPMN 2.0 model");
}
}
}

View File

@@ -0,0 +1,89 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.flow.engine.utils;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.impl.persistence.entity.ProcessDefinitionEntityImpl;
import org.flowable.engine.repository.ProcessDefinition;
import org.springblade.core.cache.utils.CacheUtil;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.SpringUtil;
import org.springblade.core.tool.utils.StringPool;
import org.springblade.flow.engine.entity.FlowProcess;
import org.springblade.system.cache.DictCache;
/**
* 流程缓存
*
* @author Chill
*/
public class FlowCache {
private static final String FLOW_CACHE = "flow:process";
private static final String FLOW_DEFINITION_ID = "definition:id";
private static RepositoryService repositoryService;
private static RepositoryService getRepositoryService() {
if (repositoryService == null) {
repositoryService = SpringUtil.getBean(RepositoryService.class);
}
return repositoryService;
}
/**
* 获得流程定义对象
*
* @param processDefinitionId 流程对象id
* @return
*/
public static FlowProcess getProcessDefinition(String processDefinitionId) {
return CacheUtil.get(FLOW_CACHE, FLOW_DEFINITION_ID, processDefinitionId, () -> {
ProcessDefinition processDefinition = getRepositoryService().createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
ProcessDefinitionEntityImpl processDefinitionEntity = BeanUtil.copyProperties(processDefinition, ProcessDefinitionEntityImpl.class);
return new FlowProcess(processDefinitionEntity);
});
}
/**
* 获取流程类型名
*
* @param category 流程类型
* @return
*/
public static String getCategoryName(String category) {
if (Func.isEmpty(category)) {
return StringPool.EMPTY;
}
String[] categoryArr = category.split(StringPool.UNDERSCORE);
if (categoryArr.length <= 1) {
return StringPool.EMPTY;
} else {
return DictCache.getValue(category.split(StringPool.UNDERSCORE)[0], Func.toInt(category.split(StringPool.UNDERSCORE)[1]));
}
}
}

View File

@@ -0,0 +1,6 @@
#数据源配置
spring:
datasource:
url: ${blade.datasource.flow.dev.url}
username: ${blade.datasource.flow.dev.username}
password: ${blade.datasource.flow.dev.password}

View File

@@ -0,0 +1,6 @@
#数据源配置
spring:
datasource:
url: ${blade.datasource.flow.prod.url}
username: ${blade.datasource.flow.prod.username}
password: ${blade.datasource.flow.prod.password}

View File

@@ -0,0 +1,6 @@
#数据源配置
spring:
datasource:
url: ${blade.datasource.flow.test.url}
username: ${blade.datasource.flow.test.username}
password: ${blade.datasource.flow.test.password}

View File

@@ -0,0 +1,13 @@
#服务器端口
server:
port: 8008
#flowable配置
flowable:
activity-font-name: \u5B8B\u4F53
label-font-name: \u5B8B\u4F53
annotation-font-name: \u5B8B\u4F53
check-process-definitions: false
database-schema-update: false
async-executor-activate: false
async-history-executor-activate: false

View File

@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:flowable="http://flowable.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.flowable.org/processdef">
<process id="Leave" name="请假流程" isExecutable="true">
<documentation>请假流程</documentation>
<startEvent id="start" name="开始" flowable:initiator="applyUser"></startEvent>
<userTask id="hrTask" name="人事审批" flowable:assignee="${taskUser}">
<extensionElements>
<modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
</extensionElements>
</userTask>
<exclusiveGateway id="judgeTask"></exclusiveGateway>
<userTask id="managerTak" name="经理审批" flowable:candidateGroups="manager"></userTask>
<userTask id="bossTask" name="老板审批" flowable:candidateGroups="boss"></userTask>
<endEvent id="end" name="结束"></endEvent>
<sequenceFlow id="flow1" sourceRef="start" targetRef="hrTask"></sequenceFlow>
<sequenceFlow id="managerPassFlow" name="通过" sourceRef="managerTak" targetRef="end">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${pass}]]></conditionExpression>
</sequenceFlow>
<userTask id="userTask" name="调整申请" flowable:assignee="${applyUser}">
<extensionElements>
<modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
</extensionElements>
</userTask>
<sequenceFlow id="bossPassFlow" name="通过" sourceRef="bossTask" targetRef="end">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${pass}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="judgeMore" name="大于3天" sourceRef="judgeTask" targetRef="bossTask">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${days > 3}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="managerNotPassFlow" name="驳回" sourceRef="managerTak" targetRef="userTask">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${!pass}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="bossNotPassFlow" name="驳回" sourceRef="bossTask" targetRef="userTask">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${!pass}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="hrPassFlow" name="同意" sourceRef="hrTask" targetRef="judgeTask">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${pass}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="hrNotPassFlow" name="驳回" sourceRef="hrTask" targetRef="userTask">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${!pass}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="judgeLess" name="小于3天" sourceRef="judgeTask" targetRef="managerTak">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${days <= 3}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="userPassFlow" name="重新申请" sourceRef="userTask" targetRef="hrTask">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${pass}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="userNotPassFlow" name="关闭申请" sourceRef="userTask" targetRef="end">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${!pass}]]></conditionExpression>
</sequenceFlow>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_Leave">
<bpmndi:BPMNPlane bpmnElement="Leave" id="BPMNPlane_Leave">
<bpmndi:BPMNShape bpmnElement="start" id="BPMNShape_start">
<omgdc:Bounds height="30.0" width="30.0" x="300.0" y="135.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="hrTask" id="BPMNShape_hrTask">
<omgdc:Bounds height="80.0" width="100.0" x="360.0" y="165.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="judgeTask" id="BPMNShape_judgeTask">
<omgdc:Bounds height="40.0" width="40.0" x="255.0" y="300.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="managerTak" id="BPMNShape_managerTak">
<omgdc:Bounds height="80.0" width="100.0" x="555.0" y="75.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="bossTask" id="BPMNShape_bossTask">
<omgdc:Bounds height="80.0" width="100.0" x="450.0" y="420.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="end" id="BPMNShape_end">
<omgdc:Bounds height="28.0" width="28.0" x="705.0" y="390.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="userTask" id="BPMNShape_userTask">
<omgdc:Bounds height="80.0" width="100.0" x="510.0" y="270.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
<omgdi:waypoint x="327.9390183144677" y="157.4917313275668"></omgdi:waypoint>
<omgdi:waypoint x="360.0" y="176.05263157894737"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="hrPassFlow" id="BPMNEdge_hrPassFlow">
<omgdi:waypoint x="363.04347826086956" y="244.95000000000002"></omgdi:waypoint>
<omgdi:waypoint x="285.77299999999997" y="310.79999999999995"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="hrNotPassFlow" id="BPMNEdge_hrNotPassFlow">
<omgdi:waypoint x="459.95" y="236.21875000000006"></omgdi:waypoint>
<omgdi:waypoint x="513.9794844818516" y="270.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="judgeLess" id="BPMNEdge_judgeLess">
<omgdi:waypoint x="274.3359375" y="300.66397214564284"></omgdi:waypoint>
<omgdi:waypoint x="274.3359375" y="115.0"></omgdi:waypoint>
<omgdi:waypoint x="554.9999999999982" y="115.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="userPassFlow" id="BPMNEdge_userPassFlow">
<omgdi:waypoint x="510.0" y="310.0"></omgdi:waypoint>
<omgdi:waypoint x="411.0" y="310.0"></omgdi:waypoint>
<omgdi:waypoint x="411.0" y="244.95000000000002"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="bossPassFlow" id="BPMNEdge_bossPassFlow">
<omgdi:waypoint x="549.9499999999998" y="447.2146118721461"></omgdi:waypoint>
<omgdi:waypoint x="705.4331577666419" y="407.4567570622598"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="judgeMore" id="BPMNEdge_judgeMore">
<omgdi:waypoint x="287.29730895645025" y="327.65205479452055"></omgdi:waypoint>
<omgdi:waypoint x="450.0" y="428.8888888888889"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="managerPassFlow" id="BPMNEdge_managerPassFlow">
<omgdi:waypoint x="620.7588235294118" y="154.95"></omgdi:waypoint>
<omgdi:waypoint x="713.8613704477151" y="390.96328050279476"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="userNotPassFlow" id="BPMNEdge_userNotPassFlow">
<omgdi:waypoint x="609.95" y="339.5301886792453"></omgdi:waypoint>
<omgdi:waypoint x="706.9383699359797" y="396.87411962686997"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="bossNotPassFlow" id="BPMNEdge_bossNotPassFlow">
<omgdi:waypoint x="515.98" y="420.0"></omgdi:waypoint>
<omgdi:waypoint x="544.0" y="349.95000000000005"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="managerNotPassFlow" id="BPMNEdge_managerNotPassFlow">
<omgdi:waypoint x="595.438344721373" y="154.95"></omgdi:waypoint>
<omgdi:waypoint x="567.9366337262223" y="270.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>

View File

@@ -0,0 +1,15 @@
FROM bladex/alpine-java:openjdk17_cn_slim
LABEL maintainer="bladejava@qq.com"
RUN mkdir -p /blade/job
WORKDIR /blade/job
EXPOSE 7770
COPY ./target/blade-job.jar ./app.jar
ENTRYPOINT ["java", "--add-opens", "java.base/java.lang=ALL-UNNAMED", "--add-opens", "java.base/java.lang.reflect=ALL-UNNAMED", "-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar"]
CMD ["--spring.profiles.active=test"]

View File

@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>blade-ops</artifactId>
<groupId>org.springblade</groupId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>blade-job</artifactId>
<name>${project.artifactId}</name>
<packaging>jar</packaging>
<dependencies>
<!--Blade-->
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-common</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-core-boot</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-starter-http</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-starter-swagger</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-starter-powerjob</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<configuration>
<skip>${docker.fabric.skip}</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,44 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.job;
import org.springblade.core.cloud.client.BladeCloudApplication;
import org.springblade.core.launch.BladeApplication;
import org.springblade.core.launch.constant.AppConstant;
/**
* 任务服务
*
* @author Chill
*/
@BladeCloudApplication
public class JobApplication {
public static void main(String[] args) {
BladeApplication.run(AppConstant.APPLICATION_JOB_NAME, JobApplication.class, args);
}
}

View File

@@ -0,0 +1,166 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.job.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.IsAdmin;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.job.pojo.entity.JobInfo;
import org.springblade.job.pojo.vo.JobInfoVO;
import org.springblade.job.service.IJobInfoService;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
/**
* 任务信息表 控制器
*
* @author BladeX
*/
@RestController
@AllArgsConstructor
@IsAdmin
@RequestMapping("/job-info")
@Tag(name = "任务信息表", description = "任务信息表接口")
public class JobInfoController extends BladeController {
private final IJobInfoService jobInfoService;
/**
* 任务信息表 详情
*/
@GetMapping("/detail")
@ApiOperationSupport(order = 1)
@Operation(summary = "详情", description = "传入jobInfo")
public R<JobInfo> detail(JobInfo jobInfo) {
JobInfo detail = jobInfoService.getOne(Condition.getQueryWrapper(jobInfo));
return R.data(detail);
}
/**
* 任务信息表 分页
*/
@GetMapping("/list")
@ApiOperationSupport(order = 2)
@Operation(summary = "分页", description = "传入jobInfo")
public R<IPage<JobInfo>> list(@Parameter(hidden = true) @RequestParam Map<String, Object> jobInfo, Query query) {
IPage<JobInfo> pages = jobInfoService.page(Condition.getPage(query), Condition.getQueryWrapper(jobInfo, JobInfo.class));
return R.data(pages);
}
/**
* 任务信息表 自定义分页
*/
@GetMapping("/page")
@ApiOperationSupport(order = 3)
@Operation(summary = "分页", description = "传入jobInfo")
public R<IPage<JobInfoVO>> page(JobInfoVO jobInfo, Query query) {
IPage<JobInfoVO> pages = jobInfoService.selectJobInfoPage(Condition.getPage(query), jobInfo);
return R.data(pages);
}
/**
* 任务信息表 新增
*/
@PostMapping("/save")
@ApiOperationSupport(order = 4)
@Operation(summary = "新增", description = "传入jobInfo")
public R save(@Valid @RequestBody JobInfo jobInfo) {
return R.status(jobInfoService.save(jobInfo));
}
/**
* 任务信息表 修改
*/
@PostMapping("/update")
@ApiOperationSupport(order = 5)
@Operation(summary = "修改", description = "传入jobInfo")
public R update(@Valid @RequestBody JobInfo jobInfo) {
return R.status(jobInfoService.updateById(jobInfo));
}
/**
* 任务信息表 新增或修改
*/
@PostMapping("/submit")
@ApiOperationSupport(order = 6)
@Operation(summary = "新增或修改", description = "传入jobInfo")
public R submit(@Valid @RequestBody JobInfo jobInfo) {
return R.status(jobInfoService.submitAndSync(jobInfo));
}
/**
* 任务信息表 删除
*/
@PostMapping("/remove")
@ApiOperationSupport(order = 7)
@Operation(summary = "删除", description = "传入ids")
public R remove(@Parameter(description = "主键集合", required = true) @RequestParam String ids) {
return R.status(jobInfoService.removeAndSync(Func.toLongList(ids)));
}
/**
* 任务信息表 变更状态
*/
@PostMapping("/change")
@ApiOperationSupport(order = 8)
@Operation(summary = "变更状态", description = "传入id与status")
public R change(@Parameter(description = "主键", required = true) @RequestParam Long id, @Parameter(description = "是否启用", required = true) @RequestParam Integer enable) {
return R.status(jobInfoService.changeServerJob(id, enable));
}
/**
* 运行服务
*/
@PostMapping("run")
@ApiOperationSupport(order = 9)
@Operation(summary = "运行服务", description = "传入jobInfoId")
public R run(@Parameter(description = "主键", required = true) @RequestParam Long id) {
return R.status(jobInfoService.runServerJob(id));
}
/**
* 任务信息数据同步
*/
@PostMapping("sync")
@ApiOperationSupport(order = 10)
@Operation(summary = "任务信息数据同步", description = "任务信息数据同步")
public R sync() {
return R.status(jobInfoService.sync());
}
}

View File

@@ -0,0 +1,164 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.job.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.IsAdmin;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringPool;
import org.springblade.job.pojo.entity.JobServer;
import org.springblade.job.pojo.vo.JobServerVO;
import org.springblade.job.service.IJobServerService;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
/**
* 任务服务表 控制器
*
* @author BladeX
*/
@RestController
@AllArgsConstructor
@IsAdmin
@RequestMapping("/job-server")
@Tag(name = "任务服务表", description = "任务服务表接口")
public class JobServerController extends BladeController {
private final IJobServerService jobServerService;
/**
* 任务服务表 详情
*/
@GetMapping("/detail")
@ApiOperationSupport(order = 1)
@Operation(summary = "详情", description = "传入jobServer")
public R<JobServer> detail(JobServer jobServer) {
JobServer detail = jobServerService.getOne(Condition.getQueryWrapper(jobServer));
return R.data(detail);
}
/**
* 任务服务表 分页
*/
@GetMapping("/list")
@ApiOperationSupport(order = 2)
@Operation(summary = "分页", description = "传入jobServer")
public R<IPage<JobServer>> list(@Parameter(hidden = true) @RequestParam Map<String, Object> jobServer, Query query) {
IPage<JobServer> pages = jobServerService.page(Condition.getPage(query), Condition.getQueryWrapper(jobServer, JobServer.class));
return R.data(pages);
}
/**
* 任务服务表 自定义分页
*/
@GetMapping("/page")
@ApiOperationSupport(order = 3)
@Operation(summary = "分页", description = "传入jobServer")
public R<IPage<JobServerVO>> page(JobServerVO jobServer, Query query) {
IPage<JobServerVO> pages = jobServerService.selectJobServerPage(Condition.getPage(query), jobServer);
return R.data(pages);
}
/**
* 任务服务表 新增
*/
@PostMapping("/save")
@ApiOperationSupport(order = 4)
@Operation(summary = "新增", description = "传入jobServer")
public R save(@Valid @RequestBody JobServer jobServer) {
return R.status(jobServerService.save(jobServer));
}
/**
* 任务服务表 修改
*/
@PostMapping("/update")
@ApiOperationSupport(order = 5)
@Operation(summary = "修改", description = "传入jobServer")
public R update(@Valid @RequestBody JobServer jobServer) {
return R.status(jobServerService.updateById(jobServer));
}
/**
* 任务服务表 新增或修改
*/
@PostMapping("/submit")
@ApiOperationSupport(order = 6)
@Operation(summary = "新增或修改", description = "传入jobServer")
public R submit(@Valid @RequestBody JobServer jobServer) {
return R.status(jobServerService.submitAndSync(jobServer));
}
/**
* 任务服务表 删除
*/
@PostMapping("/remove")
@ApiOperationSupport(order = 7)
@Operation(summary = "逻辑删除", description = "传入ids")
public R remove(@Parameter(description = "主键集合", required = true) @RequestParam String ids) {
return R.status(jobServerService.deleteLogic(Func.toLongList(ids)));
}
/**
* 应用服务信息 列表
*/
@GetMapping("/select")
@ApiOperationSupport(order = 8)
@Operation(summary = "应用服务信息", description = "应用服务信息")
public R select() {
List<JobServer> list = jobServerService.list();
list.forEach(jobServer -> jobServer.setJobAppName(
jobServer.getJobAppName() + StringPool.COLON + StringPool.SPACE + StringPool.LEFT_BRACKET +
jobServer.getJobServerName() + StringPool.SPACE + StringPool.DASH + StringPool.SPACE + jobServer.getJobServerUrl() + StringPool.RIGHT_BRACKET)
);
return R.data(list);
}
/**
* 任务服务数据同步
*/
@PostMapping("sync")
@ApiOperationSupport(order = 9)
@Operation(summary = "任务服务数据同步", description = "任务服务数据同步")
public R sync() {
jobServerService.list().forEach(jobServerService::sync);
return R.success("同步完毕");
}
}

View File

@@ -0,0 +1,51 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.job.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.job.pojo.entity.JobInfo;
import org.springblade.job.pojo.vo.JobInfoVO;
import java.util.List;
/**
* 任务信息表 Mapper 接口
*
* @author BladeX
*/
public interface JobInfoMapper extends BaseMapper<JobInfo> {
/**
* 自定义分页
*
* @param page
* @param jobInfo
* @return
*/
List<JobInfoVO> selectJobInfoPage(IPage page, JobInfoVO jobInfo);
}

View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.springblade.job.mapper.JobInfoMapper">
<!-- 通用查询映射结果 -->
<resultMap id="jobInfoResultMap" type="org.springblade.job.pojo.entity.JobInfo">
<result column="id" property="id"/>
<result column="job_server_id" property="jobServerId"/>
<result column="job_id" property="jobId"/>
<result column="job_name" property="jobName"/>
<result column="job_description" property="jobDescription"/>
<result column="job_params" property="jobParams"/>
<result column="time_expression_type" property="timeExpressionType"/>
<result column="time_expression" property="timeExpression"/>
<result column="execute_type" property="executeType"/>
<result column="processor_type" property="processorType"/>
<result column="processor_info" property="processorInfo"/>
<result column="max_instance_num" property="maxInstanceNum"/>
<result column="concurrency" property="concurrency"/>
<result column="instance_time_limit" property="instanceTimeLimit"/>
<result column="instance_retry_num" property="instanceRetryNum"/>
<result column="task_retry_num" property="taskRetryNum"/>
<result column="min_cpu_cores" property="minCpuCores"/>
<result column="min_memory_space" property="minMemorySpace"/>
<result column="min_disk_space" property="minDiskSpace"/>
<result column="designated_workers" property="designatedWorkers"/>
<result column="max_worker_count" property="maxWorkerCount"/>
<result column="notify_user_ids" property="notifyUserIds"/>
<result column="enable" property="enable"/>
<result column="dispatch_strategy" property="dispatchStrategy"/>
<result column="lifecycle" property="lifecycle"/>
<result column="alert_threshold" property="alertThreshold"/>
<result column="statistic_window_len" property="statisticWindowLen"/>
<result column="silence_window_len" property="silenceWindowLen"/>
<result column="log_type" property="logType"/>
<result column="log_level" property="logLevel"/>
<result column="extra" property="extra"/>
<result column="create_user" property="createUser"/>
<result column="create_dept" property="createDept"/>
<result column="create_time" property="createTime"/>
<result column="update_user" property="updateUser"/>
<result column="update_time" property="updateTime"/>
<result column="status" property="status"/>
<result column="is_deleted" property="isDeleted"/>
</resultMap>
<select id="selectJobInfoPage" resultMap="jobInfoResultMap">
select * from blade_job_info where is_deleted = 0
</select>
</mapper>

View File

@@ -0,0 +1,51 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.job.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.job.pojo.entity.JobServer;
import org.springblade.job.pojo.vo.JobServerVO;
import java.util.List;
/**
* 任务服务表 Mapper 接口
*
* @author BladeX
*/
public interface JobServerMapper extends BaseMapper<JobServer> {
/**
* 自定义分页
*
* @param page
* @param jobServer
* @return
*/
List<JobServerVO> selectJobServerPage(IPage page, JobServerVO jobServer);
}

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.springblade.job.mapper.JobServerMapper">
<!-- 通用查询映射结果 -->
<resultMap id="jobServerResultMap" type="org.springblade.job.pojo.entity.JobServer">
<result column="id" property="id"/>
<result column="job_server_name" property="jobServerName"/>
<result column="job_server_url" property="jobServerUrl"/>
<result column="job_app_name" property="jobAppName"/>
<result column="job_app_password" property="jobAppPassword"/>
<result column="job_remark" property="jobRemark"/>
<result column="create_user" property="createUser"/>
<result column="create_dept" property="createDept"/>
<result column="create_time" property="createTime"/>
<result column="update_user" property="updateUser"/>
<result column="update_time" property="updateTime"/>
<result column="status" property="status"/>
<result column="is_deleted" property="isDeleted"/>
</resultMap>
<select id="selectJobServerPage" resultMap="jobServerResultMap">
select * from blade_job_server where is_deleted = 0
</select>
</mapper>

View File

@@ -0,0 +1,56 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.job.pojo.dto;
import lombok.Data;
import org.springblade.job.pojo.entity.JobInfo;
import org.springblade.job.pojo.entity.JobServer;
import tech.powerjob.client.PowerJobClient;
/**
* 任务数据DTO
*
* @author Chill
*/
@Data
public class JobDTO {
/**
* 任务信息类
*/
private JobInfo jobInfo;
/**
* 任务服务类
*/
private JobServer jobServer;
/**
* 任务客户端类
*/
private PowerJobClient powerJobClient;
}

View File

@@ -0,0 +1,202 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.job.pojo.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springblade.core.mp.base.BaseEntity;
import java.io.Serial;
import java.math.BigDecimal;
/**
* 任务信息表 实体类
*
* @author BladeX
*/
@Data
@TableName("blade_job_info")
@EqualsAndHashCode(callSuper = true)
@Schema(description = "任务信息表")
public class JobInfo extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 任务服务ID
*/
@Schema(description = "任务服务ID")
private Long jobServerId;
/**
* 任务 ID可选null 代表创建任务,否则填写需要修改的任务 ID
*/
@Schema(description = "任务 ID可选null 代表创建任务,否则填写需要修改的任务 ID")
private Long jobId;
/**
* 任务名称
*/
@Schema(description = "任务名称")
private String jobName;
/**
* 任务描述
*/
@Schema(description = "任务描述")
private String jobDescription;
/**
* 任务参数Processor#process 方法入参 TaskContext 对象的 jobParams 字段
*/
@Schema(description = "任务参数Processor#process 方法入参 TaskContext 对象的 jobParams 字段")
private String jobParams;
/**
* 时间表达式类型,枚举值
*/
@Schema(description = "时间表达式类型,枚举值")
private Integer timeExpressionType;
/**
* 时间表达式,填写类型由 timeExpressionType 决定,比如 CRON 需要填写 CRON 表达式
*/
@Schema(description = "时间表达式,填写类型由 timeExpressionType 决定,比如 CRON 需要填写 CRON 表达式")
private String timeExpression;
/**
* 执行类型,枚举值
*/
@Schema(description = "执行类型,枚举值")
private Integer executeType;
/**
* 处理器类型,枚举值
*/
@Schema(description = "处理器类型,枚举值")
private Integer processorType;
/**
* 处理器参数,填写类型由 processorType 决定如Java 处理器需要填写全限定类名com.github.kfcfans.oms.processors.demo.MapReduceProcessorDemo
*/
@Schema(description = "处理器参数,填写类型由 processorType 决定如Java 处理器需要填写全限定类名com.github.kfcfans.oms.processors.demo.MapReduceProcessorDemo")
private String processorInfo;
/**
* 最大实例数,该任务同时执行的数量(任务和实例就像是类和对象的关系,任务被调度执行后被称为实例)
*/
@Schema(description = "最大实例数,该任务同时执行的数量(任务和实例就像是类和对象的关系,任务被调度执行后被称为实例)")
private Integer maxInstanceNum;
/**
* 单机线程并发数表示该实例执行过程中每个Worker 使用的线程数量
*/
@Schema(description = "单机线程并发数表示该实例执行过程中每个Worker 使用的线程数量")
private Integer concurrency;
/**
* 任务实例运行时间限制0 代表无任何限制,超时会被打断并判定为执行失败
*/
@Schema(description = "任务实例运行时间限制0 代表无任何限制,超时会被打断并判定为执行失败")
private Long instanceTimeLimit;
/**
* instanceRetryNum 任务实例重试次数,整个任务失败时重试,代价大,不推荐使用
*/
@Schema(description = "instanceRetryNum 任务实例重试次数,整个任务失败时重试,代价大,不推荐使用")
private Integer instanceRetryNum;
/**
* taskRetryNum Task 重试次数,每个子 Task 失败后单独重试,代价小,推荐使用
*/
@Schema(description = "taskRetryNum Task 重试次数,每个子 Task 失败后单独重试,代价小,推荐使用")
private Integer taskRetryNum;
/**
* minCpuCores 最小可用 CPU 核心数CPU 可用核心数小于该值的 Worker 将不会执行该任务0 代表无任何限制
*/
@Schema(description = "minCpuCores 最小可用 CPU 核心数CPU 可用核心数小于该值的 Worker 将不会执行该任务0 代表无任何限制")
private BigDecimal minCpuCores;
/**
* 最小内存大小GB可用内存小于该值的Worker 将不会执行该任务0 代表无任何限制
*/
@Schema(description = "最小内存大小GB可用内存小于该值的Worker 将不会执行该任务0 代表无任何限制")
private BigDecimal minMemorySpace;
/**
* 最小磁盘大小GB可用磁盘空间小于该值的Worker 将不会执行该任务0 代表无任何限制
*/
@Schema(description = "最小磁盘大小GB可用磁盘空间小于该值的Worker 将不会执行该任务0 代表无任何限制")
private BigDecimal minDiskSpace;
/**
* 指定机器执行,设置该参数后只有列表中的机器允许执行该任务,空代表不指定机器
*/
@Schema(description = "指定机器执行,设置该参数后只有列表中的机器允许执行该任务,空代表不指定机器")
private String designatedWorkers;
/**
* 最大执行机器数量限定调动执行的机器数量0代表无限制
*/
@Schema(description = "最大执行机器数量限定调动执行的机器数量0代表无限制")
private Integer maxWorkerCount;
/**
* 接收报警的用户 ID 列表
*/
@Schema(description = "接收报警的用户 ID 列表")
private String notifyUserIds;
/**
* 是否启用该任务,未启用的任务不会被调度
*/
@Schema(description = "是否启用该任务,未启用的任务不会被调度")
private Integer enable;
/**
* 调度策略枚举目前支持随机RANDOM和 健康度优先HEALTH_FIRST
*/
@Schema(description = "调度策略枚举目前支持随机RANDOM和 健康度优先HEALTH_FIRST")
private Integer dispatchStrategy;
/**
* lifecycle 生命周期(预留,用于指定定时调度任务的生效时间范围)
*/
@Schema(description = "lifecycle 生命周期(预留,用于指定定时调度任务的生效时间范围)")
private String lifecycle;
/**
* 错误阈值0代表不限制
*/
@Schema(description = "错误阈值0代表不限制")
private Integer alertThreshold;
/**
* 统计的窗口长度(s)0代表不限制
*/
@Schema(description = "统计的窗口长度(s)0代表不限制")
private Integer statisticWindowLen;
/**
* 沉默时间窗口(s)0代表不限制
*/
@Schema(description = "沉默时间窗口(s)0代表不限制")
private Integer silenceWindowLen;
/**
* 日志配置
*/
@Schema(description = "日志配置")
private Integer logType;
/**
* 日志配置
*/
@Schema(description = "日志级别")
private Integer logLevel;
/**
* 扩展字段供开发者使用用于功能扩展powerjob 自身不会使用该字段)
*/
@Schema(description = "扩展字段供开发者使用用于功能扩展powerjob 自身不会使用该字段)")
private String extra;
}

View File

@@ -0,0 +1,76 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.job.pojo.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springblade.core.mp.base.BaseEntity;
import java.io.Serial;
/**
* 任务服务表 实体类
*
* @author BladeX
*/
@Data
@TableName("blade_job_server")
@EqualsAndHashCode(callSuper = true)
@Schema(description = "任务服务表")
public class JobServer extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 任务服务名称
*/
@Schema(description = "任务服务名称")
private String jobServerName;
/**
* 任务服务器地址
*/
@Schema(description = "任务服务器地址")
private String jobServerUrl;
/**
* 任务应用名称
*/
@Schema(description = "任务应用名称")
private String jobAppName;
/**
* 任务应用密码
*/
@Schema(description = "任务应用密码")
private String jobAppPassword;
/**
* 任务备注
*/
@Schema(description = "任务备注")
private String jobRemark;
}

View File

@@ -0,0 +1,45 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.job.pojo.vo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springblade.job.pojo.entity.JobInfo;
import java.io.Serial;
/**
* 任务信息表 视图实体类
*
* @author BladeX
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class JobInfoVO extends JobInfo {
@Serial
private static final long serialVersionUID = 1L;
}

View File

@@ -0,0 +1,45 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.job.pojo.vo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springblade.job.pojo.entity.JobServer;
import java.io.Serial;
/**
* 任务服务表 视图实体类
*
* @author BladeX
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class JobServerVO extends JobServer {
@Serial
private static final long serialVersionUID = 1L;
}

View File

@@ -0,0 +1,35 @@
package org.springblade.job.processor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import tech.powerjob.worker.core.processor.ProcessResult;
import tech.powerjob.worker.core.processor.TaskContext;
import tech.powerjob.worker.core.processor.sdk.BasicProcessor;
import tech.powerjob.worker.log.OmsLogger;
// 支持 SpringBean 的形式
@Slf4j
@Component
public class ProcessorDemo implements BasicProcessor {
@Override
public ProcessResult process(TaskContext context) {
// 在线日志功能,可以直接在控制台查看任务日志,非常便捷
OmsLogger omsLogger = context.getOmsLogger();
omsLogger.info("BasicProcessorDemo start to process, current JobParams is {}.", context.getJobParams());
// TaskContext为任务的上下文信息包含了在控制台录入的任务元数据常用字段为
// jobParams任务参数在控制台录入instanceParams任务实例参数通过 OpenAPI 触发的任务实例才可能存在该参数)
// 进行实际处理...
log.info("============== ProcessorDemo#process ==============");
log.info("hello blade");
log.info("============== ProcessorDemo#process ==============");
// 返回结果,该结果会被持久化到数据库,在前端页面直接查看,极为方便
return new ProcessResult(true, "result is success");
}
}

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