增加定时任务功能

This commit is contained in:
wenli 2024-07-30 19:06:17 +08:00
parent 25f47615f0
commit 9840e82378
33 changed files with 3003 additions and 90 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 365 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 378 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 339 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 358 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 367 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 737 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 385 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 752 KiB

View File

@ -125,31 +125,33 @@ HTTP库使用 OpenFeign HTTP库该库提供了方便的 HTTP 请求和响
### JavaFX
| 模块 | 浅色 | 深色 | 玻璃 |
|------|------------------------------------|------------------------------------|------------------------------------|
| 登录 | ![登录](/.image/javafx/登录.png) | - | - |
| 主页 | ![主页](/.image/javafx/主页1.png) | ![主页](/.image/javafx/主页2.png) | ![主页](/.image/javafx/主页3.png) |
| 主页2 | ![主页2](/.image/javafx/主页21.png) | ![主页2](/.image/javafx/主页22.png) | ![主页2](/.image/javafx/主页23.png) |
| 用户管理 | ![用户管理](/.image/javafx/用户管理1.png) | ![用户管理](/.image/javafx/用户管理2.png) | ![用户管理](/.image/javafx/用户管理3.png) |
| 模块 | 浅色 | 深色 | glass |
|------|------------------------------------|------------------------------------|-----------------------------------|
| 登录 | ![登录](/.image/javafx/登录.png) | - | - |
| 主页 | ![主页](/.image/javafx/主页1.png) | ![主页](/.image/javafx/主页2.png) | ![主页](/.image/javafx/主页3.png) |
| 主页2 | ![主页2](/.image/javafx/主页21.png) | ![主页2](/.image/javafx/主页22.png) | ![主页2](/.image/javafx/主页23.png) |
| 用户管理 | ![用户管理](/.image/javafx/用户管理1.png) | ![用户管理](/.image/javafx/用户管理2.png) | ![用户管理](/.image/javafx/用户管理3.png) |
| 角色管理 | ![角色管理1](/.image/javafx/角色管理1.png) | ![角色管理2](/.image/javafx/角色管理2.png) | ![用户管理3](/.image/javafx/用户管理3.png) |
| 菜单管理 | ![菜单管理1](/.image/javafx/菜单管理1.png) | ![菜单管理2](/.image/javafx/菜单管理2.png) | ![菜单管理3](/.image/javafx/菜单管理3.png) |
| 部门管理 | ![部门管理](/.image/javafx/部门管理1.png) | ![部门管理](/.image/javafx/部门管理2.png) | ![部门管理](/.image/javafx/部门管理3.png) |
| 岗位管理 | ![岗位管理](/.image/javafx/岗位管理1.png) | ![岗位管理](/.image/javafx/岗位管理2.png) | ![岗位管理](/.image/javafx/岗位管理3.png) |
| 字典管理 | ![字典管理](/.image/javafx/字典管理1.png) | ![字典管理](/.image/javafx/字典管理2.png) | ![字典管理](/.image/javafx/字典管理3.png) |
| 字典数据 | ![字典数据](/.image/javafx/字典数据1.png) | ![字典数据](/.image/javafx/字典数据2.png) | ![字典数据](/.image/javafx/字典数据3.png) |
| 通知公告 | ![通知公告](/.image/javafx/通知公告1.png) | ![通知公告](/.image/javafx/通知公告2.png) | ![通知公告](/.image/javafx/通知公告3.png) |
| 消息模板 | ![消息模板](/.image/javafx/消息模板1.png) | ![消息模板](/.image/javafx/消息模板2.png) | ![消息模板](/.image/javafx/消息模板3.png) |
| 消息记录 | ![消息记录](/.image/javafx/消息记录1.png) | ![消息记录](/.image/javafx/消息记录2.png) | ![消息记录](/.image/javafx/消息记录3.png) |
| 我的消息 | ![我的消息](/.image/javafx/我的消息1.png) | ![我的消息](/.image/javafx/我的消息2.png) | ![我的消息](/.image/javafx/我的消息3.png) |
| 操作日志 | ![操作日志](/.image/javafx/操作日志1.png) | ![操作日志](/.image/javafx/操作日志2.png) | ![操作日志](/.image/javafx/操作日志3.png) |
| 登录日志 | ![登录日志](/.image/javafx/登录日志1.png) | ![登录日志](/.image/javafx/登录日志2.png) | ![登录日志](/.image/javafx/登录日志3.png) |
| 令牌管理 | ![令牌管理](/.image/javafx/令牌管理1.png) | ![令牌管理](/.image/javafx/令牌管理2.png) | ![令牌管理](/.image/javafx/令牌管理3.png) |
| 文件配置 | ![文件配置](/.image/javafx/文件配置1.png) | ![文件配置](/.image/javafx/文件配置2.png) | ![文件配置](/.image/javafx/文件配置3.png) |
| 文件列表 | ![文件列表](/.image/javafx/文件列表1.png) | ![文件列表](/.image/javafx/文件列表2.png) | ![文件列表](/.image/javafx/文件列表3.png) |
| 部门管理 | ![部门管理](/.image/javafx/部门管理1.png) | ![部门管理](/.image/javafx/部门管理2.png) | ![部门管理](/.image/javafx/部门管理3.png) |
| 岗位管理 | ![岗位管理](/.image/javafx/岗位管理1.png) | ![岗位管理](/.image/javafx/岗位管理2.png) | ![岗位管理](/.image/javafx/岗位管理3.png) |
| 字典管理 | ![字典管理](/.image/javafx/字典管理1.png) | ![字典管理](/.image/javafx/字典管理2.png) | ![字典管理](/.image/javafx/字典管理3.png) |
| 字典数据 | ![字典数据](/.image/javafx/字典数据1.png) | ![字典数据](/.image/javafx/字典数据2.png) | ![字典数据](/.image/javafx/字典数据3.png) |
| 通知公告 | ![通知公告](/.image/javafx/通知公告1.png) | ![通知公告](/.image/javafx/通知公告2.png) | ![通知公告](/.image/javafx/通知公告3.png) |
| 消息模板 | ![消息模板](/.image/javafx/消息模板1.png) | ![消息模板](/.image/javafx/消息模板2.png) | ![消息模板](/.image/javafx/消息模板3.png) |
| 消息记录 | ![消息记录](/.image/javafx/消息记录1.png) | ![消息记录](/.image/javafx/消息记录2.png) | ![消息记录](/.image/javafx/消息记录3.png) |
| 我的消息 | ![我的消息](/.image/javafx/我的消息1.png) | ![我的消息](/.image/javafx/我的消息2.png) | ![我的消息](/.image/javafx/我的消息3.png) |
| 操作日志 | ![操作日志](/.image/javafx/操作日志1.png) | ![操作日志](/.image/javafx/操作日志2.png) | ![操作日志](/.image/javafx/操作日志3.png) |
| 登录日志 | ![登录日志](/.image/javafx/登录日志1.png) | ![登录日志](/.image/javafx/登录日志2.png) | ![登录日志](/.image/javafx/登录日志3.png) |
| 令牌管理 | ![令牌管理](/.image/javafx/令牌管理1.png) | ![令牌管理](/.image/javafx/令牌管理2.png) | ![令牌管理](/.image/javafx/令牌管理3.png) |
| 文件配置 | ![文件配置](/.image/javafx/文件配置1.png) | ![文件配置](/.image/javafx/文件配置2.png) | ![文件配置](/.image/javafx/文件配置3.png) |
| 文件列表 | ![文件列表](/.image/javafx/文件列表1.png) | ![文件列表](/.image/javafx/文件列表2.png) | ![文件列表](/.image/javafx/文件列表3.png) |
| 定时任务 | ![定时任务](/.image/javafx/定时任务1.png) | ![定时任务](/.image/javafx/定时任务2.png) | ![定时任务](/.image/javafx/定时任务3.png) |
| 执行日志 | ![执行日志](/.image/javafx/执行日志1.png) | ![执行日志](/.image/javafx/执行日志2.png) | ![执行日志](/.image/javafx/执行日志3.png) |
### Java Swing
| 模块 | 浅色 | 深色 | 玻璃 |
| 模块 | 浅色 | 深色1 | 深色2 |
|------|-----------------------------------|-----------------------------------|-----------------------------------|
| 登录 | ![登录](/.image/swing/登录.png) | - | - |
| 用户管理 | ![用户管理](/.image/swing/用户管理1.png) | ![用户管理](/.image/swing/用户管理2.png) | ![用户管理](/.image/swing/用户管理3.png) |
@ -167,3 +169,5 @@ HTTP库使用 OpenFeign HTTP库该库提供了方便的 HTTP 请求和响
| 登录日志 | ![登录日志](/.image/swing/登录日志1.png) | ![登录日志](/.image/swing/登录日志2.png) | ![登录日志](/.image/swing/登录日志3.png) |
| 文件配置 | ![文件配置](/.image/swing/文件配置1.png) | ![文件配置](/.image/swing/文件配置2.png) | ![文件配置](/.image/swing/文件配置3.png) |
| 文件列表 | ![文件列表](/.image/swing/文件列表1.png) | ![文件列表](/.image/swing/文件列表2.png) | ![文件列表](/.image/swing/文件列表3.png) |
| 定时任务 | ![定时任务](/.image/swing/定时任务1.png) | ![定时任务](/.image/swing/定时任务2.png) | ![定时任务](/.image/swing/定时任务3.png) |
| 执行日志 | ![执行日志](/.image/swing/执行日志1.png) | ![执行日志](/.image/swing/执行日志2.png) | ![执行日志](/.image/swing/执行日志3.png) |

View File

@ -15,10 +15,7 @@ import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
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 org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

View File

@ -0,0 +1,61 @@
package com.lw.ui.request.api.job;
import com.lw.dillon.admin.framework.common.pojo.CommonResult;
import com.lw.dillon.admin.framework.common.pojo.PageResult;
import com.lw.dillon.admin.module.infra.controller.admin.job.vo.job.JobPageReqVO;
import com.lw.dillon.admin.module.infra.controller.admin.job.vo.job.JobRespVO;
import com.lw.dillon.admin.module.infra.controller.admin.job.vo.job.JobSaveReqVO;
import com.lw.ui.request.api.BaseFeignApi;
import feign.Param;
import feign.QueryMap;
import feign.RequestLine;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
public interface JobFeign extends BaseFeignApi {
// "创建定时任务")
@RequestLine("POST /admin-api/infra/job/create")
CommonResult<Long> createJob(JobSaveReqVO createReqVO);
// "更新定时任务")
@RequestLine("PUT /admin-api/infra/job/update")
CommonResult<Boolean> updateJob(JobSaveReqVO updateReqVO);
// "更新定时任务的状态")
@RequestLine("PUT /admin-api/infra/job/update-status?id={id}&status={status}")
CommonResult<Boolean> updateJobStatus(@Param("id") Long id, @Param("status") Integer status);
// "删除定时任务")
@RequestLine("DELETE /admin-api/infra/job/delete?id={id}")
CommonResult<Boolean> deleteJob(@Param("id") Long id);
// "触发定时任务")
@RequestLine("PUT /admin-api/infra/job/trigger?id={id}")
CommonResult<Boolean> triggerJob(@Param("id") Long id);
// "同步定时任务")
@RequestLine("POST /admin-api/infra/job/sync")
CommonResult<Boolean> syncJob();
// "获得定时任务")
@RequestLine("GET /admin-api/infra/job/get?id={id}")
CommonResult<JobRespVO> getJob(@Param("id") Long id);
// "获得定时任务分页")
@RequestLine("GET /admin-api/infra/job/page")
CommonResult<PageResult<JobRespVO>> getJobPage(@QueryMap Map<String,Object> pageVO);
// "获得定时任务的下 n 次执行时间")
@RequestLine("GET /admin-api/infra/job/get_next_times?id={id}&count={count}")
CommonResult<List<LocalDateTime>> getJobNextTimes(
@Param("id") Long id,
@Param("count") Integer count);
}

View File

@ -0,0 +1,26 @@
package com.lw.ui.request.api.job;
import com.lw.dillon.admin.framework.common.pojo.CommonResult;
import com.lw.dillon.admin.framework.common.pojo.PageResult;
import com.lw.dillon.admin.module.infra.controller.admin.job.vo.log.JobLogRespVO;
import com.lw.ui.request.api.BaseFeignApi;
import feign.Param;
import feign.QueryMap;
import feign.RequestLine;
import java.util.Map;
public interface JobLogFeign extends BaseFeignApi {
//"获得定时任务日志")
@RequestLine("GET /admin-api/infra/job-log/get?id={id}")
CommonResult<JobLogRespVO> getJobLog(@Param("id") Long id);
//"获得定时任务日志分页")
@RequestLine("GET /admin-api/infra/job-log/page")
CommonResult<PageResult<JobLogRespVO>> getJobLogPage(@QueryMap Map<String,Object> pageVO);
}

View File

@ -66,11 +66,13 @@
<groupId>org.kordamp.ikonli</groupId>
<artifactId>ikonli-javafx</artifactId>
<version>${lib.ikonli.version}</version>
</dependency>
<dependency>
<groupId>org.kordamp.ikonli</groupId>
<artifactId>ikonli-feather-pack</artifactId>
<version>${lib.ikonli.version}</version>
</dependency>
<dependency>
<groupId>org.kordamp.ikonli</groupId>
@ -86,12 +88,19 @@
<groupId>org.controlsfx</groupId>
<artifactId>controlsfx</artifactId>
<version>${controlsfx.version}</version>
</dependency>
<dependency>
<groupId>fr.brouillard.oss</groupId>
<artifactId>cssfx</artifactId>
<version>${lib.cssfx.version}</version>
<exclusions>
<exclusion>
<groupId>org.openjfx</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
@ -103,7 +112,6 @@
<groupId>de.saxsys</groupId>
<artifactId>mvvmfx</artifactId>
<version>${mvvmfx-version}</version>
</dependency>
<dependency>
<groupId>de.saxsys</groupId>
@ -116,6 +124,12 @@
<groupId>io.github.mkpaz</groupId>
<artifactId>atlantafx-base</artifactId>
<version>${atlantafx.version}</version>
<exclusions>
<exclusion>
<groupId>org.openjfx</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
@ -149,16 +163,7 @@
<version>1.2.4</version>
</dependency>
<dependency>
<groupId>de.saxsys</groupId>
<artifactId>mvvmfx</artifactId>
<version>${mvvmfx-version}</version>
</dependency>
<dependency>
<groupId>de.saxsys</groupId>
<artifactId>mvvmfx-validation</artifactId>
<version>${mvvmfx-version}</version>
</dependency>
<dependency>
<groupId>org.kordamp.jipsy</groupId>
<artifactId>jipsy-processor</artifactId>
@ -177,6 +182,12 @@
<groupId>com.dlsc.gemsfx</groupId>
<artifactId>gemsfx</artifactId>
<version>2.32.0</version>
<exclusions>
<exclusion>
<groupId>org.openjfx</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>

View File

@ -0,0 +1,92 @@
package com.lw.fx.view.infra.job;
import de.saxsys.mvvmfx.FxmlView;
import de.saxsys.mvvmfx.InjectViewModel;
import javafx.beans.binding.Bindings;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.util.StringConverter;
import java.net.URL;
import java.util.ResourceBundle;
public class JobFormView implements FxmlView<JobFormViewModel>, Initializable {
@InjectViewModel
private JobFormViewModel viewModel;
@FXML
private HBox basePathBox;
@FXML
private TextField cronExpressionField;
@FXML
private TextField handlerNameField;
@FXML
private TextField handlerParamField;
@FXML
private HBox hostBox;
@FXML
private TextField monitorTimeoutFiled;
@FXML
private TextField nameField;
@FXML
private HBox passwordBox;
@FXML
private HBox portBox;
@FXML
private TextField retryCountField;
@FXML
private TextField retryIntervalFiled;
@FXML
private VBox rootBox;
@FXML
private HBox usernameBox;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
nameField.textProperty().bindBidirectional(viewModel.nameProperty());
cronExpressionField.textProperty().bindBidirectional(viewModel.cronExpressionProperty());
handlerNameField.textProperty().bindBidirectional(viewModel.handlerNameProperty());
handlerParamField.textProperty().bindBidirectional(viewModel.handlerParamProperty());
StringConverter stringConverter= new StringConverter<Number>() {
@Override
public String toString(Number object) {
return object == null ? "" : object.toString();
}
@Override
public Number fromString(String string) {
if (string == null || string.isEmpty()) {
return 0;
}
try {
return Integer.parseInt(string);
} catch (NumberFormatException e) {
return 0; // Default value in case of parsing error
}
}
};
Bindings.bindBidirectional(retryIntervalFiled.textProperty(), viewModel.retryIntervalProperty(),stringConverter );
Bindings.bindBidirectional(monitorTimeoutFiled.textProperty(), viewModel.monitorTimeoutProperty(),stringConverter );
Bindings.bindBidirectional(retryCountField.textProperty(), viewModel.retryCountProperty(),stringConverter );
}
}

View File

@ -0,0 +1,106 @@
package com.lw.fx.view.infra.job;
import cn.hutool.core.bean.BeanUtil;
import com.lw.dillon.admin.framework.common.pojo.CommonResult;
import com.lw.dillon.admin.module.infra.controller.admin.job.vo.job.JobRespVO;
import com.lw.dillon.admin.module.infra.controller.admin.job.vo.job.JobSaveReqVO;
import com.lw.dillon.admin.module.infra.controller.admin.job.vo.job.JobSaveReqVO;
import com.lw.dillon.admin.module.system.controller.admin.permission.vo.role.RoleSaveReqVO;
import com.lw.fx.request.Request;
import com.lw.ui.request.api.job.JobFeign;
import de.saxsys.mvvmfx.ViewModel;
import de.saxsys.mvvmfx.utils.mapping.ModelWrapper;
import io.datafx.core.concurrent.ProcessChain;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.LongProperty;
import javafx.beans.property.StringProperty;
public class JobFormViewModel implements ViewModel {
private Long id = null;
private ModelWrapper<JobRespVO> wrapper = new ModelWrapper<>();
public void updateData(Long id, boolean isAdd) {
this.id = id;
ProcessChain.create()
.addSupplierInExecutor(() -> {
if (id == null) {
return new JobRespVO();
}
return Request.connector(JobFeign.class).getJob(id).getData();
})
.addConsumerInPlatformThread(rel -> {
setWrapper(rel);
})
.run();
}
public void setWrapper(JobRespVO respVO) {
wrapper.set(respVO);
wrapper.reload();
}
public CommonResult save(boolean isAdd) {
if (isAdd) {
return Request.connector(JobFeign.class).createJob(getSaveReqVO());
} else {
return Request.connector(JobFeign.class).updateJob(getSaveReqVO());
}
}
public JobSaveReqVO getSaveReqVO() {
wrapper.commit();
JobRespVO jobRespVO = wrapper.get();
JobSaveReqVO saveVo = new JobSaveReqVO();
BeanUtil.copyProperties(jobRespVO, saveVo);
return saveVo;
}
public LongProperty idProperty() {
return wrapper.field("id", JobRespVO::getId, JobRespVO::setId);
}
public StringProperty nameProperty() {
return wrapper.field("name", JobRespVO::getName, JobRespVO::setName, "");
}
public StringProperty handlerNameProperty() {
return wrapper.field("handlerName", JobRespVO::getHandlerName, JobRespVO::setHandlerName, "");
}
public StringProperty handlerParamProperty() {
return wrapper.field("handlerParam", JobRespVO::getHandlerParam, JobRespVO::setHandlerParam, "");
}
public StringProperty cronExpressionProperty() {
return wrapper.field("cronExpression", JobRespVO::getCronExpression, JobRespVO::setCronExpression, "");
}
public IntegerProperty statusProperty() {
return wrapper.field("status", JobRespVO::getStatus, JobRespVO::setStatus);
}
public IntegerProperty retryCountProperty() {
return wrapper.field("retryCount", JobRespVO::getRetryCount, JobRespVO::setRetryCount);
}
public IntegerProperty retryIntervalProperty() {
return wrapper.field("retryInterval", JobRespVO::getRetryInterval, JobRespVO::setRetryInterval);
}
public IntegerProperty monitorTimeoutProperty() {
return wrapper.field("monitorTimeout", JobRespVO::getMonitorTimeout, JobRespVO::setMonitorTimeout);
}
}

View File

@ -0,0 +1,374 @@
package com.lw.fx.view.infra.job;
import cn.hutool.core.date.DateUtil;
import com.lw.dillon.admin.module.infra.controller.admin.job.vo.log.JobLogRespVO;
import com.lw.dillon.admin.module.system.controller.admin.dict.vo.data.DictDataSimpleRespVO;
import com.lw.fx.request.Request;
import com.lw.fx.store.AppStore;
import com.lw.fx.view.control.PagingControl;
import com.lw.fx.view.control.WFXGenericDialog;
import com.lw.ui.request.api.job.JobFeign;
import com.lw.ui.utils.DictTypeEnum;
import de.saxsys.mvvmfx.FxmlView;
import de.saxsys.mvvmfx.InjectViewModel;
import io.datafx.core.concurrent.ProcessChain;
import javafx.collections.FXCollections;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.util.Callback;
import org.kordamp.ikonli.feather.Feather;
import org.kordamp.ikonli.javafx.FontIcon;
import java.net.URL;
import java.util.Map;
import java.util.ResourceBundle;
import static atlantafx.base.theme.Styles.*;
import static com.lw.ui.utils.DictTypeEnum.INFRA_JOB_LOG_STATUS;
import static com.lw.ui.utils.DictTypeEnum.INFRA_JOB_STATUS;
public class JobLogView implements FxmlView<JobLogViewModel>, Initializable {
@InjectViewModel
private JobLogViewModel viewModel;
@FXML
private VBox contentPane;
@FXML
private TableColumn<JobLogRespVO, Integer> durationCol;
@FXML
private DatePicker endDatePicker;
@FXML
private TableColumn<JobLogRespVO, ?> executeIndexCol;
@FXML
private TableColumn<JobLogRespVO, Long> executeTimeCol;
@FXML
private TextField handlerNameField;
@FXML
private TableColumn<JobLogRespVO, ?> handlerNamecol;
@FXML
private TableColumn<JobLogRespVO, ?> handlerParamCol;
@FXML
private TableColumn<JobLogRespVO, ?> idCol;
@FXML
private Button infoBut;
@FXML
private TableColumn<JobLogRespVO, ?> jobIdCol;
@FXML
private TableColumn<JobLogRespVO, Long> optCol;
@FXML
private Button resetBut;
@FXML
private StackPane rootPane;
@FXML
private Button searchBut;
@FXML
private DatePicker startDatePicker;
@FXML
private TableColumn<JobLogRespVO, Integer> statusCol;
@FXML
private ComboBox<DictDataSimpleRespVO> statusComboBox;
@FXML
private TableView<JobLogRespVO> tableView;
private PagingControl pagingControl;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
pagingControl = new PagingControl();
contentPane.getChildren().add(pagingControl);
startDatePicker.valueProperty().bindBidirectional(viewModel.beginDateProperty());
endDatePicker.valueProperty().bindBidirectional(viewModel.endDateProperty());
pagingControl.totalProperty().bind(viewModel.totalProperty());
viewModel.pageNumProperty().bind(pagingControl.pageNumProperty());
viewModel.pageSizeProperty().bind(pagingControl.pageSizeProperty());
pagingControl.pageNumProperty().addListener((observable, oldValue, newValue) -> {
viewModel.loadTableData();
});
pagingControl.pageSizeProperty().addListener((observable, oldValue, newValue) -> {
viewModel.loadTableData();
});
statusComboBox.setItems(FXCollections.observableArrayList(AppStore.getDictDataList(INFRA_JOB_STATUS)));
statusComboBox.valueProperty().bindBidirectional(viewModel.statusProperty());
handlerNameField.textProperty().bindBidirectional(viewModel.handlerNameProperty());
idCol.setCellValueFactory(new PropertyValueFactory<>("id"));
idCol.setStyle("-fx-alignment: CENTER");
jobIdCol.setCellValueFactory(new PropertyValueFactory<>("jobId"));
jobIdCol.setStyle("-fx-alignment: CENTER");
statusCol.setCellValueFactory(new PropertyValueFactory<>("status"));
statusCol.setStyle("-fx-alignment: CENTER");
statusCol.setCellFactory(new Callback<TableColumn<JobLogRespVO, Integer>, TableCell<JobLogRespVO, Integer>>() {
@Override
public TableCell<JobLogRespVO, Integer> call(TableColumn<JobLogRespVO, Integer> param) {
return new TableCell<>() {
@Override
protected void updateItem(Integer item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
DictDataSimpleRespVO dict = AppStore.getDictDataValueMap(INFRA_JOB_LOG_STATUS).get(item + "");
Button state = new Button(dict.getLabel());
switch (dict.getColorType()) {
case "primary":
state.getStyleClass().addAll(BUTTON_OUTLINED, ACCENT);
break;
case "success":
state.getStyleClass().addAll(BUTTON_OUTLINED, SUCCESS);
break;
case "info":
state.getStyleClass().addAll(BUTTON_OUTLINED);
break;
case "warning":
state.getStyleClass().addAll(BUTTON_OUTLINED, WARNING);
break;
case "danger":
state.getStyleClass().addAll(BUTTON_OUTLINED, DANGER);
break;
default:
state.getStyleClass().addAll(BUTTON_OUTLINED);
}
HBox box = new HBox(state);
box.setPadding(new Insets(7, 7, 7, 7));
box.setAlignment(Pos.CENTER);
setGraphic(box);
}
}
};
}
});
handlerNamecol.setCellValueFactory(new PropertyValueFactory<>("handlerName"));
handlerNamecol.setStyle("-fx-alignment: CENTER");
handlerParamCol.setCellValueFactory(new PropertyValueFactory<>("handlerParam"));
handlerParamCol.setStyle("-fx-alignment: CENTER");
executeIndexCol.setCellValueFactory(new PropertyValueFactory<>("executeIndex"));
executeIndexCol.setStyle("-fx-alignment: CENTER");
executeTimeCol.setCellValueFactory(new PropertyValueFactory<>("id"));
executeTimeCol.setStyle("-fx-alignment: CENTER");
executeTimeCol.setCellFactory(new Callback<TableColumn<JobLogRespVO, Long>, TableCell<JobLogRespVO, Long>>() {
@Override
public TableCell<JobLogRespVO, Long> call(TableColumn<JobLogRespVO, Long> param) {
return new TableCell<>() {
@Override
protected void updateItem(Long item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
} else {
if (item != null) {
JobLogRespVO respVO = getTableRow().getItem();
this.setText(DateUtil.format(respVO.getBeginTime(), "yyyy-MM-dd HH:mm:ss") + " ~ " + DateUtil.format(respVO.getEndTime(), "yyyy-MM-dd HH:mm:ss"));
}
}
}
};
}
});
durationCol.setCellValueFactory(new PropertyValueFactory<>("duration"));
durationCol.setStyle("-fx-alignment: CENTER");
durationCol.setCellFactory(new Callback<TableColumn<JobLogRespVO, Integer>, TableCell<JobLogRespVO, Integer>>() {
@Override
public TableCell<JobLogRespVO, Integer> call(TableColumn<JobLogRespVO, Integer> param) {
return new TableCell<>() {
@Override
protected void updateItem(Integer item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
} else {
if (item != null) {
this.setText(item + " 毫秒");
}
}
}
};
}
});
optCol.setCellValueFactory(new PropertyValueFactory<>("id"));
optCol.setCellFactory(new Callback<TableColumn<JobLogRespVO, Long>, TableCell<JobLogRespVO, Long>>() {
@Override
public TableCell<JobLogRespVO, Long> call(TableColumn<JobLogRespVO, Long> param) {
TableCell cell = new TableCell<JobLogRespVO, Long>() {
@Override
protected void updateItem(Long item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
Button openDetailBut = new Button("详细");
openDetailBut.setOnAction(event -> showDetailView(getTableRow().getItem()));
openDetailBut.setGraphic(FontIcon.of(Feather.EDIT));
openDetailBut.getStyleClass().addAll(FLAT, ACCENT);
HBox box = new HBox(openDetailBut);
box.setAlignment(Pos.CENTER);
setGraphic(box);
}
}
};
return cell;
}
});
tableView.setItems(viewModel.getTableItems());
searchBut.setOnAction(actionEvent -> viewModel.loadTableData());
resetBut.setOnAction(actionEvent -> {
jobIdCol.setText(null);
statusComboBox.getSelectionModel().select(null);
handlerNameField.setText(null);
endDatePicker.setValue(null);
startDatePicker.setValue(null);
viewModel.loadTableData();
});
}
/**
* 显示编辑对话框
*/
private void showDetailView(JobLogRespVO respVo) {
ProcessChain.create()
.addSupplierInExecutor(() -> {
return Request.connector(JobFeign.class).getJobNextTimes(respVo.getId(), 5);
})
.addConsumerInPlatformThread(r -> {
if (r.isSuccess()) {
WFXGenericDialog dialog = new WFXGenericDialog();
dialog.addActions(
Map.entry(new Button("确定"), event -> {
dialog.close();
})
);
VBox vBox = new VBox(10, createTextField("日志编号", respVo.getId() + "")
, createTextField("任务编号", respVo.getJobId() + "")
, createTextField("处理器的名字", respVo.getHandlerName())
, createTextField("处理器的参数", respVo.getHandlerParam())
, createTextField("第几次执行", respVo.getExecuteIndex() + "")
, createTextField("执行时间", DateUtil.format(respVo.getBeginTime(), "yyyy-MM-dd HH:mm:ss") + " ~ " + DateUtil.format(respVo.getEndTime(), "yyyy-MM-dd HH:mm:ss"))
, createTextField("执行时长", respVo.getDuration() + "毫秒")
, createDictBut("任务状态", respVo.getStatus(), INFRA_JOB_LOG_STATUS)
, createTextField("执行结果", respVo.getResult())
);
vBox.setPrefWidth(500);
dialog.setHeaderIcon(FontIcon.of(Feather.INFO));
dialog.setHeaderText("详情");
dialog.setContent(vBox);
dialog.show(rootPane.getScene());
}
}).onException(e -> e.printStackTrace())
.run();
}
private HBox createTextField(String text, String value) {
Label label = new Label(text);
label.setAlignment(Pos.CENTER_RIGHT);
label.setPrefWidth(100);
TextField textField = new TextField(value);
textField.setEditable(false);
HBox.setHgrow(textField, Priority.ALWAYS);
HBox hBox = new HBox(7, label, textField);
hBox.setAlignment(Pos.CENTER_LEFT);
return hBox;
}
private HBox createDictBut(String text, Object value, DictTypeEnum dictTypeEnum) {
Label label = new Label(text);
label.setAlignment(Pos.CENTER_RIGHT);
label.setPrefWidth(100);
DictDataSimpleRespVO dict = AppStore.getDictDataValueMap(dictTypeEnum).get(value + "");
Button state = new Button(dict.getLabel());
switch (dict.getColorType()) {
case "primary":
state.getStyleClass().addAll(BUTTON_OUTLINED, ACCENT);
break;
case "success":
state.getStyleClass().addAll(BUTTON_OUTLINED, SUCCESS);
break;
case "info":
state.getStyleClass().addAll(BUTTON_OUTLINED);
break;
case "warning":
state.getStyleClass().addAll(BUTTON_OUTLINED, WARNING);
break;
case "danger":
state.getStyleClass().addAll(BUTTON_OUTLINED, DANGER);
break;
default:
state.getStyleClass().addAll(BUTTON_OUTLINED);
}
HBox hBox = new HBox(7, label, state);
hBox.setAlignment(Pos.CENTER_LEFT);
return hBox;
}
}

View File

@ -0,0 +1,141 @@
package com.lw.fx.view.infra.job;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import com.lw.dillon.admin.module.infra.controller.admin.job.vo.log.JobLogRespVO;
import com.lw.dillon.admin.module.system.controller.admin.dict.vo.data.DictDataSimpleRespVO;
import com.lw.fx.request.Request;
import com.lw.ui.request.api.job.JobLogFeign;
import de.saxsys.mvvmfx.ViewModel;
import io.datafx.core.concurrent.ProcessChain;
import javafx.beans.property.*;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
public class JobLogViewModel implements ViewModel {
private SimpleIntegerProperty total = new SimpleIntegerProperty(0);
private IntegerProperty pageNum = new SimpleIntegerProperty(0);
private IntegerProperty pageSize = new SimpleIntegerProperty(10);
private StringProperty name = new SimpleStringProperty();
private StringProperty handlerName = new SimpleStringProperty();
private ObjectProperty<DictDataSimpleRespVO> status = new SimpleObjectProperty<>();
private ObservableList<JobLogRespVO> tableItems = FXCollections.observableArrayList();
private ObjectProperty<LocalDate> beginDate = new SimpleObjectProperty<>();
private ObjectProperty<LocalDate> endDate = new SimpleObjectProperty<>();
public JobLogViewModel() {
}
public void loadTableData() {
Map<String, Object> queryMap = new HashMap<>();
queryMap.put("pageNo", pageNum.get() + 1);
queryMap.put("pageSize", pageSize.get());
queryMap.put("handlerName", handlerName.get());
if (status.get() != null) {
queryMap.put("status", Convert.toInt(status.get().getValue(), null));
}
if (ObjectUtil.isAllNotEmpty(beginDate.get(), endDate.get())) {
String sd = beginDate.get().atTime(0, 0, 0).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
String ed = endDate.get().atTime(23, 59, 59).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
queryMap.put("beginTime",sd);
queryMap.put("endTime",ed);
}
ProcessChain.create()
.addRunnableInPlatformThread(() -> tableItems.clear())
.addSupplierInExecutor(() -> Request.connector(JobLogFeign.class).getJobLogPage(queryMap))
.addConsumerInPlatformThread(listCommonResult -> {
if (listCommonResult.isSuccess()) {
tableItems.setAll(listCommonResult.getCheckedData().getList());
totalProperty().set(listCommonResult.getData().getTotal().intValue());
}
}).onException(e -> e.printStackTrace())
.run();
}
public int getTotal() {
return total.get();
}
public SimpleIntegerProperty totalProperty() {
return total;
}
public int getPageNum() {
return pageNum.get();
}
public IntegerProperty pageNumProperty() {
return pageNum;
}
public int getPageSize() {
return pageSize.get();
}
public IntegerProperty pageSizeProperty() {
return pageSize;
}
public ObservableList<JobLogRespVO> getTableItems() {
return tableItems;
}
public String getName() {
return name.get();
}
public StringProperty nameProperty() {
return name;
}
public String getHandlerName() {
return handlerName.get();
}
public StringProperty handlerNameProperty() {
return handlerName;
}
public DictDataSimpleRespVO getStatus() {
return status.get();
}
public ObjectProperty<DictDataSimpleRespVO> statusProperty() {
return status;
}
public LocalDate getBeginDate() {
return beginDate.get();
}
public ObjectProperty<LocalDate> beginDateProperty() {
return beginDate;
}
public LocalDate getEndDate() {
return endDate.get();
}
public ObjectProperty<LocalDate> endDateProperty() {
return endDate;
}
}

View File

@ -0,0 +1,502 @@
package com.lw.fx.view.infra.job;
import cn.hutool.core.date.DateUtil;
import com.lw.dillon.admin.module.infra.controller.admin.job.vo.job.JobRespVO;
import com.lw.dillon.admin.module.system.controller.admin.dict.vo.data.DictDataSimpleRespVO;
import com.lw.fx.request.Request;
import com.lw.fx.store.AppStore;
import com.lw.fx.util.MessageType;
import com.lw.fx.view.control.PagingControl;
import com.lw.fx.view.control.WFXGenericDialog;
import com.lw.ui.request.api.job.JobFeign;
import com.lw.ui.utils.DictTypeEnum;
import de.saxsys.mvvmfx.*;
import io.datafx.core.concurrent.ProcessChain;
import javafx.collections.FXCollections;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.util.Callback;
import org.kordamp.ikonli.feather.Feather;
import org.kordamp.ikonli.javafx.FontIcon;
import java.net.URL;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.ResourceBundle;
import static atlantafx.base.theme.Styles.*;
import static com.lw.ui.utils.DictTypeEnum.INFRA_JOB_STATUS;
public class JobView implements FxmlView<JobViewModel>, Initializable {
@InjectViewModel
private JobViewModel viewModel;
@FXML
private Button addBut;
@FXML
private VBox contentPane;
@FXML
private TableColumn<JobRespVO, ?> cronExpressionCol;
@FXML
private TableColumn<JobRespVO, ?> handlerNameCol;
@FXML
private TextField handlerNameField;
@FXML
private TableColumn<JobRespVO, ?> handlerParamCol;
@FXML
private TableColumn<JobRespVO, ?> idCol;
@FXML
private Button infoBut;
@FXML
private TableColumn<JobRespVO, ?> nameCol;
@FXML
private TextField nameField;
@FXML
private TableColumn<JobRespVO, Long> optCol;
@FXML
private Button resetBut;
@FXML
private StackPane rootPane;
@FXML
private Button searchBut;
@FXML
private TableColumn<JobRespVO, Integer> statusCol;
@FXML
private ComboBox<DictDataSimpleRespVO> statusComboBox;
@FXML
private TableView<JobRespVO> tableView;
private PagingControl pagingControl;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
pagingControl = new PagingControl();
contentPane.getChildren().add(pagingControl);
pagingControl.totalProperty().bind(viewModel.totalProperty());
viewModel.pageNumProperty().bind(pagingControl.pageNumProperty());
viewModel.pageSizeProperty().bind(pagingControl.pageSizeProperty());
pagingControl.pageNumProperty().addListener((observable, oldValue, newValue) -> {
viewModel.loadTableData();
});
pagingControl.pageSizeProperty().addListener((observable, oldValue, newValue) -> {
viewModel.loadTableData();
});
statusComboBox.setItems(FXCollections.observableArrayList(AppStore.getDictDataList(INFRA_JOB_STATUS)));
statusComboBox.valueProperty().bindBidirectional(viewModel.statusProperty());
nameField.textProperty().bindBidirectional(viewModel.nameProperty());
handlerNameField.textProperty().bindBidirectional(viewModel.handlerNameProperty());
idCol.setCellValueFactory(new PropertyValueFactory<>("id"));
idCol.setStyle("-fx-alignment: CENTER");
nameCol.setCellValueFactory(new PropertyValueFactory<>("name"));
nameCol.setStyle("-fx-alignment: CENTER");
statusCol.setCellValueFactory(new PropertyValueFactory<>("status"));
statusCol.setStyle("-fx-alignment: CENTER");
statusCol.setCellFactory(new Callback<TableColumn<JobRespVO, Integer>, TableCell<JobRespVO, Integer>>() {
@Override
public TableCell<JobRespVO, Integer> call(TableColumn<JobRespVO, Integer> param) {
return new TableCell<>() {
@Override
protected void updateItem(Integer item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
DictDataSimpleRespVO dict = AppStore.getDictDataValueMap(INFRA_JOB_STATUS).get(item + "");
Button state = new Button(dict.getLabel());
switch (dict.getColorType()) {
case "primary":
state.getStyleClass().addAll(BUTTON_OUTLINED, ACCENT);
break;
case "success":
state.getStyleClass().addAll(BUTTON_OUTLINED, SUCCESS);
break;
case "info":
state.getStyleClass().addAll(BUTTON_OUTLINED);
break;
case "warning":
state.getStyleClass().addAll(BUTTON_OUTLINED, WARNING);
break;
case "danger":
state.getStyleClass().addAll(BUTTON_OUTLINED, DANGER);
break;
default:
state.getStyleClass().addAll(BUTTON_OUTLINED);
}
HBox box = new HBox(state);
box.setPadding(new Insets(7, 7, 7, 7));
box.setAlignment(Pos.CENTER);
setGraphic(box);
}
}
};
}
});
handlerNameCol.setCellValueFactory(new PropertyValueFactory<>("handlerName"));
handlerNameCol.setStyle("-fx-alignment: CENTER");
handlerParamCol.setCellValueFactory(new PropertyValueFactory<>("handlerParam"));
handlerParamCol.setStyle("-fx-alignment: CENTER");
cronExpressionCol.setCellValueFactory(new PropertyValueFactory<>("cronExpression"));
cronExpressionCol.setStyle("-fx-alignment: CENTER");
optCol.setCellValueFactory(new PropertyValueFactory<>("id"));
optCol.setCellFactory(new Callback<TableColumn<JobRespVO, Long>, TableCell<JobRespVO, Long>>() {
@Override
public TableCell<JobRespVO, Long> call(TableColumn<JobRespVO, Long> param) {
TableCell cell = new TableCell<JobRespVO, Long>() {
@Override
protected void updateItem(Long item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
int status=getTableRow().getItem().getStatus();
Button editBut = new Button("编辑");
editBut.setOnAction(event -> showFormView(getTableRow().getItem().getId()));
editBut.setGraphic(FontIcon.of(Feather.EDIT));
editBut.getStyleClass().addAll(FLAT, ACCENT);
Button onBut = new Button(status == 2 ? "开启" : "暂停");
onBut.setOnAction(event -> showOnDialog(getTableRow().getItem(), status == 2 ? 1 : 2));
onBut.setGraphic(FontIcon.of(Feather.ACTIVITY));
onBut.getStyleClass().addAll(FLAT, ACCENT);
Button handleRunBut = new Button("执行一次");
handleRunBut.setOnAction(event -> showTriggerJobDialog(getTableRow().getItem()));
handleRunBut.setGraphic(FontIcon.of(Feather.PLAY));
handleRunBut.getStyleClass().addAll(FLAT, ACCENT);
Button openDetailBut = new Button("任务详细");
openDetailBut.setOnAction(event -> showDetailView(getTableRow().getItem()));
openDetailBut.setGraphic(FontIcon.of(Feather.EYE));
openDetailBut.getStyleClass().addAll(FLAT, ACCENT);
Button handleJobLogBut = new Button("调度日志");
handleJobLogBut.setOnAction(event -> {
openJobLogTab(getTableRow().getItem().getHandlerName());
});
handleJobLogBut.setGraphic(FontIcon.of(Feather.DATABASE));
handleJobLogBut.getStyleClass().addAll(FLAT, ACCENT);
Button delBut = new Button("删除");
delBut.setOnAction(actionEvent -> showDelDialog(getTableRow().getItem()));
delBut.setGraphic(FontIcon.of(Feather.TRASH));
delBut.getStyleClass().addAll(FLAT, DANGER);
HBox box = new HBox(editBut, onBut, handleRunBut, openDetailBut, handleJobLogBut, delBut);
box.setAlignment(Pos.CENTER);
// box.setSpacing(7);
setGraphic(box);
}
}
};
return cell;
}
});
tableView.setItems(viewModel.getTableItems());
addBut.setOnAction(actionEvent -> showFormView(null));
searchBut.setOnAction(actionEvent -> viewModel.loadTableData());
infoBut.setOnAction(actionEvent -> openJobLogTab(null));
resetBut.setOnAction(actionEvent -> {
nameField.setText(null);
statusComboBox.getSelectionModel().select(null);
handlerNameField.setText(null);
viewModel.loadTableData();
});
}
private void openJobLogTab(String handlerName) {
ViewTuple<JobLogView, JobLogViewModel> viewTuple = FluentViewLoader.fxmlView(JobLogView.class).load();
viewTuple.getViewModel().handlerNameProperty().set(handlerName);
viewTuple.getViewModel().loadTableData();
MvvmFX.getNotificationCenter().publish("addTab", "调度日志", Feather.DATABASE, viewTuple.getView());
}
/**
* 显示编辑对话框
*/
private void showFormView(Long id) {
WFXGenericDialog dialog = new WFXGenericDialog();
boolean isAdd = (id == null);
ViewTuple<JobFormView, JobFormViewModel> load = FluentViewLoader.fxmlView(JobFormView.class).load();
load.getViewModel().updateData(id, isAdd);
dialog.addActions(
Map.entry(new Button("取消"), event -> dialog.close()),
Map.entry(new Button("确定"), event -> {
ProcessChain.create()
.addSupplierInExecutor(() -> {
return load.getViewModel().save(isAdd);
})
.addConsumerInPlatformThread(r -> {
if (r.isSuccess()) {
dialog.close();
MvvmFX.getNotificationCenter().publish("message", "保存成功", MessageType.SUCCESS);
viewModel.loadTableData();
}
}).onException(e -> e.printStackTrace())
.run();
})
);
dialog.setHeaderIcon(FontIcon.of(Feather.INFO));
dialog.setHeaderText(id != null ? "编辑Job" : "添加Job");
dialog.setContent(load.getView());
dialog.show(rootPane.getScene());
}
private void showOnDialog(JobRespVO respVO, int status) {
WFXGenericDialog dialog = new WFXGenericDialog();
dialog.setHeaderIcon(FontIcon.of(Feather.INFO));
dialog.setHeaderText("温馨提示");
String text = status == 1 ? "开启" : "关闭";
dialog.addActions(
Map.entry(new Button("取消"), event -> dialog.close()),
Map.entry(new Button("确定"), event -> {
ProcessChain.create()
.addSupplierInExecutor(() -> {
return Request.connector(JobFeign.class).updateJobStatus(respVO.getId(), status);
})
.addConsumerInPlatformThread(r -> {
if (r.isSuccess()) {
dialog.close();
MvvmFX.getNotificationCenter().publish("message", text + "成功", MessageType.SUCCESS);
viewModel.loadTableData();
}
}).onException(e -> e.printStackTrace())
.run();
})
);
dialog.setContent(new Label("确认要" + text + "定时任务编号为" + respVO.getName() + "的数据项?"));
dialog.show(rootPane.getScene());
}
private void showTriggerJobDialog(JobRespVO respVO) {
WFXGenericDialog dialog = new WFXGenericDialog();
dialog.setHeaderIcon(FontIcon.of(Feather.INFO));
dialog.setHeaderText("温馨提示");
dialog.addActions(
Map.entry(new Button("取消"), event -> dialog.close()),
Map.entry(new Button("确定"), event -> {
ProcessChain.create()
.addSupplierInExecutor(() -> {
return Request.connector(JobFeign.class).triggerJob(respVO.getId());
})
.addConsumerInPlatformThread(r -> {
if (r.isSuccess()) {
dialog.close();
MvvmFX.getNotificationCenter().publish("message", "执行成功", MessageType.SUCCESS);
viewModel.loadTableData();
}
}).onException(e -> e.printStackTrace())
.run();
})
);
dialog.setContent(new Label("确认要立即执行一次" + respVO.getName() + "的任务?"));
dialog.show(rootPane.getScene());
}
private void showDelDialog(JobRespVO respVO) {
WFXGenericDialog dialog = new WFXGenericDialog();
dialog.setHeaderIcon(FontIcon.of(Feather.INFO));
dialog.setHeaderText("温馨提示");
dialog.addActions(
Map.entry(new Button("取消"), event -> dialog.close()),
Map.entry(new Button("确定"), event -> {
ProcessChain.create()
.addSupplierInExecutor(() -> {
return Request.connector(JobFeign.class).deleteJob(respVO.getId());
})
.addConsumerInPlatformThread(r -> {
if (r.isSuccess()) {
dialog.close();
MvvmFX.getNotificationCenter().publish("message", "删除成功", MessageType.SUCCESS);
viewModel.loadTableData();
}
}).onException(e -> e.printStackTrace())
.run();
})
);
dialog.setContent(new Label("是否确认删除名称为" + respVO.getName() + "的数据项?"));
dialog.show(rootPane.getScene());
}
/**
* 显示编辑对话框
*/
private void showDetailView(JobRespVO respVo) {
ProcessChain.create()
.addSupplierInExecutor(() -> {
return Request.connector(JobFeign.class).getJobNextTimes(respVo.getId(), 5);
})
.addConsumerInPlatformThread(r -> {
if (r.isSuccess()) {
WFXGenericDialog dialog = new WFXGenericDialog();
dialog.addActions(
Map.entry(new Button("确定"), event -> {
dialog.close();
})
);
ListView<LocalDateTime> listView = new ListView(FXCollections.observableArrayList(r.getCheckedData()));
listView.setCellFactory(cell -> new ListCell<>() {
@Override
protected void updateItem(LocalDateTime localDateTime, boolean b) {
super.updateItem(localDateTime, b);
if (b) {
setText(null);
setGraphic(null);
} else {
Label numLabel = new Label("" + (getIndex() + 1) + "");
numLabel.getStyleClass().addAll("accent", "title-4");
FontIcon fontIcon = new FontIcon();
fontIcon.setIconLiteral("mdal-label");
numLabel.setGraphic(fontIcon);
Label timeLabel = new Label(DateUtil.format(getItem(), "yyyy-MM-dd HH:mm:ss"));
timeLabel.getStyleClass().addAll("text-caption", "text-muted");
VBox vBox = new VBox(10, numLabel, timeLabel);
HBox box = new HBox(vBox);
box.setPadding(new Insets(10));
setGraphic(box);
}
}
});
Label label = new Label("后续执行时间");
label.setAlignment(Pos.TOP_RIGHT);
label.setPrefWidth(100);
HBox.setHgrow(listView, Priority.ALWAYS);
HBox netTiemBox = new HBox(7, label, listView);
netTiemBox.setAlignment(Pos.TOP_CENTER);
VBox.setVgrow(netTiemBox, Priority.ALWAYS);
VBox vBox = new VBox(10, createTextField("任务编号", respVo.getId() + "")
, createTextField("任务名称", respVo.getName() + "")
, createDictBut("任务状态", respVo.getStatus(), INFRA_JOB_STATUS)
, createTextField("处理器的名字", respVo.getHandlerName())
, createTextField("处理器的参数", respVo.getHandlerParam())
, createTextField("Cron 表达式", respVo.getCronExpression())
, createTextField("重试次数", respVo.getRetryCount() + "")
, createTextField("重试间隔", respVo.getRetryInterval() + "毫秒")
, createTextField("监控超时时间", respVo.getMonitorTimeout() > 0 ? respVo.getMonitorTimeout() + "毫秒" : "未开启")
, netTiemBox
);
vBox.setPrefWidth(500);
dialog.setHeaderIcon(FontIcon.of(Feather.INFO));
dialog.setHeaderText("详情");
dialog.setContent(vBox);
dialog.show(rootPane.getScene());
}
}).onException(e -> e.printStackTrace())
.run();
}
private HBox createTextField(String text, String value) {
Label label = new Label(text);
label.setAlignment(Pos.CENTER_RIGHT);
label.setPrefWidth(100);
TextField textField = new TextField(value);
textField.setEditable(false);
HBox.setHgrow(textField, Priority.ALWAYS);
HBox hBox = new HBox(7, label, textField);
hBox.setAlignment(Pos.CENTER_LEFT);
return hBox;
}
private HBox createDictBut(String text, Object value, DictTypeEnum dictTypeEnum) {
Label label = new Label(text);
label.setAlignment(Pos.CENTER_RIGHT);
label.setPrefWidth(100);
DictDataSimpleRespVO dict = AppStore.getDictDataValueMap(dictTypeEnum).get(value + "");
Button state = new Button(dict.getLabel());
switch (dict.getColorType()) {
case "primary":
state.getStyleClass().addAll(BUTTON_OUTLINED, ACCENT);
break;
case "success":
state.getStyleClass().addAll(BUTTON_OUTLINED, SUCCESS);
break;
case "info":
state.getStyleClass().addAll(BUTTON_OUTLINED);
break;
case "warning":
state.getStyleClass().addAll(BUTTON_OUTLINED, WARNING);
break;
case "danger":
state.getStyleClass().addAll(BUTTON_OUTLINED, DANGER);
break;
default:
state.getStyleClass().addAll(BUTTON_OUTLINED);
}
HBox hBox = new HBox(7, label, state);
hBox.setAlignment(Pos.CENTER_LEFT);
return hBox;
}
}

View File

@ -0,0 +1,113 @@
package com.lw.fx.view.infra.job;
import cn.hutool.core.convert.Convert;
import com.lw.dillon.admin.module.infra.controller.admin.job.vo.job.JobRespVO;
import com.lw.dillon.admin.module.system.controller.admin.dict.vo.data.DictDataSimpleRespVO;
import com.lw.fx.request.Request;
import com.lw.ui.request.api.job.JobFeign;
import de.saxsys.mvvmfx.ViewModel;
import io.datafx.core.concurrent.ProcessChain;
import javafx.beans.property.*;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import java.util.HashMap;
import java.util.Map;
public class JobViewModel implements ViewModel {
private SimpleIntegerProperty total = new SimpleIntegerProperty(0);
private IntegerProperty pageNum = new SimpleIntegerProperty(0);
private IntegerProperty pageSize = new SimpleIntegerProperty(10);
private StringProperty name = new SimpleStringProperty();
private StringProperty handlerName = new SimpleStringProperty();
private ObjectProperty<DictDataSimpleRespVO> status = new SimpleObjectProperty<>();
private ObservableList<JobRespVO> tableItems = FXCollections.observableArrayList();
public JobViewModel() {
loadTableData();
}
public void loadTableData() {
Map<String, Object> queryMap = new HashMap<>();
queryMap.put("pageNo", pageNum.get() + 1);
queryMap.put("pageSize", pageSize.get());
queryMap.put("name", name.get());
queryMap.put("handlerName", handlerName.get());
if (status.get() != null) {
queryMap.put("status", Convert.toInt(status.get().getValue(), null));
}
ProcessChain.create()
.addRunnableInPlatformThread(() -> tableItems.clear())
.addSupplierInExecutor(() -> Request.connector(JobFeign.class).getJobPage(queryMap))
.addConsumerInPlatformThread(listCommonResult -> {
if (listCommonResult.isSuccess()) {
tableItems.setAll(listCommonResult.getCheckedData().getList());
totalProperty().set(listCommonResult.getData().getTotal().intValue());
}
}).onException(e -> e.printStackTrace())
.run();
}
public int getTotal() {
return total.get();
}
public SimpleIntegerProperty totalProperty() {
return total;
}
public int getPageNum() {
return pageNum.get();
}
public IntegerProperty pageNumProperty() {
return pageNum;
}
public int getPageSize() {
return pageSize.get();
}
public IntegerProperty pageSizeProperty() {
return pageSize;
}
public ObservableList<JobRespVO> getTableItems() {
return tableItems;
}
public String getName() {
return name.get();
}
public StringProperty nameProperty() {
return name;
}
public String getHandlerName() {
return handlerName.get();
}
public StringProperty handlerNameProperty() {
return handlerName;
}
public DictDataSimpleRespVO getStatus() {
return status.get();
}
public ObjectProperty<DictDataSimpleRespVO> statusProperty() {
return status;
}
}

View File

@ -12,59 +12,61 @@
<?import javafx.scene.layout.VBox?>
<?import org.kordamp.ikonli.javafx.FontIcon?>
<StackPane fx:id="rootPane" prefHeight="609.0" prefWidth="1223.0" styleClass="tab-center-pane" xmlns="http://javafx.com/javafx/22" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.lw.fx.view.infra.file.FileListView">
<children>
<VBox fx:id="contentPane" prefHeight="200.0" prefWidth="100.0" spacing="7.0" styleClass="sample">
<children>
<HBox alignment="CENTER_LEFT" spacing="5.0">
<children>
<Label text="文件路径" />
<TextField fx:id="pathField" prefWidth="150.0" promptText="请输入文件路径" />
<Label text="文件类型" />
<TextField fx:id="typeField" promptText="请输入文件类型" />
<Label text="创建日期" />
<DatePicker fx:id="startDatePicker" prefWidth="140.0" />
<Label text="-" />
<DatePicker fx:id="endDatePicker" prefWidth="140.0" />
<Button fx:id="searchBut" mnemonicParsing="false" text="查询">
<graphic>
<FontIcon iconLiteral="fth-search" />
</graphic>
</Button>
<Button fx:id="resetBut" mnemonicParsing="false" text="重置">
<graphic>
<FontIcon iconLiteral="fth-refresh-cw" />
</graphic>
</Button>
<Button fx:id="uploadBut" mnemonicParsing="false" text="上传文件">
<graphic>
<FontIcon iconLiteral="fth-plus" />
</graphic>
</Button>
</children>
<opaqueInsets>
<Insets />
</opaqueInsets>
</HBox>
<TableView fx:id="tableView" editable="true" VBox.vgrow="ALWAYS">
<columns>
<TableColumn fx:id="nameCol" text="文件名" />
<TableColumn fx:id="pathCol" text="文件路径" />
<TableColumn fx:id="urlCol" text="URL" />
<TableColumn fx:id="sizeCol" text="文件大小" />
<TableColumn fx:id="typeCol" text="文件类型" />
<TableColumn fx:id="centerCol" text="文件内容" />
<TableColumn fx:id="createTimeCol" text="上传时间" />
<TableColumn fx:id="optCol" text="操作" />
</columns>
<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
</columnResizePolicy>
</TableView>
</children>
</VBox>
</children>
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding>
<StackPane fx:id="rootPane" prefHeight="609.0" prefWidth="1223.0" styleClass="tab-center-pane"
xmlns="http://javafx.com/javafx/22" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="com.lw.fx.view.infra.file.FileListView">
<children>
<VBox fx:id="contentPane" prefHeight="200.0" prefWidth="100.0" spacing="7.0" styleClass="sample">
<children>
<HBox alignment="CENTER_LEFT" spacing="5.0">
<children>
<Label text="文件路径"/>
<TextField fx:id="pathField" prefWidth="150.0" promptText="请输入文件路径"/>
<Label text="文件类型"/>
<TextField fx:id="typeField" promptText="请输入文件类型"/>
<Label text="创建日期"/>
<DatePicker fx:id="startDatePicker" prefWidth="140.0"/>
<Label text="-"/>
<DatePicker fx:id="endDatePicker" prefWidth="140.0"/>
<Button fx:id="searchBut" mnemonicParsing="false" text="查询">
<graphic>
<FontIcon iconLiteral="fth-search"/>
</graphic>
</Button>
<Button fx:id="resetBut" mnemonicParsing="false" text="重置">
<graphic>
<FontIcon iconLiteral="fth-refresh-cw"/>
</graphic>
</Button>
<Button fx:id="uploadBut" mnemonicParsing="false" text="上传文件">
<graphic>
<FontIcon iconLiteral="fth-plus"/>
</graphic>
</Button>
</children>
<opaqueInsets>
<Insets/>
</opaqueInsets>
</HBox>
<TableView fx:id="tableView" editable="true" VBox.vgrow="ALWAYS">
<columns>
<TableColumn fx:id="nameCol" text="文件名"/>
<TableColumn fx:id="pathCol" text="文件路径"/>
<TableColumn fx:id="urlCol" text="URL"/>
<TableColumn fx:id="sizeCol" text="文件大小"/>
<TableColumn fx:id="typeCol" text="文件类型"/>
<TableColumn fx:id="centerCol" text="文件内容"/>
<TableColumn fx:id="createTimeCol" text="上传时间"/>
<TableColumn fx:id="optCol" text="操作"/>
</columns>
<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY"/>
</columnResizePolicy>
</TableView>
</children>
</VBox>
</children>
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
</padding>
</StackPane>

View File

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<VBox fx:id="rootBox" alignment="TOP_CENTER" prefHeight="257.0" prefWidth="620.0" spacing="10.0" xmlns="http://javafx.com/javafx/22" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.lw.fx.view.infra.job.JobFormView">
<children>
<HBox alignment="CENTER_LEFT" spacing="10.0" VBox.vgrow="ALWAYS">
<children>
<Label alignment="CENTER_RIGHT" contentDisplay="RIGHT" minWidth="80.0" text="*任务名称" />
<TextField fx:id="nameField" promptText="请输入任务名称" HBox.hgrow="ALWAYS" />
</children>
</HBox>
<HBox alignment="CENTER_LEFT" spacing="10.0" VBox.vgrow="ALWAYS">
<children>
<Label alignment="CENTER_RIGHT" contentDisplay="RIGHT" minWidth="80.0" text="*处理器的名字" />
<TextField fx:id="handlerNameField" promptText="请输入处理器的名字" HBox.hgrow="ALWAYS" />
</children>
</HBox>
<HBox fx:id="basePathBox" alignment="CENTER_LEFT" spacing="10.0" VBox.vgrow="ALWAYS">
<children>
<Label alignment="CENTER_RIGHT" contentDisplay="RIGHT" minWidth="80.0" text="*处理器的参数" />
<TextField fx:id="handlerParamField" promptText="请输入处理器的参数" HBox.hgrow="ALWAYS" />
</children>
</HBox>
<HBox fx:id="hostBox" alignment="CENTER_LEFT" spacing="10.0" VBox.vgrow="ALWAYS">
<children>
<Label alignment="CENTER_RIGHT" contentDisplay="RIGHT" minWidth="80.0" text="*CRON 表达式" />
<TextField fx:id="cronExpressionField" promptText="请输入CRON 表达式" HBox.hgrow="ALWAYS" />
</children>
</HBox>
<HBox fx:id="portBox" alignment="CENTER_LEFT" spacing="10.0" VBox.vgrow="ALWAYS">
<children>
<Label alignment="CENTER_RIGHT" contentDisplay="RIGHT" minWidth="80.0" text="*重试次数" />
<TextField fx:id="retryCountField" promptText="请输入重试次数。设置为 0 时,不进行重试" HBox.hgrow="ALWAYS" />
</children>
</HBox>
<HBox fx:id="usernameBox" alignment="CENTER_LEFT" spacing="10.0" VBox.vgrow="ALWAYS">
<children>
<Label alignment="CENTER_RIGHT" contentDisplay="RIGHT" minWidth="80.0" text="*重试间隔" />
<TextField fx:id="retryIntervalFiled" promptText="请输入重试间隔,单位:毫秒。设置为 0 时,无需间隔" HBox.hgrow="ALWAYS" />
</children>
</HBox>
<HBox fx:id="passwordBox" alignment="CENTER_LEFT" spacing="10.0" VBox.vgrow="ALWAYS">
<children>
<Label alignment="CENTER_RIGHT" contentDisplay="RIGHT" minWidth="80.0" text="*监控超时时间" />
<TextField fx:id="monitorTimeoutFiled" promptText="请输入监控超时时间,单位:毫秒" HBox.hgrow="ALWAYS" />
</children>
</HBox>
</children>
<padding>
<Insets right="10.0" />
</padding>
</VBox>

View File

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.DatePicker?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<?import org.kordamp.ikonli.javafx.FontIcon?>
<StackPane fx:id="rootPane" prefHeight="609.0" prefWidth="1223.0" styleClass="tab-center-pane" xmlns="http://javafx.com/javafx/22" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.lw.fx.view.infra.job.JobLogView">
<children>
<VBox fx:id="contentPane" prefHeight="200.0" prefWidth="100.0" spacing="7.0" styleClass="sample">
<children>
<HBox alignment="CENTER_LEFT" spacing="5.0">
<children>
<Label text="任务状态" />
<ComboBox fx:id="statusComboBox" promptText="请选择任务状态" />
<Label text="处理器的名字" />
<TextField fx:id="handlerNameField" promptText="请输入处理器的名字" />
<Label text="创建日期" />
<DatePicker fx:id="startDatePicker" prefWidth="140.0" />
<Label text="-" />
<DatePicker fx:id="endDatePicker" prefWidth="140.0" />
<Button fx:id="searchBut" mnemonicParsing="false" text="查询">
<graphic>
<FontIcon iconLiteral="fth-search" />
</graphic>
</Button>
<Button fx:id="resetBut" mnemonicParsing="false" text="重置">
<graphic>
<FontIcon iconLiteral="fth-refresh-cw" />
</graphic>
</Button>
<Button fx:id="infoBut" mnemonicParsing="false" text="执行日志" />
</children>
<opaqueInsets>
<Insets />
</opaqueInsets>
</HBox>
<TableView fx:id="tableView" editable="true" VBox.vgrow="ALWAYS">
<columns>
<TableColumn fx:id="idCol" text="日志编号" />
<TableColumn fx:id="jobIdCol" text="任务编号" />
<TableColumn fx:id="handlerNamecol" text="处理器的名字" />
<TableColumn fx:id="handlerParamCol" text="处理器的参数" />
<TableColumn fx:id="executeIndexCol" text="第几次执行" />
<TableColumn fx:id="executeTimeCol" minWidth="320.0" text="执行时间" />
<TableColumn fx:id="durationCol" text="执行时长" />
<TableColumn fx:id="statusCol" text="任务状态" />
<TableColumn fx:id="optCol" text="操作" />
</columns>
<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
</columnResizePolicy>
</TableView>
</children>
</VBox>
</children>
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding>
</StackPane>

View File

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<?import org.kordamp.ikonli.javafx.FontIcon?>
<StackPane fx:id="rootPane" prefHeight="609.0" prefWidth="1223.0" styleClass="tab-center-pane" xmlns="http://javafx.com/javafx/22" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.lw.fx.view.infra.job.JobView">
<children>
<VBox fx:id="contentPane" prefHeight="200.0" prefWidth="100.0" spacing="7.0" styleClass="sample">
<children>
<HBox alignment="CENTER_LEFT" spacing="5.0">
<children>
<Label text="任务名称" />
<TextField fx:id="nameField" prefWidth="150.0" promptText="请输入任务名称" />
<Label text="任务状态" />
<ComboBox fx:id="statusComboBox" promptText="请选择任务状态" />
<Label text="处理器的名字" />
<TextField fx:id="handlerNameField" promptText="请输入处理器的名字" />
<Button fx:id="searchBut" mnemonicParsing="false" text="查询">
<graphic>
<FontIcon iconLiteral="fth-search" />
</graphic>
</Button>
<Button fx:id="resetBut" mnemonicParsing="false" text="重置">
<graphic>
<FontIcon iconLiteral="fth-refresh-cw" />
</graphic>
</Button>
<Button fx:id="addBut" mnemonicParsing="false" text="新增">
<graphic>
<FontIcon iconLiteral="fth-plus" />
</graphic>
</Button>
<Button fx:id="infoBut" mnemonicParsing="false" text="执行日志" />
</children>
<opaqueInsets>
<Insets />
</opaqueInsets>
</HBox>
<TableView fx:id="tableView" editable="true" VBox.vgrow="ALWAYS">
<columns>
<TableColumn fx:id="idCol" text="任务编号" />
<TableColumn fx:id="nameCol" text="任务名称" />
<TableColumn fx:id="statusCol" text="任务状态" />
<TableColumn fx:id="handlerNameCol" text="处理器的名字" />
<TableColumn fx:id="handlerParamCol" text="处理器的参数" />
<TableColumn fx:id="cronExpressionCol" text="CRON 表达式" />
<TableColumn fx:id="optCol" minWidth="320.0" prefWidth="320.0" text="操作" />
</columns>
<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
</columnResizePolicy>
</TableView>
</children>
</VBox>
</children>
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding>
</StackPane>

View File

@ -76,6 +76,7 @@ public class SidePane extends WPanel {
((JLabel) component).setIcon(svgIcon);
((JLabel) component).setIconTextGap(7);
}

View File

@ -0,0 +1,170 @@
/*
* Created by JFormDesigner on Sun Jun 16 17:23:39 CST 2024
*/
package com.lw.swing.view.intra.job;
import cn.hutool.core.convert.Convert;
import com.lw.dillon.admin.framework.common.pojo.CommonResult;
import com.lw.dillon.admin.module.infra.controller.admin.job.vo.job.JobRespVO;
import com.lw.dillon.admin.module.infra.controller.admin.job.vo.job.JobSaveReqVO;
import com.lw.swing.request.Request;
import com.lw.ui.request.api.job.JobFeign;
import net.miginfocom.swing.MigLayout;
import javax.swing.*;
import java.util.concurrent.ExecutionException;
/**
* @author wenli
*/
public class JobFormPane extends JPanel {
private Long id;
public JobFormPane() {
initComponents();
}
private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents @formatter:off
// Generated using JFormDesigner non-commercial license
label1 = new JLabel();
nameField = new JTextField();
label2 = new JLabel();
handlerNameField = new JTextField();
label4 = new JLabel();
handlerParamField = new JTextField();
label5 = new JLabel();
cronExpressionField = new JTextField();
label6 = new JLabel();
retryCountField = new JTextField();
label7 = new JLabel();
retryIntervalFiled = new JTextField();
label3 = new JLabel();
monitorTimeoutField = new JTextField();
//======== this ========
setLayout(new MigLayout(
"fill,hidemode 3",
// columns
"[right]" +
"[520:n,grow,fill]",
// rows
"[]" +
"[]" +
"[]" +
"[]" +
"[]" +
"[]" +
"[]"));
//---- label1 ----
label1.setText("*\u4efb\u52a1\u540d\u79f0");
add(label1, "cell 0 0");
add(nameField, "cell 1 0");
//---- label2 ----
label2.setText("*\u5904\u7406\u5668\u7684\u540d\u5b57 ");
add(label2, "cell 0 1");
add(handlerNameField, "cell 1 1");
//---- label4 ----
label4.setText("\u5904\u7406\u5668\u7684\u53c2\u6570");
add(label4, "cell 0 2");
add(handlerParamField, "cell 1 2");
//---- label5 ----
label5.setText("*CRON \u8868\u8fbe\u5f0f");
add(label5, "cell 0 3");
add(cronExpressionField, "cell 1 3");
//---- label6 ----
label6.setText("*\u91cd\u8bd5\u6b21\u6570");
add(label6, "cell 0 4");
add(retryCountField, "cell 1 4");
//---- label7 ----
label7.setText("*\u91cd\u8bd5\u95f4\u9694");
add(label7, "cell 0 5");
add(retryIntervalFiled, "cell 1 5");
//---- label3 ----
label3.setText("\u76d1\u63a7\u8d85\u65f6\u65f6\u95f4");
add(label3, "cell 0 6");
add(monitorTimeoutField, "cell 1 6");
// JFormDesigner - End of component initialization //GEN-END:initComponents @formatter:on
}
private void setValue(JobRespVO respVO) {
nameField.setText(respVO.getName());
handlerNameField.setText(respVO.getHandlerName());
handlerParamField.setText(respVO.getHandlerParam());
cronExpressionField.setText(respVO.getCronExpression());
retryCountField.setText(respVO.getRetryCount()+"");
retryIntervalFiled.setText(respVO.getRetryInterval()+"");
monitorTimeoutField.setText(respVO.getMonitorTimeout()+"");
}
public JobSaveReqVO getValue() {
JobSaveReqVO reqVO = new JobSaveReqVO();
reqVO.setId(id);
reqVO.setName(nameField.getText());
reqVO.setHandlerName(handlerNameField.getText());
reqVO.setHandlerParam(handlerParamField.getText());
reqVO.setCronExpression(cronExpressionField.getText());
reqVO.setRetryCount(Convert.toInt(retryCountField.getText(),0));
reqVO.setRetryInterval(Convert.toInt(retryIntervalFiled.getText(),0));
reqVO.setMonitorTimeout(Convert.toInt(monitorTimeoutField.getText(),0));
return reqVO;
}
public void updateData(Long id) {
this.id = id;
SwingWorker<JobRespVO, JobRespVO> swingWorker = new SwingWorker<JobRespVO, JobRespVO>() {
@Override
protected JobRespVO doInBackground() throws Exception {
JobRespVO postRespVO = new JobRespVO();
if (id != null) {
CommonResult<JobRespVO> userResult = Request.connector(JobFeign.class).getJob(id);
postRespVO = userResult.getData();
}
return postRespVO;
}
@Override
protected void done() {
try {
setValue(get());
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
}
};
swingWorker.execute();
}
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables @formatter:off
// Generated using JFormDesigner non-commercial license
private JLabel label1;
private JTextField nameField;
private JLabel label2;
private JTextField handlerNameField;
private JLabel label4;
private JTextField handlerParamField;
private JLabel label5;
private JTextField cronExpressionField;
private JLabel label6;
private JTextField retryCountField;
private JLabel label7;
private JTextField retryIntervalFiled;
private JLabel label3;
private JTextField monitorTimeoutField;
// JFormDesigner - End of variables declaration //GEN-END:variables @formatter:on
}

View File

@ -0,0 +1,94 @@
JFDML JFormDesigner: "8.2.3.0.386" Java: "17.0.11" encoding: "UTF-8"
new FormModel {
contentType: "form/swing"
root: new FormRoot {
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "fill,hidemode 3"
"$columnConstraints": "[right][520:n,grow,fill]"
"$rowConstraints": "[][][][][][][]"
} ) {
name: "this"
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label1"
"text": "*任务名称"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 0"
} )
add( new FormComponent( "javax.swing.JTextField" ) {
name: "nameField"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 0"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label2"
"text": "*处理器的名字 "
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 1"
} )
add( new FormComponent( "javax.swing.JTextField" ) {
name: "handlerNameField"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 1"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label4"
"text": "处理器的参数"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 2"
} )
add( new FormComponent( "javax.swing.JTextField" ) {
name: "handlerParamField"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 2"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label5"
"text": "*CRON 表达式"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 3"
} )
add( new FormComponent( "javax.swing.JTextField" ) {
name: "cronExpressionField"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 3"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label6"
"text": "*重试次数"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 4"
} )
add( new FormComponent( "javax.swing.JTextField" ) {
name: "retryCountField"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 4"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label7"
"text": "*重试间隔"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 5"
} )
add( new FormComponent( "javax.swing.JTextField" ) {
name: "retryIntervalFiled"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 5"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "label3"
"text": "监控超时时间"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 6"
} )
add( new FormComponent( "javax.swing.JTextField" ) {
name: "monitorTimeoutField"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 6"
} )
}, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 )
"size": new java.awt.Dimension( 695, 445 )
} )
}
}

View File

@ -0,0 +1,378 @@
/*
* Created by JFormDesigner on Thu Jun 13 19:52:21 CST 2024
*/
package com.lw.swing.view.intra.job;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.formdev.flatlaf.extras.FlatSVGIcon;
import com.lw.dillon.admin.framework.common.pojo.CommonResult;
import com.lw.dillon.admin.framework.common.pojo.PageResult;
import com.lw.dillon.admin.module.infra.controller.admin.job.vo.log.JobLogRespVO;
import com.lw.dillon.admin.module.system.controller.admin.dict.vo.data.DictDataSimpleRespVO;
import com.lw.swing.components.*;
import com.lw.swing.components.table.renderer.OptButtonTableCellEditor;
import com.lw.swing.components.table.renderer.OptButtonTableCellRenderer;
import com.lw.swing.request.Request;
import com.lw.swing.store.AppStore;
import com.lw.swing.utils.BadgeLabelUtil;
import com.lw.ui.request.api.job.JobLogFeign;
import com.lw.ui.utils.DictTypeEnum;
import net.miginfocom.swing.MigLayout;
import org.jdesktop.swingx.JXTable;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.util.List;
import java.util.*;
import java.util.concurrent.ExecutionException;
import static com.lw.ui.utils.DictTypeEnum.*;
import static javax.swing.JOptionPane.OK_CANCEL_OPTION;
import static javax.swing.JOptionPane.PLAIN_MESSAGE;
/**
* @author wenli
*/
public class JobLogPane extends JPanel {
private String[] COLUMN_ID = {"日志编号", "任务编号", "处理器的名字", "处理器的参数", "第几次执行", "执行时间", "执行时长", "任务状态", "操作"};
private DefaultTableModel tableModel;
private WPaginationPane paginationPane;
public JobLogPane() {
initComponents();
initListeners();
}
private void initComponents() {
textField = new JTextField();
scrollPane1 = new WScrollPane();
centerPane = new JPanel();
scrollPane2 = new WScrollPane();
table = new JXTable(tableModel = new DefaultTableModel());
toolPane = new WPanel();
label7 = new JLabel();
handlerNameField = new JTextField();
label9 = new JLabel();
stautsComboBox = new JComboBox();
label10 = new JLabel();
startDateTextField = new WLocalDateCombo();
label11 = new JLabel();
endDateTextField = new WLocalDateCombo();
searchBut = new JButton();
reseBut = new JButton();
//======== this ========
setOpaque(false);
setLayout(new BorderLayout(10, 10));
//======== centerPane ========
{
centerPane.setOpaque(false);
centerPane.setLayout(new BorderLayout(10, 10));
//======== scrollPane2 ========
{
tableModel.setColumnIdentifiers(COLUMN_ID);
scrollPane2.setViewportView(table);
}
JPanel panel = new WPanel();
panel.setLayout(new BorderLayout());
panel.add(scrollPane2);
paginationPane = new WPaginationPane() {
@Override
public void setPageIndex(long pageIndex) {
super.setPageIndex(pageIndex);
loadTableData("");
}
};
paginationPane.setOpaque(false);
panel.add(paginationPane, BorderLayout.SOUTH);
centerPane.add(panel, BorderLayout.CENTER);
//======== toolPane ========
{
toolPane.setLayout(new MigLayout(
"fill,insets 0,hidemode 3",
// columns
"[left]",
// rows
"[]"));
toolPane.setBorder(new EmptyBorder(10, 10, 10, 10));
//---- label7 ----
label7.setText("处理器的名字");
toolPane.add(label7, "cell 0 0");
//---- userNameTextField ----
handlerNameField.setColumns(15);
toolPane.add(handlerNameField, "cell 0 0");
//---- label9 ----
label9.setText("任务状态");
toolPane.add(label9, "cell 0 0");
toolPane.add(stautsComboBox, "cell 0 0");
//---- label10 ----
label10.setText("执行时间");
toolPane.add(label10, "cell 0 0");
//---- startDateTextField ----
toolPane.add(startDateTextField, "cell 0 0");
//---- label11 ----
label11.setText("-");
toolPane.add(label11, "cell 0 0");
//---- endDateTextField ----
toolPane.add(endDateTextField, "cell 0 0");
//---- button1 ----
searchBut.setText("\u641c\u7d22");
toolPane.add(searchBut, "cell 0 0");
//---- reseBut ----
reseBut.setText("\u91cd\u7f6e");
toolPane.add(reseBut, "cell 0 0");
}
centerPane.add(toolPane, BorderLayout.NORTH);
}
add(centerPane, BorderLayout.CENTER);
// JFormDesigner - End of component initialization //GEN-END:initComponents @formatter:on
table.setRowHeight(40);
AppStore.getDictDataList(INFRA_JOB_STATUS).forEach(dictDataSimpleRespVO -> {
stautsComboBox.addItem(dictDataSimpleRespVO);
});
stautsComboBox.setSelectedItem(null);
startDateTextField.setValue(null);
endDateTextField.setValue(null);
table.setDefaultRenderer(Object.class, new CenterTableCellRenderer());
centerPane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
}
private JToolBar creatBar() {
JToolBar optBar = new JToolBar();
optBar.setOpaque(false);
JButton detailsBut = new JButton("详细");
detailsBut.setForeground(UIManager.getColor("App.accentColor"));
detailsBut.setIcon(new FlatSVGIcon("icons/xiugai.svg", 15, 15));
detailsBut.addActionListener(e -> showDetails());
detailsBut.setForeground(UIManager.getColor("App.accentColor"));
optBar.add(Box.createGlue());
optBar.add(detailsBut);
optBar.add(Box.createGlue());
return optBar;
}
private void initListeners() {
reseBut.addActionListener(e -> reset());
searchBut.addActionListener(e -> loadTableData(""));
}
private void showDetails() {
int selRow = table.getSelectedRow();
JobLogRespVO finalRespVO = null;
if (selRow != -1) {
finalRespVO = (JobLogRespVO) table.getValueAt(selRow, COLUMN_ID.length - 1);
}
JPanel panel = new JPanel();
panel.setLayout(new MigLayout(
"fill,insets 0,hidemode 3",
// columns
"[fill][grow,fill]",
// rows
"[][][][][][][][]"));
panel.setPreferredSize(new Dimension(450, 500));
addMessageInfo("日志编号", finalRespVO.getId(), panel, 0);
addMessageInfo("任务编号", finalRespVO.getJobId(), panel, 1);
addMessageInfo("处理器的名字", finalRespVO.getHandlerName(), panel, 2);
addMessageInfo("处理器的参数", finalRespVO.getHandlerParam(), panel, 3);
addMessageInfo("第几次执行", finalRespVO.getExecuteIndex(), panel, 4);
addMessageInfo("执行时间", DateUtil.format(Convert.toLocalDateTime(finalRespVO.getBeginTime()), "yyyy-MM-dd HH:mm:ss") + " ~ " + DateUtil.format(Convert.toLocalDateTime(finalRespVO.getEndTime()), "yyyy-MM-dd HH:mm:ss"), panel, 5);
addMessageInfo("执行时长", finalRespVO.getDuration() + " 毫秒", panel, 6);
addMessageInfo("任务状态", INFRA_JOB_LOG_STATUS, finalRespVO.getStatus(), panel, 7);
addMessageInfo("执行结果", finalRespVO.getResult(), panel, 8);
WOptionPane.showOptionDialog(null, panel, "任务详细", OK_CANCEL_OPTION, PLAIN_MESSAGE, null, new Object[]{"确定", "取消"}, "确定");
}
private void reset() {
handlerNameField.setText("");
stautsComboBox.setSelectedItem(null);
startDateTextField.setValue(null);
endDateTextField.setValue(null);
loadTableData("");
}
private void addMessageInfo(String text, Object value, JPanel panel, int row) {
JLabel label = new JLabel(text,JLabel.RIGHT);
JTextField textField = new JTextField(Convert.toStr(value));
textField.setEditable(false);
panel.add(label, "cell 0 " + row);
panel.add(textField, "cell 1 " + row);
}
private void addMessageInfo(String text, DictTypeEnum dictType, Object value, JPanel panel, int row) {
JLabel label = new JLabel(text,JLabel.RIGHT);
JLabel badge = BadgeLabelUtil.getBadgeLabel(dictType, value);
panel.add(label, "cell 0 " + row);
panel.add(badge, "cell 1 " + row + ",alignx left,growx 0");
}
@Override
public void updateUI() {
super.updateUI();
if (table != null) {
table.setDefaultRenderer(Object.class, new CenterTableCellRenderer());
}
}
public void loadTableData(String handlerName) {
handlerNameField.setText(handlerName);
Map<String, Object> queryMap = new HashMap<>();
queryMap.put("pageNo", paginationPane.getPageIndex());
queryMap.put("pageSize", paginationPane.getPageSize());
if (StrUtil.isNotBlank(handlerNameField.getText())) {
handlerName = handlerNameField.getText();
}
Integer stauts = null;
if (stautsComboBox.getSelectedItem() != null) {
DictDataSimpleRespVO dictDataSimpleRespVO = (DictDataSimpleRespVO) stautsComboBox.getSelectedItem();
stauts = Convert.toInt(dictDataSimpleRespVO.getValue(), null);
}
if (ObjectUtil.isAllNotEmpty(startDateTextField.getValue(), endDateTextField.getValue())) {
String[] dateTimes = new String[2];
dateTimes[0] = DateUtil.format(startDateTextField.getValue().atTime(0, 0, 0), "yyyy-MM-dd HH:mm:ss");
dateTimes[1] = DateUtil.format(endDateTextField.getValue().atTime(23, 59, 59), "yyyy-MM-dd HH:mm:ss");
queryMap.put("beginTime", dateTimes[0]);
queryMap.put("endTime", dateTimes[1]);
}
queryMap.put("handlerName", handlerName);
queryMap.put("stauts", stauts);
SwingWorker<Vector<Vector>, Long> swingWorker = new SwingWorker<Vector<Vector>, Long>() {
@Override
protected Vector<Vector> doInBackground() throws Exception {
CommonResult<PageResult<JobLogRespVO>> result = Request.connector(JobLogFeign.class).getJobLogPage(queryMap);
Vector<Vector> tableData = new Vector<>();
if (result.isSuccess()) {
result.getData().getList().forEach(respVO -> {
Vector rowV = new Vector();
rowV.add(respVO.getId());
rowV.add(respVO.getJobId());
rowV.add(respVO.getHandlerName());
rowV.add(respVO.getHandlerParam());
rowV.add(respVO.getExecuteIndex());
rowV.add(DateUtil.format(Convert.toLocalDateTime(respVO.getBeginTime()), "yyyy-MM-dd HH:mm:ss") + " ~ " + DateUtil.format(Convert.toLocalDateTime(respVO.getEndTime()), "yyyy-MM-dd HH:mm:ss"));
rowV.add(respVO.getDuration() + " 毫秒");
rowV.add(respVO.getStatus());
rowV.add(respVO);
tableData.add(rowV);
});
publish(result.getData().getTotal());
}
return tableData;
}
@Override
protected void process(List<Long> chunks) {
chunks.forEach(total -> paginationPane.setTotal(total));
}
@Override
protected void done() {
try {
tableModel.setDataVector(get(), new Vector<>(Arrays.asList(COLUMN_ID)));
table.getColumn("执行时间").setMinWidth(300);
table.getColumn("操作").setMinWidth(80);
table.getColumn("操作").setCellRenderer(new OptButtonTableCellRenderer(creatBar()));
table.getColumn("操作").setCellEditor(new OptButtonTableCellEditor(creatBar()));
table.getColumn("任务状态").setCellRenderer(new DefaultTableCellRenderer() {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 15, 10));
JLabel label = BadgeLabelUtil.getBadgeLabel(INFRA_JOB_STATUS, value);
panel.add(label);
panel.setBackground(component.getBackground());
panel.setOpaque(isSelected);
return panel;
}
});
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
}
};
swingWorker.execute();
}
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables @formatter:off
// Generated using JFormDesigner non-commercial license
private JTextField textField;
private JScrollPane scrollPane1;
private JPanel centerPane;
private JScrollPane scrollPane2;
private JTable table;
private JPanel toolPane;
private JLabel label7;
private JTextField handlerNameField;
private JLabel label9;
private JComboBox<DictDataSimpleRespVO> stautsComboBox;
private JLabel label10;
private WLocalDateCombo startDateTextField;
private JLabel label11;
private WLocalDateCombo endDateTextField;
private JButton searchBut;
private JButton reseBut;
// JFormDesigner - End of variables declaration //GEN-END:variables @formatter:on
}

View File

@ -0,0 +1,645 @@
/*
* Created by JFormDesigner on Thu Jun 13 19:52:21 CST 2024
*/
package com.lw.swing.view.intra.job;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.formdev.flatlaf.extras.FlatSVGIcon;
import com.lw.dillon.admin.framework.common.pojo.CommonResult;
import com.lw.dillon.admin.framework.common.pojo.PageResult;
import com.lw.dillon.admin.module.infra.controller.admin.job.vo.job.JobRespVO;
import com.lw.dillon.admin.module.infra.controller.admin.job.vo.job.JobSaveReqVO;
import com.lw.dillon.admin.module.system.controller.admin.dict.vo.data.DictDataSimpleRespVO;
import com.lw.swing.components.*;
import com.lw.swing.components.notice.WMessage;
import com.lw.swing.components.table.renderer.OptButtonTableCellEditor;
import com.lw.swing.components.table.renderer.OptButtonTableCellRenderer;
import com.lw.swing.request.Request;
import com.lw.swing.store.AppStore;
import com.lw.swing.utils.BadgeLabelUtil;
import com.lw.swing.view.MainFrame;
import com.lw.ui.request.api.job.JobFeign;
import com.lw.ui.utils.DictTypeEnum;
import net.miginfocom.swing.MigLayout;
import org.jdesktop.swingx.JXTable;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.time.LocalDateTime;
import java.util.List;
import java.util.*;
import java.util.concurrent.ExecutionException;
import static com.lw.ui.utils.DictTypeEnum.INFRA_JOB_STATUS;
import static javax.swing.JOptionPane.*;
/**
* @author wenli
*/
public class JobPane extends JPanel {
private String[] COLUMN_ID = {"任务编号", "任务名称", "任务状态", "处理器的名字", "处理器的参数", "CRON 表达式", "操作"};
private DefaultTableModel tableModel;
private WPaginationPane paginationPane;
public JobPane() {
initComponents();
initListeners();
loadTableData();
}
private void initComponents() {
textField = new JTextField();
scrollPane1 = new WScrollPane();
centerPane = new JPanel();
scrollPane2 = new WScrollPane();
table = new JXTable(tableModel = new DefaultTableModel());
toolPane = new WPanel();
label7 = new JLabel();
nameField = new JTextField();
label9 = new JLabel();
handlerNameField = new JTextField();
searchBut = new JButton();
reseBut = new JButton();
newBut = new JButton();
//======== this ========
setOpaque(false);
setLayout(new BorderLayout(10, 10));
//======== centerPane ========
{
centerPane.setOpaque(false);
centerPane.setLayout(new BorderLayout(10, 10));
//======== scrollPane2 ========
{
tableModel.setColumnIdentifiers(COLUMN_ID);
scrollPane2.setViewportView(table);
}
JPanel panel = new WPanel();
panel.setLayout(new BorderLayout());
panel.add(scrollPane2);
paginationPane = new WPaginationPane() {
@Override
public void setPageIndex(long pageIndex) {
super.setPageIndex(pageIndex);
loadTableData();
}
};
paginationPane.setOpaque(false);
panel.add(paginationPane, BorderLayout.SOUTH);
centerPane.add(panel, BorderLayout.CENTER);
//======== toolPane ========
{
toolPane.setLayout(new MigLayout(
"fill,insets 0,hidemode 3",
// columns
"[left]",
// rows
"[]"));
toolPane.setBorder(new EmptyBorder(10, 10, 10, 10));
//---- label7 ----
label7.setText("任务名称");
toolPane.add(label7, "cell 0 0");
//---- userNameTextField ----
nameField.setColumns(15);
toolPane.add(nameField, "cell 0 0");
//---- label7 ----
toolPane.add(new JLabel("任务状态"), "cell 0 0");
toolPane.add(statusComboBox = new JComboBox(), "cell 0 0");
//---- label9 ----
label9.setText("处理器的名字");
toolPane.add(label9, "cell 0 0");
handlerNameField.setColumns(15);
toolPane.add(handlerNameField, "cell 0 0");
//---- button1 ----
searchBut.setText("搜索");
toolPane.add(searchBut, "cell 0 0");
//---- reseBut ----
reseBut.setText("重置");
toolPane.add(reseBut, "cell 0 0");
//---- newBut ----
newBut.setText("新增");
toolPane.add(newBut, "cell 0 0");
toolPane.add(logBut = new JButton("调度日志"), "cell 0 0");
}
centerPane.add(toolPane, BorderLayout.NORTH);
}
add(centerPane, BorderLayout.CENTER);
// JFormDesigner - End of component initialization //GEN-END:initComponents @formatter:on
table.setRowHeight(40);
table.setDefaultRenderer(Object.class, new CenterTableCellRenderer());
AppStore.getDictDataList(INFRA_JOB_STATUS).forEach(dictDataSimpleRespVO -> {
statusComboBox.addItem(dictDataSimpleRespVO);
});
statusComboBox.setSelectedItem(null);
}
private JToolBar creatBar() {
JToolBar optBar = new JToolBar();
optBar.setOpaque(false);
JButton del = new JButton("删除");
del.setIcon(new FlatSVGIcon("icons/delte.svg", 15, 15));
del.addActionListener(e -> del());
del.setForeground(UIManager.getColor("app-error-color-5"));
JButton editBut = new JButton("修改");
editBut.setForeground(UIManager.getColor("App.accentColor"));
editBut.addActionListener(e -> showEditDialog());
JButton statusBut = new JButton("开启/暂停");
statusBut.setForeground(UIManager.getColor("App.accentColor"));
statusBut.addActionListener(e -> showOnDialog());
JButton executeBut = new JButton("执行一次");
executeBut.setForeground(UIManager.getColor("App.accentColor"));
executeBut.addActionListener(e -> triggerJob());
JButton detailBut = new JButton("任务详细");
detailBut.setForeground(UIManager.getColor("App.accentColor"));
detailBut.addActionListener(e -> showDetailsDialog());
JButton logBut = new JButton("调度日志");
logBut.addActionListener(e -> showJobLog());
logBut.setForeground(UIManager.getColor("App.accentColor"));
optBar.add(Box.createGlue());
optBar.add(editBut);
optBar.add(statusBut);
optBar.add(executeBut);
optBar.add(detailBut);
optBar.add(logBut);
optBar.add(del);
optBar.add(Box.createGlue());
return optBar;
}
private void initListeners() {
reseBut.addActionListener(e -> reset());
searchBut.addActionListener(e -> loadTableData());
newBut.addActionListener(e -> showAddDialog(null));
logBut.addActionListener(e -> showJobLogTab(new JobRespVO()));
}
private void reset() {
nameField.setText("");
handlerNameField.setText(null);
statusComboBox.setSelectedItem(null);
loadTableData();
}
private void showEditDialog() {
int selRow = table.getSelectedRow();
Long id = null;
if (selRow != -1) {
id = Convert.toLong(table.getValueAt(selRow, 0));
}
JobFormPane roleEditPane = new JobFormPane();
roleEditPane.updateData(id);
int opt = WOptionPane.showOptionDialog(null, roleEditPane, "修改", OK_CANCEL_OPTION, PLAIN_MESSAGE, null, new Object[]{"确定", "取消"}, "确定");
if (opt == 0) {
edit(roleEditPane.getValue());
}
}
private void showAddDialog(Long id) {
JobFormPane formPane = new JobFormPane();
formPane.updateData(id);
int opt = WOptionPane.showOptionDialog(null, formPane, "添加", OK_CANCEL_OPTION, PLAIN_MESSAGE, null, new Object[]{"确定", "取消"}, "确定");
if (opt == 0) {
add(formPane.getValue());
}
}
@Override
public void updateUI() {
super.updateUI();
if (table != null) {
table.setDefaultRenderer(Object.class, new CenterTableCellRenderer());
}
}
/**
* 添加
*/
private void add(JobSaveReqVO saveReqVO) {
SwingWorker<CommonResult<Long>, Object> swingWorker = new SwingWorker<CommonResult<Long>, Object>() {
@Override
protected CommonResult<Long> doInBackground() throws Exception {
return Request.connector(JobFeign.class).createJob(saveReqVO);
}
@Override
protected void done() {
try {
if (get().isSuccess()) {
WMessage.showMessageSuccess(MainFrame.getInstance(), "添加成功!");
loadTableData();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
swingWorker.execute();
}
private void edit(JobSaveReqVO saveReqVO) {
SwingWorker<CommonResult<Boolean>, Object> swingWorker = new SwingWorker<CommonResult<Boolean>, Object>() {
@Override
protected CommonResult<Boolean> doInBackground() throws Exception {
return Request.connector(JobFeign.class).updateJob(saveReqVO);
}
@Override
protected void done() {
try {
if (get().isSuccess()) {
WMessage.showMessageSuccess(MainFrame.getInstance(), "修改成功!");
loadTableData();
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
}
};
swingWorker.execute();
}
private void triggerJob() {
Long id = null;
int selRow = table.getSelectedRow();
JobRespVO jobRespVO = null;
if (selRow != -1) {
id = Convert.toLong(table.getValueAt(selRow, 0));
jobRespVO = (JobRespVO) table.getValueAt(selRow, COLUMN_ID.length - 1);
}
int opt = WOptionPane.showOptionDialog(this, "是否要执行[" + jobRespVO.getHandlerName() + "]", "提示", OK_CANCEL_OPTION, WARNING_MESSAGE, null, null, null);
if (opt != 0) {
return;
}
Long finalId = id;
SwingWorker<CommonResult<Boolean>, Object> swingWorker = new SwingWorker<CommonResult<Boolean>, Object>() {
@Override
protected CommonResult<Boolean> doInBackground() throws Exception {
return Request.connector(JobFeign.class).triggerJob(finalId);
}
@Override
protected void done() {
try {
if (get().isSuccess()) {
WMessage.showMessageSuccess(MainFrame.getInstance(), "执行成功!");
loadTableData();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
swingWorker.execute();
}
private void showOnDialog() {
Long id = null;
JobRespVO jobRespVO = null;
int selRow = table.getSelectedRow();
if (selRow != -1) {
id = Convert.toLong(table.getValueAt(selRow, 0));
jobRespVO = (JobRespVO) table.getValueAt(selRow, COLUMN_ID.length - 1);
}
String text = (jobRespVO.getStatus() == 2) ? "开启" : "暂停";
int opt = WOptionPane.showOptionDialog(this, "是否" + text + "[" + jobRespVO.getName() + "]", "提示", OK_CANCEL_OPTION, WARNING_MESSAGE, null, null, null);
if (opt != 0) {
return;
}
Long finalId = id;
int status = jobRespVO.getStatus() == 2 ? 1 : 2;
SwingWorker<CommonResult<Boolean>, Object> swingWorker = new SwingWorker<CommonResult<Boolean>, Object>() {
@Override
protected CommonResult<Boolean> doInBackground() throws Exception {
return Request.connector(JobFeign.class).updateJobStatus(finalId, status);
}
@Override
protected void done() {
try {
if (get().isSuccess()) {
WMessage.showMessageSuccess(MainFrame.getInstance(), text + "成功!");
loadTableData();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
swingWorker.execute();
}
private void del() {
Long id = null;
String userName = null;
int selRow = table.getSelectedRow();
if (selRow != -1) {
id = Convert.toLong(table.getValueAt(selRow, 0));
userName = Convert.toStr(table.getValueAt(selRow, 1));
}
int opt = WOptionPane.showOptionDialog(this, "是否确定删除[" + userName + "]", "提示", OK_CANCEL_OPTION, WARNING_MESSAGE, null, null, null);
if (opt != 0) {
return;
}
Long finalId = id;
SwingWorker<CommonResult<Boolean>, Object> swingWorker = new SwingWorker<CommonResult<Boolean>, Object>() {
@Override
protected CommonResult<Boolean> doInBackground() throws Exception {
return Request.connector(JobFeign.class).deleteJob(finalId);
}
@Override
protected void done() {
try {
if (get().isSuccess()) {
WMessage.showMessageSuccess(MainFrame.getInstance(), "删除成功!");
loadTableData();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
swingWorker.execute();
}
public void loadTableData() {
Map<String, Object> queryMap = new HashMap<>();
queryMap.put("pageNo", paginationPane.getPageIndex());
queryMap.put("pageSize", paginationPane.getPageSize());
String name = null;
String handlerName = null;
if (StrUtil.isNotBlank(nameField.getText())) {
name = nameField.getText();
}
if (StrUtil.isNotBlank(handlerNameField.getText())) {
handlerName = handlerNameField.getText();
}
Integer status = null;
if (statusComboBox.getSelectedItem() != null) {
DictDataSimpleRespVO dictDataSimpleRespVO = (DictDataSimpleRespVO) statusComboBox.getSelectedItem();
status = Convert.toInt(dictDataSimpleRespVO.getValue(), null);
}
queryMap.put("name", name);
queryMap.put("handlerName", handlerName);
queryMap.put("status", status);
SwingWorker<Vector<Vector>, Long> swingWorker = new SwingWorker<Vector<Vector>, Long>() {
@Override
protected Vector<Vector> doInBackground() throws Exception {
CommonResult<PageResult<JobRespVO>> result = Request.connector(JobFeign.class).getJobPage(queryMap);
Vector<Vector> tableData = new Vector<Vector>();
if (result.isSuccess()) {
result.getData().getList().forEach(respVO -> {
Vector rowV = new Vector();
rowV.add(respVO.getId());
rowV.add(respVO.getName());
rowV.add(respVO.getStatus());
rowV.add(respVO.getHandlerName());
rowV.add(respVO.getHandlerParam());
rowV.add(respVO.getCronExpression());
rowV.add(respVO);
tableData.add(rowV);
});
publish(result.getData().getTotal());
}
return tableData;
}
@Override
protected void process(List<Long> chunks) {
chunks.forEach(total -> paginationPane.setTotal(total));
}
@Override
protected void done() {
try {
tableModel.setDataVector(get(), new Vector<>(Arrays.asList(COLUMN_ID)));
table.getColumn("操作").setMinWidth(240);
table.getColumn("操作").setCellRenderer(new OptButtonTableCellRenderer(creatBar()));
table.getColumn("操作").setCellEditor(new OptButtonTableCellEditor(creatBar()));
table.getColumn("任务状态").setCellRenderer(new DefaultTableCellRenderer() {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 15, 10));
JLabel label = BadgeLabelUtil.getBadgeLabel(INFRA_JOB_STATUS, value);
panel.add(label);
panel.setBackground(component.getBackground());
panel.setOpaque(isSelected);
return panel;
}
});
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
}
};
swingWorker.execute();
}
private void showDetailsDialog() {
int selRow = table.getSelectedRow();
JobRespVO respVO = null;
if (selRow != -1) {
respVO = (JobRespVO) table.getValueAt(selRow, COLUMN_ID.length - 1);
}
JobRespVO finalRespVO = respVO;
SwingWorker<DefaultListModel, Long> swingWorker = new SwingWorker<DefaultListModel, Long>() {
@Override
protected DefaultListModel doInBackground() throws Exception {
CommonResult<List<LocalDateTime>> result = Request.connector(JobFeign.class).getJobNextTimes(finalRespVO.getId(), 5);
DefaultListModel listModel = new DefaultListModel();
if (result.isSuccess()) {
int index = 1;
for (LocalDateTime dateTime : result.getData()) {
listModel.addElement("" + index + "次: " + DateUtil.format(dateTime, "yyyy-MM-dd HH:mm:ss"));
index++;
}
}
return listModel;
}
@Override
protected void process(List<Long> chunks) {
chunks.forEach(total -> paginationPane.setTotal(total));
}
@Override
protected void done() {
try {
JList<String> list = new JList<>();
list.setModel(get());
JPanel panel = new JPanel();
panel.setLayout(new MigLayout(
"fill,insets 0,hidemode 3",
// columns
"[fill][grow,fill]",
// rows
"[][][][][][][][][][]"));
panel.setPreferredSize(new Dimension(450, 600));
addMessageInfo("任务编号", finalRespVO.getId(), panel, 0);
addMessageInfo("任务名称", finalRespVO.getName(), panel, 1);
addMessageInfo("任务状态", INFRA_JOB_STATUS, finalRespVO.getStatus(), panel, 2);
addMessageInfo("处理器的名字", finalRespVO.getHandlerName(), panel, 3);
addMessageInfo("处理器的参数", finalRespVO.getHandlerParam(), panel, 4);
addMessageInfo("Cron 表达式", finalRespVO.getCronExpression(), panel, 5);
addMessageInfo("重试次数", finalRespVO.getRetryCount(), panel, 6);
addMessageInfo("重试间隔", finalRespVO.getRetryInterval(), panel, 7);
addMessageInfo("监控超时时间", finalRespVO.getMonitorTimeout(), panel, 8);
panel.add(new JLabel("后续执行时间"), "cell 0 9");
panel.add(list, "cell 1 9,growy 0");
WOptionPane.showOptionDialog(null, panel, "任务详细", OK_CANCEL_OPTION, PLAIN_MESSAGE, null, new Object[]{"确定", "取消"}, "确定");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
swingWorker.execute();
}
private void addMessageInfo(String text, Object value, JPanel panel, int row) {
JLabel label = new JLabel(text);
JTextField textField = new JTextField(Convert.toStr(value));
textField.setEditable(false);
panel.add(label, "cell 0 " + row);
panel.add(textField, "cell 1 " + row);
}
private void addMessageInfo(String text, DictTypeEnum dictType, Object value, JPanel panel, int row) {
JLabel label = new JLabel(text);
JLabel badge = BadgeLabelUtil.getBadgeLabel(dictType, value);
panel.add(label, "cell 0 " + row);
panel.add(badge, "cell 1 " + row + ",alignx left,growx 0");
}
private void showJobLog() {
int selRow = table.getSelectedRow();
JobRespVO respVO = null;
if (selRow != -1) {
respVO = (JobRespVO) table.getValueAt(selRow, COLUMN_ID.length - 1);
showJobLogTab(respVO);
}
}
private void showJobLogTab(JobRespVO respVO) {
int tabIndex = MainFrame.getInstance().getTabbedPane().indexOfTab("调度日志");
JobLogPane jobLogPane;
if (tabIndex == -1) {
jobLogPane = new JobLogPane();
MainFrame.getInstance().getTabbedPane().addTab("调度日志", jobLogPane);
} else {
jobLogPane = (JobLogPane) MainFrame.getInstance().getTabbedPane().getComponentAt(tabIndex);
}
MainFrame.getInstance().getTabbedPane().setSelectedIndex(MainFrame.getInstance().getTabbedPane().indexOfTab("调度日志"));
jobLogPane.loadTableData(respVO.getHandlerName());
}
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables @formatter:off
// Generated using JFormDesigner non-commercial license
private JTextField textField;
private JScrollPane scrollPane1;
private JPanel centerPane;
private JScrollPane scrollPane2;
private JTable table;
private JPanel toolPane;
private JLabel label7;
private JTextField nameField;
private JLabel label9;
private JTextField handlerNameField;
private JComboBox statusComboBox;
private JButton searchBut;
private JButton reseBut;
private JButton newBut;
private JButton logBut;
// JFormDesigner - End of variables declaration //GEN-END:variables @formatter:on
}

BIN
dump.rdb Normal file

Binary file not shown.