增加javafx版消息模板、消息记录和我的消息功能

This commit is contained in:
wenli 2024-07-24 21:15:54 +08:00
parent 3f2a14363e
commit fa6aaa96ee
55 changed files with 3293 additions and 109 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 296 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 320 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 325 KiB

View File

@ -1,5 +1,3 @@
# Dillon-Admin-Pro
java权限管理系统桌面客户端
@ -8,7 +6,6 @@ java权限管理系统桌面客户端
本项目是一套权限管理系统的用户界面(UI)实现分别使用java图形化JavaFX和Java Swing技术实现了两套桌面客户端界面同时也可支持web的界面使用
以下是本项目使用的技术栈和相关组件:
应用程序结构:采用 mvvmFX 框架,该框架基于 MVVM (Model-View-ViewModel) 架构模式,用于实现数据绑定和视图模型的管理。
@ -23,13 +20,11 @@ java权限管理系统桌面客户端
HTTP库使用 OpenFeign HTTP库该库提供了方便的 HTTP 请求和响应处理功能,用于与后端服务器进行通信和数据交互。
本项目的目标是提供一套完整的、易于使用的权限管理系统UI适用于个人用户和企业用户。界面设计参考了若依前端基于 RuoYi-Vue
本项目的目标是提供一套完整的、易于使用的权限管理系统UI适用于个人用户和企业用户。界面设计参考了若依前端基于 [芋道源码/yudao-ui-admin-vue3](https://github.com/yudaocode/yudao-ui-admin-vue3/)
的设计,以提供现代化、直观的用户界面。同时,使用了多种技术和组件来增强用户体验,包括数据绑定、主题化、图标和动画等方面。
请注意,本项目仅提供用户界面(UI)部分的实现,后端采用了若依/RuoYi-Cloud 框架作为后台支持。如果需要完整的权限管理系统,需要结合后端框架使用。
* 界面参考若依前端(基于 [RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue))
* 后端采用[若依/RuoYi-Cloud](https://gitee.com/y_project/RuoYi-Cloud)
* 界面基于 [芋道源码/yudao-ui-admin-vue3](https://github.com/yudaocode/yudao-ui-admin-vue3/)
* 后端采用[芋道源码/ruoyi-vue-pro](https://github.com/YunaiV/ruoyi-vue-pro)
* 前端技术栈:
* 应用程序结构 [mvvmFX](https://github.com/sialcasa/mvvmFX) ([文档](https://github.com/sialcasa/mvvmFX/wiki))
* 主题 [atlantafx](https://github.com/mkpaz/atlantafx) ([文档](https://mkpaz.github.io/atlantafx/))
@ -39,6 +34,7 @@ HTTP库使用 OpenFeign HTTP库该库提供了方便的 HTTP 请求和响
* http库 [OpenFeign](https://github.com/OpenFeign/feign)
## mvvmfx包找不到的话请使用Sonatype快照存储库将此存储库添加到 pom.xml 的 <repositorys> 部分
```agsl
<repository>
<id>sonatype-snapshots</id>
@ -48,14 +44,52 @@ HTTP库使用 OpenFeign HTTP库该库提供了方便的 HTTP 请求和响
</snapshots>
</repository>
```
## 启动说明
## 快速启动(后端项目)
### 1 初始化 Redis
项目使用 Redis 缓存数据,所以需要启动一个 Redis 服务。
> 不会安装的胖友,可以选择阅读下文
> * Windows 安装 Redis 指南http://www.iocoder.cn/Redis/windows-install
> * Mac 安装 Redis 指南http://www.iocoder.cn/Redis/mac-install
默认配置下Redis 启动在 6379 端口,不设置账号密码。如果不一致,需要修改 application-local.yaml 配置文件。
```agsl
# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
redis:
host: 127.0.0.1 # 地址
port: 6379 # 端口
database: 0 # 数据库索引
```
### 2 启动后端项目
> 执行 com.lw.dillon.admin.server.DillonServerApplication 类,进行启动。
启动完成后,使用浏览器访问 http://127.0.0.1:48080地址返回如下 JSON 字符串,说明成功。
```agsl
{
"code": 401,
"data": null,
"msg": "账号未登录"
}
```
## javafx
```agsl
1 在idea右侧栏找到Maven展开并点击Plugins->sass-cli:run会编译出index.css
2 运行主类com.lw.fx.AppStart即可
```
## javaSwing
```agsl
1 运行主类com.lw.swing.DillonSwingUiApplication即可
```
@ -64,7 +98,6 @@ HTTP库使用 OpenFeign HTTP库该库提供了方便的 HTTP 请求和响
>
> * 后端只修改了system_menu表增加了component_swing和component_fx两个字段分别对应javaSwing和javaFx的界面类
## 🐶 新手必读
* 演示地址【Vue3 + element-plus】<http://dashboard-vue3.yudao.iocoder.cn>
@ -73,24 +106,25 @@ HTTP库使用 OpenFeign HTTP库该库提供了方便的 HTTP 请求和响
### 系统功能
| | 功能 | 描述 |
|-----|-------|---------------------------------|
| | 用户管理 | 用户是系统操作者,该功能主要完成系统用户配置 |
| ⭐️ | 在线用户 | 当前系统中活跃用户状态监控,支持手动踢下线 |
| | 角色管理 | 角色菜单权限分配、设置角色按机构进行数据范围权限划分 |
| | 菜单管理 | 配置系统菜单、操作权限、按钮权限标识等,本地缓存提供性能 |
| | 部门管理 | 配置系统组织机构(公司、部门、小组),树结构展现支持数据权限 |
| | 岗位管理 | 配置系统用户所属担任职务 |
| | 字典管理 | 对系统中经常使用的一些较为固定的数据进行维护 |
| 🚀 | 操作日志 | 系统正常操作日志记录和查询,集成 Swagger 生成日志内容 |
| ⭐️ | 登录日志 | 系统登录日志记录查询,包含登录异常 |
| | 通知公告 | 系统通知公告信息发布维护 |
| | 功能 | 描述 |
|----|------|---------------------------------|
| | 用户管理 | 用户是系统操作者,该功能主要完成系统用户配置 |
| ⭐️ | 在线用户 | 当前系统中活跃用户状态监控,支持手动踢下线 |
| | 角色管理 | 角色菜单权限分配、设置角色按机构进行数据范围权限划分 |
| | 菜单管理 | 配置系统菜单、操作权限、按钮权限标识等,本地缓存提供性能 |
| | 部门管理 | 配置系统组织机构(公司、部门、小组),树结构展现支持数据权限 |
| | 岗位管理 | 配置系统用户所属担任职务 |
| | 字典管理 | 对系统中经常使用的一些较为固定的数据进行维护 |
| 🚀 | 操作日志 | 系统正常操作日志记录和查询,集成 Swagger 生成日志内容 |
| ⭐️ | 登录日志 | 系统登录日志记录查询,包含登录异常 |
| | 通知公告 | 系统通知公告信息发布维护 |
## 🐷 演示图
### 系统功能
### JavaFX
| 模块 | 浅色 | 深色 | 玻璃 |
|------|------------------------------------|------------------------------------|------------------------------------|
| 登录 | ![登录](/.image/javafx/登录.png) | - | - |
@ -104,12 +138,15 @@ HTTP库使用 OpenFeign HTTP库该库提供了方便的 HTTP 请求和响
| 字典管理 | ![字典管理](/.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
| 模块 | 浅色 | 深色 | 玻璃 |
|------|-----------------------------------|-----------------------------------|-----------------------------------|
| 登录 | ![登录](/.image/swing/登录.png) | - | - |

View File

@ -46,4 +46,5 @@ public class NotifyMessageRespVO {
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}

View File

@ -0,0 +1,47 @@
package com.lw.ui.request.api.system;
import com.lw.dillon.admin.framework.common.pojo.CommonResult;
import com.lw.dillon.admin.framework.common.pojo.PageResult;
import com.lw.dillon.admin.module.system.controller.admin.notify.vo.message.NotifyMessageRespVO;
import com.lw.ui.request.api.BaseFeignApi;
import feign.Param;
import feign.QueryMap;
import feign.RequestLine;
import java.util.List;
import java.util.Map;
public interface NotifyMessageFeign extends BaseFeignApi {
// ========== 管理所有的站内信 ==========
//获得站内信")
@RequestLine("GET /admin-api/system/notify-message/get?id={id}")
CommonResult<NotifyMessageRespVO> getNotifyMessage(@Param("id") Long id);
//获得站内信分页")
@RequestLine("GET /admin-api/system/notify-message/page")
CommonResult<PageResult<NotifyMessageRespVO>> getNotifyMessagePage(@QueryMap Map<String, Object> pageVO);
// ========== 查看自己的站内信 ==========
//获得我的站内信分页"
@RequestLine("GET /admin-api/system/notify-message/my-page")
CommonResult<PageResult<NotifyMessageRespVO>> getMyMyNotifyMessagePage(@QueryMap Map<String, Object> pageVO);
//标记站内信为已读")
@RequestLine("PUT /admin-api/system/notify-message/update-read?ids={ids}")
CommonResult<Boolean> updateNotifyMessageRead( @Param("ids")List<Long> ids);
//标记所有站内信为已读")
@RequestLine("PUT /admin-api/system/notify-message/update-all-read")
CommonResult<Boolean> updateAllNotifyMessageRead();
@RequestLine("GET /admin-api/system/notify-message/get-unread-list?size={size}")
CommonResult<List<NotifyMessageRespVO>> getUnreadNotifyMessageList(@Param("size") Integer size);
//获得当前用户的未读站内信数量")
@RequestLine("GET /admin-api/system/notify-message/get-unread-count")
CommonResult<Long> getUnreadNotifyMessageCount();
}

View File

@ -0,0 +1,41 @@
package com.lw.ui.request.api.system;
import com.lw.dillon.admin.framework.common.pojo.CommonResult;
import com.lw.dillon.admin.framework.common.pojo.PageResult;
import com.lw.dillon.admin.module.system.controller.admin.notify.vo.template.NotifyTemplateRespVO;
import com.lw.dillon.admin.module.system.controller.admin.notify.vo.template.NotifyTemplateSaveReqVO;
import com.lw.dillon.admin.module.system.controller.admin.notify.vo.template.NotifyTemplateSendReqVO;
import com.lw.ui.request.api.BaseFeignApi;
import feign.Param;
import feign.QueryMap;
import feign.RequestLine;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.Map;
@Tag(name = "管理后台 - 站内信模版")
public interface NotifyTemplateFeign extends BaseFeignApi {
//"创建站内信模版")
@RequestLine("POST /admin-api/system/notify-template/create")
CommonResult<Long> createNotifyTemplate(NotifyTemplateSaveReqVO createReqVO);
//"更新站内信模版")
@RequestLine("PUT /admin-api/system/notify-template/update")
CommonResult<Boolean> updateNotifyTemplate(NotifyTemplateSaveReqVO updateReqVO);
//"删除站内信模版")
@RequestLine("DELETE /admin-api/system/notify-template/delete?id={id}")
CommonResult<Boolean> deleteNotifyTemplate(@Param("id") Long id);
//"获得站内信模版")
@RequestLine("GET /admin-api/system/notify-template/get?id={id}")
CommonResult<NotifyTemplateRespVO> getNotifyTemplate(@Param("id") Long id);
//"获得站内信模版分页")
@RequestLine("GET /admin-api/system/notify-template/page")
CommonResult<PageResult<NotifyTemplateRespVO>> getNotifyTemplatePage(@QueryMap Map<String,Object> pageVO);
//"发送站内信")
@RequestLine("POST /admin-api/system/notify-template/send-notify")
CommonResult<Long> sendNotify(NotifyTemplateSendReqVO sendReqVO);
}

View File

@ -85,7 +85,7 @@ public class Request {
.decoder(GSON_DECODER)
.encoder(GSON_ENCODER)
.logger(new Slf4jLogger())
.logLevel(Logger.Level.FULL)
.logLevel(Logger.Level.BASIC)
.client(new OkHttpClient(OK_HTTP_CLIENT))
.requestInterceptor(new ForwardedForInterceptor())
.retryer(new Retryer.Default()); // 默认重试策略

View File

@ -5,6 +5,7 @@ import animatefx.animation.AnimationFX;
import animatefx.animation.FadeIn;
import animatefx.animation.FadeOut;
import animatefx.util.ParallelAnimationFX;
import atlantafx.base.controls.Popover;
import atlantafx.base.theme.Tweaks;
import cn.hutool.core.util.StrUtil;
import com.dlsc.gemsfx.AvatarView;
@ -23,6 +24,7 @@ import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Bounds;
@ -35,8 +37,12 @@ import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;
import org.kordamp.ikonli.Ikon;
import org.kordamp.ikonli.feather.Feather;
import org.kordamp.ikonli.javafx.FontIcon;
import org.kordamp.ikonli.javafx.Icon;
import org.kordamp.ikonli.material2.Material2AL;
import org.kordamp.ikonli.material2.Material2MZ;
import java.net.URL;
import java.util.ResourceBundle;
@ -56,6 +62,10 @@ public class MainView implements FxmlView<MainViewModel>, Initializable {
@FXML
private Button maximizeBut;
@FXML
private Button noticeBut;
@FXML
private Label tagLabel;
@FXML
private Button closeBut;
@FXML
private Button logoBut;
@ -66,6 +76,8 @@ public class MainView implements FxmlView<MainViewModel>, Initializable {
@FXML
private VBox sideBox;
private Popover popover;
private NavTree<AuthPermissionInfoRespVO.MenuVO> sideMenu;
private Lazy<ThemeDialog> themeDialog;
@ -78,6 +90,10 @@ public class MainView implements FxmlView<MainViewModel>, Initializable {
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
popover = new Popover();
popover.setHeaderAlwaysVisible(false);
popover.setArrowLocation(Popover.ArrowLocation.TOP_CENTER);
tabPane.setTabClosingPolicy(TabPane.TabClosingPolicy.ALL_TABS);
rootPane.getStyleClass().add("main-view");
sideMenu = new NavTree<>();
@ -131,11 +147,9 @@ public class MainView implements FxmlView<MainViewModel>, Initializable {
logoBut.textProperty().bindBidirectional(mainViewModel.titleProperty());
logoBut.getStyleClass().addAll(BUTTON_OUTLINED, FLAT, "title-1");
userBut.initialsProperty().bind(mainViewModel.nickNameProperty());
themeBut.setGraphic(theme);
themeBut.setOnAction(e -> openThemeDialog());
userBut.setOnMouseClicked(event -> showPersonalInformation());
minimizeBut.setOnAction(actionEvent -> {
if (minimizeBut.getScene() instanceof BorderlessScene) {
@ -167,21 +181,33 @@ public class MainView implements FxmlView<MainViewModel>, Initializable {
initListeners();
noticeBut.setOnMouseClicked(actionEvent ->{
ViewTuple<MessageView, MessageViewModel> viewTuple = FluentViewLoader.fxmlView(MessageView.class).load();
popover.setContentNode(viewTuple.getView());
popover.show(noticeBut);
} );
FadeTransition fadeTransition = new FadeTransition(Duration.millis(400), rootPane);
fadeTransition.setFromValue(0);
fadeTransition.setToValue(1);
fadeTransition.play();
ViewTuple<DashboardView, DashboardViewModel> viewTuple = FluentViewLoader.fxmlView(DashboardView.class).load();
loddTab( "主页", "home",false, viewTuple.getView());
loddTab("主页", Material2AL.HOME, false, viewTuple.getView());
MvvmFX.getNotificationCenter().subscribe("showThemePage", (key, payload) -> {
// trigger some actions
Platform.runLater(() -> {
loddTab("个性化设置", "home",true, new ThemePage());
loddTab("个性化设置", Material2AL.APP_SETTINGS_ALT, true, new ThemePage());
});
});
toggleStyleClass(sideMenu, Tweaks.ALT_ICON);
tagLabel.visibleProperty().bind(Bindings.createBooleanBinding( () -> {
String text = mainViewModel.unreadCountProperty().get();
return text != null && !text.isEmpty();
},
mainViewModel.unreadCountProperty()));
tagLabel.textProperty().bindBidirectional(mainViewModel.unreadCountProperty());
}
@ -221,7 +247,7 @@ public class MainView implements FxmlView<MainViewModel>, Initializable {
// trigger some actions
Platform.runLater(() -> {
loddTab((String) payload[0], (String) payload[1], true,(Parent) payload[2]);
loddTab((String) payload[0], (Ikon) payload[1], true, (Parent) payload[2]);
});
@ -320,7 +346,7 @@ public class MainView implements FxmlView<MainViewModel>, Initializable {
fadeTransition.play();
}
private void loddTab(String title, String icon, Boolean colse, Parent node) {
private void loddTab(String title, Ikon icon, Boolean colse, Parent node) {
Tab tab = null;
var tabOptional = tabPane.getTabs().stream()
.filter(t -> StrUtil.equals(t.getText(), title))
@ -333,7 +359,7 @@ public class MainView implements FxmlView<MainViewModel>, Initializable {
tab = new Tab(title);
tab.setClosable(colse);
tab.setId("main-tab");
FontIcon fontIcon = new FontIcon(Feather.STAR);
FontIcon fontIcon = new FontIcon(icon);
fontIcon.setIconSize(24);
tab.setGraphic(fontIcon);
tabPane.getTabs().add(tab);
@ -365,7 +391,7 @@ public class MainView implements FxmlView<MainViewModel>, Initializable {
menuItem1.setOnAction(actionEvent -> {
ViewTuple<UserInfoView, UserInfoViewModel> viewTuple = FluentViewLoader.fxmlView(UserInfoView.class).load();
MvvmFX.getNotificationCenter().publish("addTab", "个人中心", "", viewTuple.getView());
MvvmFX.getNotificationCenter().publish("addTab", "个人中心", Feather.USER, viewTuple.getView());
});

View File

@ -1,10 +1,12 @@
package com.lw.fx.view.main;
import cn.hutool.core.convert.Convert;
import com.lw.dillon.admin.module.system.controller.admin.auth.vo.AuthPermissionInfoRespVO;
import com.lw.fx.request.Request;
import com.lw.fx.store.AppStore;
import com.lw.fx.util.MessageType;
import com.lw.ui.request.api.system.AuthFeign;
import com.lw.ui.request.api.system.NotifyMessageFeign;
import de.saxsys.mvvmfx.MvvmFX;
import de.saxsys.mvvmfx.SceneLifecycle;
import de.saxsys.mvvmfx.ViewModel;
@ -23,13 +25,18 @@ public class MainViewModel implements ViewModel, SceneLifecycle {
private SimpleObjectProperty theme = new SimpleObjectProperty();
private SimpleBooleanProperty showNavigationBar = new SimpleBooleanProperty(true);
private StringProperty title = new SimpleStringProperty(System.getProperty("app.name"));
private StringProperty nickName = new SimpleStringProperty();
private StringProperty unreadCount = new SimpleStringProperty();
public void initialize() {
getPermissionInfo();
MvvmFX.getNotificationCenter().subscribe("notify", (key, payload) -> getPermissionInfo());
MvvmFX.getNotificationCenter().subscribe("updateMenu", (key, payload) -> getPermissionInfo());
}
public String getTitle() {
@ -134,7 +141,15 @@ public class MainViewModel implements ViewModel, SceneLifecycle {
}
})
.addSupplierInExecutor(() -> Request.connector(NotifyMessageFeign.class).getUnreadNotifyMessageCount())
.addConsumerInPlatformThread(rel -> {
if (rel.isSuccess()) {
unreadCount.set(rel.getData() == 0 ? "" : rel.getData() + "");
}
})
.onException(e -> {
unreadCount.set("");
e.printStackTrace();
})
.withFinal(() -> {
@ -165,4 +180,12 @@ public class MainViewModel implements ViewModel, SceneLifecycle {
public StringProperty nickNameProperty() {
return nickName;
}
public String getUnreadCount() {
return unreadCount.get();
}
public StringProperty unreadCountProperty() {
return unreadCount;
}
}

View File

@ -0,0 +1,105 @@
package com.lw.fx.view.main;
import com.lw.dillon.admin.module.system.controller.admin.notify.vo.message.NotifyMessageRespVO;
import com.lw.fx.request.Request;
import com.lw.fx.util.MessageType;
import com.lw.fx.view.system.config.UserInfoView;
import com.lw.fx.view.system.config.UserInfoViewModel;
import com.lw.fx.view.system.notice.MyNotifyMessageView;
import com.lw.fx.view.system.notice.MyNotifyMessageViewModel;
import com.lw.ui.request.api.system.NotifyMessageFeign;
import de.saxsys.mvvmfx.*;
import io.datafx.core.concurrent.ProcessChain;
import javafx.beans.binding.Bindings;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.*;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import org.kordamp.ikonli.feather.Feather;
import org.kordamp.ikonli.javafx.FontIcon;
import org.kordamp.ikonli.material2.Material2AL;
import java.net.URL;
import java.time.format.DateTimeFormatter;
import java.util.ResourceBundle;
import static atlantafx.base.theme.Styles.*;
public class MessageView implements FxmlView<MessageViewModel>, Initializable {
@FXML
private ListView<NotifyMessageRespVO> listView;
@FXML
private Hyperlink markersBut;
@FXML
private Hyperlink viewAllBut;
@InjectViewModel
private MessageViewModel viewModel;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
listView.setItems(viewModel.getItems());
listView.setFixedCellSize(65);
listView.setCellFactory(cell -> new ListCell<>() {
@Override
protected void updateItem(NotifyMessageRespVO notifyMessageRespVO, boolean b) {
super.updateItem(notifyMessageRespVO, b);
if (b) {
setText("");
setGraphic(null);
} else {
Label content = new Label(notifyMessageRespVO.getTemplateNickname() + " : " + notifyMessageRespVO.getTemplateContent());
content.getStyleClass().addAll("text-caption");
content.setMaxHeight(Double.MAX_VALUE);
VBox.setVgrow(content, Priority.ALWAYS);
content.setPadding(new Insets(0, 10, 0, 10));
Label createTime = new Label(notifyMessageRespVO.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
createTime.getStyleClass().addAll("text-muted");
Label typeBut = new Label("系统消息");
typeBut.setGraphic(new FontIcon(Material2AL.LABEL));
typeBut.getStyleClass().addAll(ACCENT);
Pane pane = new Pane();
HBox.setHgrow(pane, Priority.ALWAYS);
HBox hBox = new HBox(10, createTime, pane, typeBut);
hBox.setAlignment(Pos.CENTER_LEFT);
hBox.setPadding(new Insets(0, 10, 0, 10));
VBox vBox = new VBox(5, content, hBox);
vBox.setPadding(new Insets(10, 0, 0, 0));
hBox.setStyle("-fx-border-width: 0 0 1 0;-fx-border-color: -color-border-default;");
setGraphic(vBox);
}
}
});
markersBut.visibleProperty().bind(Bindings.createBooleanBinding(() -> {
return viewModel.getItems().isEmpty() == false;
}, viewModel.getItems()));
viewAllBut.setOnMouseClicked(mouseEvent -> {
ViewTuple<MyNotifyMessageView, MyNotifyMessageViewModel> viewTuple = FluentViewLoader.fxmlView(MyNotifyMessageView.class).load();
MvvmFX.getNotificationCenter().publish("addTab", "我的消息", Feather.MAIL, viewTuple.getView());
});
markersBut.setOnMouseClicked(mouseEvent -> {
ProcessChain.create()
.addSupplierInExecutor(() -> viewModel.updateNotifyMessageRead())
.addConsumerInPlatformThread(rel -> {
if (rel.isSuccess()) {
MvvmFX.getNotificationCenter().publish("message", "标记为已读成功", MessageType.SUCCESS);
MvvmFX.getNotificationCenter().publish("notify", "标记为已读成功");
viewModel.getUnreadNotifyMessageList();
}
}).run();
});
}
}

View File

@ -0,0 +1,75 @@
package com.lw.fx.view.main;
import com.lw.dillon.admin.framework.common.pojo.CommonResult;
import com.lw.dillon.admin.module.system.controller.admin.notify.vo.message.NotifyMessageRespVO;
import com.lw.fx.request.Request;
import com.lw.fx.util.MessageType;
import com.lw.fx.vo.NotifyMessageVo;
import com.lw.ui.request.api.system.NotifyMessageFeign;
import de.saxsys.mvvmfx.MvvmFX;
import de.saxsys.mvvmfx.SceneLifecycle;
import de.saxsys.mvvmfx.ViewModel;
import io.datafx.core.concurrent.ProcessChain;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import java.util.HashSet;
import java.util.Set;
public class MessageViewModel implements ViewModel, SceneLifecycle {
private ObservableList<NotifyMessageRespVO> items = FXCollections.observableArrayList();
public MessageViewModel() {
getUnreadNotifyMessageList();
}
public CommonResult<Boolean> updateNotifyMessageRead() {
Set<Long> ids = new HashSet<>();
for (NotifyMessageRespVO notifyMessageRespVO : items) {
ids.add(notifyMessageRespVO.getId());
}
return Request.connector(NotifyMessageFeign.class).updateNotifyMessageRead(ids.stream().toList());
}
public void getUnreadNotifyMessageList() {
ProcessChain.create().addRunnableInPlatformThread(() -> items.clear())
.addSupplierInExecutor(() -> {
return Request.connector(NotifyMessageFeign.class).getUnreadNotifyMessageList(10);
})
.addConsumerInPlatformThread(r -> {
if (r.isSuccess()) {
items.setAll(r.getData());
} else {
}
})
.onException(e -> {
e.printStackTrace();
})
.withFinal(() -> {
})
.run();
}
@Override
public void onViewAdded() {
}
@Override
public void onViewRemoved() {
}
public ObservableList<NotifyMessageRespVO> getItems() {
return items;
}
}

View File

@ -103,13 +103,12 @@ public class DeptFromView implements FxmlView<DeptFromViewModel>, Initializable
nameTextField.textProperty().bindBidirectional(viewModel.nameProperty());
deptTree.rootProperty().bind(viewModel.deptTreeRootProperty());
sortNumFeild.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, Integer.MAX_VALUE, 0));
viewModel.sortProperty().addListener((observable, oldValue, newValue) -> {
sortNumFeild.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, Integer.MAX_VALUE, newValue.intValue()));
});
sortNumFeild.valueProperty().addListener((observableValue, integer, t1) -> {
viewModel.sortProperty().set(t1);
});
viewModel.sortProperty().addListener((observable, oldValue, newValue) -> viewModel.sortProperty().setValue(newValue));
viewModel.statusProperty().addListener((observableValue, number, t1) -> statusToggleBut.setSelected(NumberUtil.equals(t1, 0)));
statusToggleBut.selectedProperty().addListener((observableValue, aBoolean, t1) -> viewModel.statusProperty().set(t1 ? 0 : 1));

View File

@ -57,7 +57,7 @@ public class DictTypeFormViewModel implements ViewModel {
wrapper.reload();
}
public CommonResult saveUser(boolean isAdd) {
public CommonResult save(boolean isAdd) {
if (isAdd) {
return Request.connector(DictTypeFeign.class).createDictType(getUserSaveReqVO());

View File

@ -192,14 +192,14 @@ public class DictTypeView implements FxmlView<DictTypeViewModel>, Initializable
dataBut.setOnAction(event -> {
ViewTuple<DictDataView, DictDataViewModel> viewTuple = FluentViewLoader.fxmlView(DictDataView.class).load();
viewTuple.getViewModel().loadDictTypeData(getTableRow().getItem().getType());
MvvmFX.getNotificationCenter().publish("addTab", "字典数据", "", viewTuple.getView());
MvvmFX.getNotificationCenter().publish("addTab", "字典数据", Feather.DATABASE, viewTuple.getView());
});
dataBut.setGraphic(FontIcon.of(Feather.EDIT));
dataBut.getStyleClass().addAll(FLAT, ACCENT);
Button editBut = new Button("修改");
editBut.setOnAction(event -> showDictTypeFormView(getTableRow().getItem().getId()));
editBut.setOnAction(event -> showFormView(getTableRow().getItem().getId()));
editBut.setGraphic(FontIcon.of(Feather.EDIT));
editBut.getStyleClass().addAll(FLAT, ACCENT);
@ -235,25 +235,25 @@ public class DictTypeView implements FxmlView<DictTypeViewModel>, Initializable
startDatePicker.valueProperty().bindBidirectional(viewModel.beginDateProperty());
endDatePicker.valueProperty().bindBidirectional(viewModel.endDateProperty());
addBut.setOnAction(actionEvent -> showDictTypeFormView(null));
addBut.setOnAction(actionEvent -> showFormView(null));
}
/**
* 显示编辑对话框
*/
private void showDictTypeFormView(Long roleId) {
private void showFormView(Long id) {
WFXGenericDialog dialog = new WFXGenericDialog();
boolean isAdd = (roleId == null);
boolean isAdd = (id == null);
ViewTuple<DictTypeFormView, DictTypeFormViewModel> load = FluentViewLoader.fxmlView(DictTypeFormView.class).load();
load.getViewModel().query(roleId);
load.getViewModel().query(id);
dialog.addActions(
Map.entry(new Button("取消"), event -> dialog.close()),
Map.entry(new Button("确定"), event -> {
ProcessChain.create()
.addSupplierInExecutor(() -> {
return load.getViewModel().saveUser(isAdd);
return load.getViewModel().save(isAdd);
})
.addConsumerInPlatformThread(r -> {
if (r.isSuccess()) {
@ -268,7 +268,7 @@ public class DictTypeView implements FxmlView<DictTypeViewModel>, Initializable
);
dialog.setHeaderIcon(FontIcon.of(Feather.INFO));
dialog.setHeaderText(roleId != null ? "编辑角色" : "添加角色");
dialog.setHeaderText(id != null ? "编辑角色" : "添加角色");
dialog.setContent(load.getView());
dialog.show(rootPane.getScene());

View File

@ -63,7 +63,7 @@ public class DictDataFormViewModel implements ViewModel {
wrapper.reload();
}
public CommonResult saveUser(boolean isAdd) {
public CommonResult save(boolean isAdd) {
if (isAdd) {
return Request.connector(DictDataFeign.class).createDictData(getUserSaveReqVO());

View File

@ -247,7 +247,7 @@ public class DictDataView implements FxmlView<DictDataViewModel>, Initializable
Map.entry(new Button("确定"), event -> {
ProcessChain.create()
.addSupplierInExecutor(() -> {
return load.getViewModel().saveUser(isAdd);
return load.getViewModel().save(isAdd);
})
.addConsumerInPlatformThread(r -> {
if (r.isSuccess()) {

View File

@ -264,7 +264,7 @@ public class LoginLogView implements FxmlView<LoginLogViewModel>, Initializable
Button editBut = new Button("详情");
editBut.setOnAction(event -> showDictTypeFormView(getTableRow().getItem()));
editBut.setOnAction(event -> showFormView(getTableRow().getItem()));
editBut.setGraphic(FontIcon.of(Feather.EDIT));
editBut.getStyleClass().addAll(FLAT, ACCENT);
@ -304,7 +304,7 @@ public class LoginLogView implements FxmlView<LoginLogViewModel>, Initializable
/**
* 显示编辑对话框
*/
private void showDictTypeFormView(LoginLogRespVO operateLogRespVO) {
private void showFormView(LoginLogRespVO operateLogRespVO) {
WFXGenericDialog dialog = new WFXGenericDialog();
ViewTuple<LoginLogDetailView, LoginLogDetailViewModel> load = FluentViewLoader.fxmlView(LoginLogDetailView.class).load();

View File

@ -166,11 +166,13 @@ public class MenuFromView implements FxmlView<MenuFromViewModel>, Initializable
}
});
sortNumFeild.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, Integer.MAX_VALUE, 0));
viewModel.sortProperty().addListener((observable, oldValue, newValue) -> {
sortNumFeild.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, Integer.MAX_VALUE, newValue.intValue()));
});
sortNumFeild.valueProperty().addListener((observableValue, integer, t1) -> {
viewModel.sortProperty().set(t1);
});
viewModel.sortProperty().addListener((observable, oldValue, newValue) -> viewModel.sortProperty().setValue(newValue));
viewModel.statusProperty().addListener((observableValue, number, t1) -> statusToggleBut.setSelected(NumberUtil.equals(t1, 0)));
statusToggleBut.selectedProperty().addListener((observableValue, aBoolean, t1) -> viewModel.statusProperty().set(t1 ? 0 : 1));

View File

@ -35,7 +35,7 @@ public class MenuFromViewModel implements ViewModel, SceneLifecycle {
public void initialize() {
sortProperty().set(-1);
}
@ -50,14 +50,15 @@ public class MenuFromViewModel implements ViewModel, SceneLifecycle {
if (isEdit) {
return Request.connector(MenuFeign.class).updateMenu(wrapper.get());
} else {
return Request.connector(MenuFeign.class).createMenu(wrapper.get());
return Request.connector(MenuFeign.class).createMenu(wrapper.get());
}
}
public void updateData(MenuRespVO sysMenu, boolean isAdd) {
MenuSaveVO saveVO = new MenuSaveVO();
BeanUtil.copyProperties(sysMenu,saveVO);
BeanUtil.copyProperties(sysMenu, saveVO);
ProcessChain.create()
.addRunnableInPlatformThread(() -> wrapper.set(saveVO))
.addSupplierInExecutor(() -> Request.connector(MenuFeign.class).getSimpleMenuList())

View File

@ -41,7 +41,6 @@ public class MenuManageView implements FxmlView<MenuManageViewModel>, Initializa
private MenuManageViewModel viewModel;
@FXML
private VBox content;
@ -157,7 +156,7 @@ public class MenuManageView implements FxmlView<MenuManageViewModel>, Initializa
setGraphic(null);
} else {
Button state = new Button();
if (item!=null&&item==0) {
if (item != null && item == 0) {
state.setText("正常");
state.getStyleClass().addAll(BUTTON_OUTLINED, SUCCESS);
} else {
@ -263,17 +262,17 @@ public class MenuManageView implements FxmlView<MenuManageViewModel>, Initializa
WFXGenericDialog dialog = new WFXGenericDialog();
ViewTuple<MenuFromView, MenuFromViewModel> load = FluentViewLoader.fxmlView(MenuFromView.class).load();
MenuRespVO menuRespVO=null;
MenuRespVO menuRespVO = null;
if (isEdit) {
menuRespVO = sysMenu;
}else {
} else {
menuRespVO = new MenuRespVO();
menuRespVO.setParentId(sysMenu.getId());
menuRespVO.setType(1);
}
load.getViewModel().updateData(menuRespVO,true);
dialog.clearActions();
dialog.addActions(
load.getViewModel().updateData(menuRespVO, true);
dialog.clearActions();
dialog.addActions(
Map.entry(new Button("取消"), event -> dialog.close()),
Map.entry(new Button("确定"), event -> {
@ -283,7 +282,7 @@ public class MenuManageView implements FxmlView<MenuManageViewModel>, Initializa
if (r.isSuccess()) {
dialog.close();
MvvmFX.getNotificationCenter().publish("message", "保存成功", MessageType.SUCCESS);
MvvmFX.getNotificationCenter().publish("updateMenu", "更新菜单");
query();
}
}).onException(e -> e.printStackTrace())
@ -292,16 +291,15 @@ public class MenuManageView implements FxmlView<MenuManageViewModel>, Initializa
);
dialog.setHeaderIcon(FontIcon.of(Feather.INFO));
dialog.setHeaderText(isEdit ? "编辑菜单" : "添加菜单");
dialog.setContent(load.getView());
dialog.show(root.getScene());
dialog.setHeaderIcon(FontIcon.of(Feather.INFO));
dialog.setHeaderText(isEdit ? "编辑菜单" : "添加菜单");
dialog.setContent(load.getView());
dialog.show(root.getScene());
}
/**
* 显示del对话框
*
@ -309,8 +307,8 @@ public class MenuManageView implements FxmlView<MenuManageViewModel>, Initializa
*/
private void showDelDialog(MenuRespVO sysMenu) {
WFXGenericDialog dialog = new WFXGenericDialog();
dialog.clearActions();
dialog.addActions(
dialog.clearActions();
dialog.addActions(
Map.entry(new Button("取消"), event -> dialog.close()),
Map.entry(new Button("确定"), event -> {
@ -327,10 +325,10 @@ public class MenuManageView implements FxmlView<MenuManageViewModel>, Initializa
);
dialog.setHeaderIcon(FontIcon.of(Feather.INFO));
dialog.setHeaderText("系统揭示");
dialog.setContent(new Label("是否确认删除名称为" + sysMenu.getName() + "的数据项?"));
dialog.show(root.getScene());
dialog.setHeaderIcon(FontIcon.of(Feather.INFO));
dialog.setHeaderText("系统揭示");
dialog.setContent(new Label("是否确认删除名称为" + sysMenu.getName() + "的数据项?"));
dialog.show(root.getScene());
}
/**
@ -341,8 +339,4 @@ public class MenuManageView implements FxmlView<MenuManageViewModel>, Initializa
}
}

View File

@ -0,0 +1,450 @@
package com.lw.fx.view.system.notice;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import com.dlsc.gemsfx.DialogPane;
import com.lw.dillon.admin.module.system.controller.admin.dict.vo.data.DictDataSimpleRespVO;
import com.lw.dillon.admin.module.system.controller.admin.logger.vo.loginlog.LoginLogRespVO;
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.fx.view.system.operatelog.OperateLogDetailView;
import com.lw.fx.view.system.operatelog.OperateLogDetailViewModel;
import com.lw.fx.vo.NotifyMessageVo;
import com.lw.ui.request.api.system.OperateLogFeign;
import com.lw.ui.utils.DictTypeEnum;
import de.saxsys.mvvmfx.*;
import io.datafx.core.concurrent.ProcessChain;
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.CheckBoxTableCell;
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 javax.swing.*;
import java.net.URL;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.ResourceBundle;
import static atlantafx.base.theme.Styles.*;
import static com.lw.ui.utils.DictTypeEnum.*;
public class MyNotifyMessageView implements FxmlView<MyNotifyMessageViewModel>, Initializable {
@InjectViewModel
private MyNotifyMessageViewModel viewModel;
@FXML
private VBox contentPane;
@FXML
private TableColumn<NotifyMessageVo, LocalDateTime> createTimeCol;
@FXML
private DatePicker endDatePicker;
@FXML
private TableColumn<NotifyMessageVo, Long> optCol;
@FXML
private TableColumn<NotifyMessageVo, Boolean> selCol;
@FXML
private TableColumn<NotifyMessageVo, Boolean> readStatusCol;
@FXML
private ComboBox<DictDataSimpleRespVO> readStatusComboBox;
@FXML
private TableColumn<NotifyMessageVo, LocalDateTime> readTimeCol;
@FXML
private Button resetBut;
@FXML
private Button handleUpdateListBut;
@FXML
private Button handleUpdateAllBut;
@FXML
private StackPane rootPane;
@FXML
private Button searchBut;
@FXML
private DatePicker startDatePicker;
@FXML
private TableView<NotifyMessageVo> tableView;
@FXML
private TableColumn<NotifyMessageVo, String> templateContentCol;
@FXML
private TableColumn<NotifyMessageVo, String> templateNicknameCol;
@FXML
private TableColumn<NotifyMessageVo, Integer> templateTypeCol;
@FXML
private CheckBox selAllCheckBox;
private PagingControl pagingControl;
private DialogPane dialogPane;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
readStatusComboBox.setItems(viewModel.getStautsItems());
readStatusComboBox.valueProperty().addListener((observableValue, dictDataSimpleRespVO, t1) -> {
Boolean statsu = null;
if (t1 != null) {
statsu = Convert.toBool(t1.getValue());
}
viewModel.statusProperty().set(statsu);
});
tableView.setItems(viewModel.getTableItems());
dialogPane = new DialogPane();
rootPane.getChildren().add(dialogPane);
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();
});
templateNicknameCol.setCellValueFactory(new PropertyValueFactory<>("templateNickname"));
templateNicknameCol.setStyle("-fx-alignment: CENTER");
templateTypeCol.setCellValueFactory(new PropertyValueFactory<>("templateType"));
templateTypeCol.setStyle("-fx-alignment: CENTER");
templateContentCol.setCellValueFactory(new PropertyValueFactory<>("templateContent"));
templateContentCol.setStyle("-fx-alignment: CENTER");
readStatusCol.setCellValueFactory(new PropertyValueFactory<>("readStatus"));
readStatusCol.setStyle("-fx-alignment: CENTER");
readTimeCol.setCellValueFactory(new PropertyValueFactory<>("readTime"));
readTimeCol.setStyle("-fx-alignment: CENTER");
createTimeCol.setCellValueFactory(new PropertyValueFactory<>("createTime"));
createTimeCol.setStyle("-fx-alignment: CENTER");
createTimeCol.setCellFactory(new Callback<TableColumn<NotifyMessageVo, LocalDateTime>, TableCell<NotifyMessageVo, LocalDateTime>>() {
@Override
public TableCell<NotifyMessageVo, LocalDateTime> call(TableColumn<NotifyMessageVo, LocalDateTime> param) {
return new TableCell<>() {
@Override
protected void updateItem(LocalDateTime item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
} else {
if (item != null) {
this.setText(DateUtil.format(item, "yyyy-MM-dd HH:mm:ss"));
}
}
}
};
}
});
readTimeCol.setCellFactory(new Callback<TableColumn<NotifyMessageVo, LocalDateTime>, TableCell<NotifyMessageVo, LocalDateTime>>() {
@Override
public TableCell<NotifyMessageVo, LocalDateTime> call(TableColumn<NotifyMessageVo, LocalDateTime> param) {
return new TableCell<>() {
@Override
protected void updateItem(LocalDateTime item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
} else {
if (item != null) {
this.setText(DateUtil.format(item, "yyyy-MM-dd HH:mm:ss"));
}
}
}
};
}
});
templateTypeCol.setCellFactory(new Callback<TableColumn<NotifyMessageVo, Integer>, TableCell<NotifyMessageVo, Integer>>() {
@Override
public TableCell<NotifyMessageVo, Integer> call(TableColumn<NotifyMessageVo, 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(SYSTEM_NOTIFY_TEMPLATE_TYPE).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);
}
}
};
}
});
readStatusCol.setCellFactory(new Callback<TableColumn<NotifyMessageVo, Boolean>, TableCell<NotifyMessageVo, Boolean>>() {
@Override
public TableCell<NotifyMessageVo, Boolean> call(TableColumn<NotifyMessageVo, Boolean> param) {
return new TableCell<>() {
@Override
protected void updateItem(Boolean item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
DictDataSimpleRespVO dict = AppStore.getDictDataValueMap(INFRA_BOOLEAN_STRING).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);
}
}
};
}
});
optCol.setCellValueFactory(new PropertyValueFactory<>("id"));
optCol.setCellFactory(new Callback<TableColumn<NotifyMessageVo, Long>, TableCell<NotifyMessageVo, Long>>() {
@Override
public TableCell<NotifyMessageVo, Long> call(TableColumn<NotifyMessageVo, Long> param) {
TableCell cell = new TableCell<NotifyMessageVo, Long>() {
@Override
protected void updateItem(Long item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
Button editBut = new Button("详情");
editBut.setOnAction(event -> showFormView(getTableRow().getItem()));
editBut.setGraphic(FontIcon.of(Feather.EYE));
editBut.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, delBut);
box.setAlignment(Pos.CENTER);
// box.setSpacing(7);
setGraphic(box);
}
}
};
return cell;
}
});
selCol.setCellValueFactory(c -> c.getValue().selectdProperty());
selCol.setCellFactory(CheckBoxTableCell.forTableColumn(selCol));
searchBut.setOnAction(actionEvent -> {
viewModel.loadTableData();
});
resetBut.setOnAction(actionEvent -> {
readStatusComboBox.setValue(null);
startDatePicker.setValue(null);
endDatePicker.setValue(null);
});
startDatePicker.valueProperty().bindBidirectional(viewModel.beginDateProperty());
endDatePicker.valueProperty().bindBidirectional(viewModel.endDateProperty());
selAllCheckBox.setOnAction(actionEvent -> viewModel.selAll(selAllCheckBox.isSelected()));
handleUpdateAllBut.setOnAction(actionEvent -> viewModel.updateAllNotifyMessageRead());
handleUpdateListBut.setOnAction(actionEvent -> viewModel.updateNotifyMessageRead());
}
/**
* 显示编辑对话框
*/
private void showFormView(NotifyMessageVo respVo) {
WFXGenericDialog dialog = new WFXGenericDialog();
HBox templateContentBox = createTextAreaField("内容", respVo.getTemplateContent());
VBox.setVgrow(templateContentBox, Priority.ALWAYS);
VBox vBox = new VBox(10, createTextField("发送人", respVo.getTemplateNickname())
, createTextField("发送时间", DateUtil.format(respVo.getCreateTime(),"yyyy-MM-dd HH:mm:ss"))
, createDictBut("消息类型", respVo.getTemplateType(), SYSTEM_NOTIFY_TEMPLATE_TYPE)
, createDictBut("是否已读", respVo.getReadStatus(), INFRA_BOOLEAN_STRING)
, createTextField("阅读时间", DateUtil.format(respVo.getReadTime(),"yyyy-MM-dd HH:mm:ss"))
, templateContentBox
);
dialog.addActions(
Map.entry(new Button("确定"), event -> {
dialog.close();
})
);
dialog.setHeaderIcon(FontIcon.of(Feather.INFO));
dialog.setHeaderText("详情");
dialog.setContent(vBox);
dialog.show(rootPane.getScene());
}
private HBox createTextField(String text, String value) {
Label label = new Label(text);
label.setAlignment(Pos.CENTER_RIGHT);
label.setPrefWidth(80);
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 createTextAreaField(String text, String value) {
Label label = new Label(text);
label.setAlignment(Pos.CENTER_RIGHT);
label.setPrefWidth(80);
TextArea textField = new TextArea(value);
textField.setEditable(false);
textField.setWrapText(true);
HBox.setHgrow(textField, Priority.ALWAYS);
HBox hBox = new HBox(7, label, textField);
hBox.setAlignment(Pos.TOP_LEFT);
return hBox;
}
private HBox createDictBut(String text, Object value, DictTypeEnum dictTypeEnum) {
Label label = new Label(text);
label.setAlignment(Pos.CENTER_RIGHT);
label.setPrefWidth(80);
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;
}
private void showDelDialog(NotifyMessageVo 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(OperateLogFeign.class).deleteOperateLog(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.getTemplateNickname() + "-" + respVO.getTemplateContent() + "的数据项?"));
dialog.show(rootPane.getScene());
}
}

View File

@ -0,0 +1,235 @@
package com.lw.fx.view.system.notice;
import cn.hutool.core.util.ObjectUtil;
import com.lw.dillon.admin.module.system.controller.admin.dict.vo.data.DictDataSimpleRespVO;
import com.lw.dillon.admin.module.system.controller.admin.notify.vo.message.NotifyMessageRespVO;
import com.lw.fx.request.Request;
import com.lw.fx.store.AppStore;
import com.lw.fx.util.MessageType;
import com.lw.fx.vo.NotifyMessageVo;
import com.lw.ui.request.api.system.NotifyMessageFeign;
import de.saxsys.mvvmfx.MvvmFX;
import de.saxsys.mvvmfx.SceneLifecycle;
import de.saxsys.mvvmfx.ViewModel;
import io.datafx.core.concurrent.ProcessChain;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import static com.lw.ui.utils.DictTypeEnum.INFRA_BOOLEAN_STRING;
public class MyNotifyMessageViewModel implements ViewModel, SceneLifecycle {
private SimpleIntegerProperty total = new SimpleIntegerProperty(0);
private IntegerProperty pageNum = new SimpleIntegerProperty(0);
private IntegerProperty pageSize = new SimpleIntegerProperty(10);
private ObservableList<NotifyMessageVo> tableItems = FXCollections.observableArrayList();
private ObservableList<DictDataSimpleRespVO> stautsItems = FXCollections.observableArrayList();
private ObjectProperty<LocalDate> beginDate = new SimpleObjectProperty<>();
private ObjectProperty<LocalDate> endDate = new SimpleObjectProperty<>();
private ObjectProperty<Boolean> status = new SimpleObjectProperty<>();
public MyNotifyMessageViewModel() {
initData();
loadTableData();
}
public void initData() {
ProcessChain.create()
.addSupplierInExecutor(() -> AppStore.getDictDataList(INFRA_BOOLEAN_STRING))
.addConsumerInPlatformThread(rel -> {
stautsItems.setAll(rel);
})
.run();
}
public void loadTableData() {
Map<String, Object> queryMap = new HashMap<>();
queryMap.put("pageNo", pageNum.get() + 1);
queryMap.put("pageSize", pageSize.get());
queryMap.put("readStatus", status.getValue());
if (ObjectUtil.isAllNotEmpty(getBeginDate(), getEndDate())) {
String sd = getBeginDate().atTime(0, 0, 0).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
String ed = getEndDate().atTime(23, 59, 59).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
queryMap.put("createTime", new String[]{sd, ed});
}
ProcessChain.create()
.addRunnableInPlatformThread(() -> tableItems.clear())
.addSupplierInExecutor(() -> Request.connector(NotifyMessageFeign.class).getMyMyNotifyMessagePage(queryMap))
.addConsumerInPlatformThread(listCommonResult -> {
if (listCommonResult.isSuccess()) {
listCommonResult.getData().getList().forEach(menu -> tableItems.add(convert(menu)));
totalProperty().set(listCommonResult.getData().getTotal().intValue());
}
})
.run();
}
public NotifyMessageVo convert(NotifyMessageRespVO messageRespVO) {
if (messageRespVO == null) {
return null;
}
NotifyMessageVo messageVo = new NotifyMessageVo();
messageVo.setId(messageRespVO.getId());
messageVo.setReadStatus(messageRespVO.getReadStatus());
messageVo.setCreateTime(messageRespVO.getCreateTime());
messageVo.setReadTime(messageRespVO.getReadTime());
messageVo.setTemplateCode(messageRespVO.getTemplateCode());
messageVo.setTemplateId(messageRespVO.getTemplateId());
messageVo.setUserId(messageRespVO.getUserId());
messageVo.setUserType(messageRespVO.getUserType());
messageVo.setTemplateContent(messageRespVO.getTemplateContent());
messageVo.setTemplateNickname(messageRespVO.getTemplateNickname());
messageVo.setTemplateType(messageRespVO.getTemplateType());
messageVo.setTemplateParams(messageRespVO.getTemplateParams());
return messageVo;
}
public void selAll(boolean sel) {
for (NotifyMessageVo notifyMessageRespVO : tableItems) {
notifyMessageRespVO.setSelectd(sel);
}
}
public void updateAllNotifyMessageRead() {
ProcessChain.create()
.addSupplierInExecutor(() -> Request.connector(NotifyMessageFeign.class).updateAllNotifyMessageRead())
.addConsumerInPlatformThread(rel -> {
if (rel.isSuccess()) {
loadTableData();
MvvmFX.getNotificationCenter().publish("message", "标记所有站内信为已读成功", MessageType.SUCCESS);
MvvmFX.getNotificationCenter().publish("notify","标记所有站内信为已读成功");
}
})
.run();
}
public void updateNotifyMessageRead() {
Set<Long> ids = new HashSet<>();
for (NotifyMessageVo notifyMessageRespVO : tableItems) {
if (notifyMessageRespVO.isSelectd()) {
ids.add(notifyMessageRespVO.getId());
}
}
if (ids.isEmpty()) {
MvvmFX.getNotificationCenter().publish("message", "请选择一条记录", MessageType.WARNING);
return;
}
ProcessChain.create()
.addSupplierInExecutor(() -> Request.connector(NotifyMessageFeign.class).updateNotifyMessageRead(ids.stream().toList()))
.addConsumerInPlatformThread(rel -> {
if (rel.isSuccess()) {
loadTableData();
MvvmFX.getNotificationCenter().publish("message", "标记站内信为已读成功", MessageType.SUCCESS);
MvvmFX.getNotificationCenter().publish("notify","标记站内信为已读成功");
}
})
.run();
}
public LocalDate getBeginDate() {
return beginDate.get();
}
public ObjectProperty<LocalDate> beginDateProperty() {
return beginDate;
}
public LocalDate getEndDate() {
return endDate.get();
}
public ObjectProperty<LocalDate> endDateProperty() {
return endDate;
}
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<NotifyMessageVo> getTableItems() {
return tableItems;
}
public ObservableList<DictDataSimpleRespVO> getStautsItems() {
return stautsItems;
}
public Boolean getStatus() {
return status.get();
}
public ObjectProperty<Boolean> statusProperty() {
return status;
}
@Override
public void onViewAdded() {
}
@Override
public void onViewRemoved() {
}
}

View File

@ -87,7 +87,7 @@ public class NoticeFormViewModel implements ViewModel {
wrapper.reload();
}
public CommonResult saveUser(boolean isAdd) {
public CommonResult save(boolean isAdd) {
if (isAdd) {
return Request.connector(NoticeFeign.class).createNotice(getUserSaveReqVO());

View File

@ -226,7 +226,7 @@ public class NoticeView implements FxmlView<NoticeViewModel>, Initializable {
} else {
Button editBut = new Button("修改");
editBut.setOnAction(event -> showPostFormView(getTableRow().getItem().getId()));
editBut.setOnAction(event -> showFormView(getTableRow().getItem().getId()));
editBut.setGraphic(FontIcon.of(Feather.EDIT));
editBut.getStyleClass().addAll(FLAT, ACCENT);
@ -261,25 +261,25 @@ public class NoticeView implements FxmlView<NoticeViewModel>, Initializable {
statusCombo.getSelectionModel().select(null);
});
addBut.setOnAction(actionEvent -> showPostFormView(null));
addBut.setOnAction(actionEvent -> showFormView(null));
}
/**
* 显示编辑对话框
*/
private void showPostFormView(Long roleId) {
private void showFormView(Long id) {
WFXGenericDialog dialog = new WFXGenericDialog();
boolean isAdd = (roleId == null);
boolean isAdd = (id == null);
ViewTuple<NoticeFormView, NoticeFormViewModel> load = FluentViewLoader.fxmlView(NoticeFormView.class).load();
load.getViewModel().query(roleId);
load.getViewModel().query(id);
dialog.addActions(
Map.entry(new Button("取消"), event -> dialog.close()),
Map.entry(new Button("确定"), event -> {
ProcessChain.create().addRunnableInPlatformThread(() -> load.getViewModel().commitHtmText())
.addSupplierInExecutor(() -> {
return load.getViewModel().saveUser(isAdd);
return load.getViewModel().save(isAdd);
})
.addConsumerInPlatformThread(r -> {
if (r.isSuccess()) {
@ -295,7 +295,7 @@ public class NoticeView implements FxmlView<NoticeViewModel>, Initializable {
);
dialog.setHeaderIcon(FontIcon.of(Feather.INFO));
dialog.setHeaderText(roleId != null ? "编辑角色" : "添加角色");
dialog.setHeaderText(id != null ? "编辑角色" : "添加角色");
dialog.setContent(load.getView());
dialog.show(rootPane.getScene());

View File

@ -0,0 +1,545 @@
package com.lw.fx.view.system.notice;
import cn.hutool.core.date.DateUtil;
import com.dlsc.gemsfx.DialogPane;
import com.lw.dillon.admin.module.system.controller.admin.dict.vo.data.DictDataSimpleRespVO;
import com.lw.dillon.admin.module.system.controller.admin.notify.vo.message.NotifyMessageRespVO;
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.system.OperateLogFeign;
import com.lw.ui.utils.DictTypeEnum;
import de.saxsys.mvvmfx.FxmlView;
import de.saxsys.mvvmfx.InjectViewModel;
import de.saxsys.mvvmfx.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.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.ResourceBundle;
import static atlantafx.base.theme.Styles.*;
import static com.lw.ui.utils.DictTypeEnum.*;
public class NotifyMessageView implements FxmlView<NotifyMessageViewModel>, Initializable {
@InjectViewModel
private NotifyMessageViewModel viewModel;
@FXML
private VBox contentPane;
@FXML
private TableColumn<NotifyMessageRespVO, LocalDateTime> createTimeCol;
@FXML
private Button emptyBut;
@FXML
private DatePicker endDatePicker;
@FXML
private TableColumn<NotifyMessageRespVO, ?> idCol;
@FXML
private TableColumn<NotifyMessageRespVO, Long> optCol;
@FXML
private TableColumn<NotifyMessageRespVO, Boolean> readStatusCol;
@FXML
private TableColumn<NotifyMessageRespVO, LocalDateTime> readTimeCol;
@FXML
private Button resetBut;
@FXML
private StackPane rootPane;
@FXML
private Button searchBut;
@FXML
private DatePicker startDatePicker;
@FXML
private TableView<NotifyMessageRespVO> tableView;
@FXML
private TableColumn<NotifyMessageRespVO, ?> templateCodeCol;
@FXML
private TextField templateCodeField;
@FXML
private TableColumn<NotifyMessageRespVO, ?> templateContentCol;
@FXML
private TableColumn<NotifyMessageRespVO, ?> templateNicknameCol;
@FXML
private TableColumn<NotifyMessageRespVO, ?> templateParamsCol;
@FXML
private TableColumn<NotifyMessageRespVO, Integer> templateTypeCol;
@FXML
private ComboBox<DictDataSimpleRespVO> templateTypeComBox;
@FXML
private TableColumn<NotifyMessageRespVO, ?> userIdCol;
@FXML
private TextField userIdField;
@FXML
private TableColumn<NotifyMessageRespVO, Byte> userTypeCol;
@FXML
private ComboBox<DictDataSimpleRespVO> userTypeComBox;
private PagingControl pagingControl;
private DialogPane dialogPane;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
userTypeComBox.setItems(FXCollections.observableArrayList(AppStore.getDictDataList(USER_TYPE)));
userTypeComBox.valueProperty().addListener((observableValue, userSimpleRespVO, t1) -> {
if (t1 == null) {
viewModel.userTypeProperty().set(null);
}else {
viewModel.userTypeProperty().set(t1.getValue());
}
});
templateTypeComBox.setItems(FXCollections.observableArrayList(AppStore.getDictDataList(SYSTEM_NOTIFY_TEMPLATE_TYPE)));
templateTypeComBox.valueProperty().addListener((observableValue, userSimpleRespVO, t1) -> {
if (t1 == null) {
viewModel.templateTypeProperty().set(null);
}else {
viewModel.templateTypeProperty().set(t1.getValue());
}
});
dialogPane = new DialogPane();
rootPane.getChildren().add(dialogPane);
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();
});
idCol.setCellValueFactory(new PropertyValueFactory<>("id"));
idCol.setStyle("-fx-alignment: CENTER");
userTypeCol.setCellValueFactory(new PropertyValueFactory<>("userType"));
userTypeCol.setStyle("-fx-alignment: CENTER");
userTypeCol.setCellFactory(new Callback<TableColumn<NotifyMessageRespVO, Byte>, TableCell<NotifyMessageRespVO, Byte>>() {
@Override
public TableCell<NotifyMessageRespVO, Byte> call(TableColumn<NotifyMessageRespVO, Byte> param) {
return new TableCell<>() {
@Override
protected void updateItem(Byte item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
DictDataSimpleRespVO dict = AppStore.getDictDataValueMap(USER_TYPE).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);
}
}
};
}
});
userIdCol.setCellValueFactory(new PropertyValueFactory<>("userId"));
userIdCol.setStyle("-fx-alignment: CENTER");
templateCodeCol.setCellValueFactory(new PropertyValueFactory<>("templateCode"));
templateCodeCol.setStyle("-fx-alignment: CENTER");
templateNicknameCol.setCellValueFactory(new PropertyValueFactory<>("templateNickname"));
templateNicknameCol.setStyle("-fx-alignment: CENTER");
templateContentCol.setCellValueFactory(new PropertyValueFactory<>("templateContent"));
templateContentCol.setStyle("-fx-alignment: CENTER");
templateParamsCol.setCellValueFactory(new PropertyValueFactory<>("templateParams"));
templateParamsCol.setStyle("-fx-alignment: CENTER");
templateTypeCol.setCellValueFactory(new PropertyValueFactory<>("templateType"));
templateTypeCol.setStyle("-fx-alignment: CENTER");
templateTypeCol.setCellFactory(new Callback<TableColumn<NotifyMessageRespVO, Integer>, TableCell<NotifyMessageRespVO, Integer>>() {
@Override
public TableCell<NotifyMessageRespVO, Integer> call(TableColumn<NotifyMessageRespVO, 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(SYSTEM_NOTIFY_TEMPLATE_TYPE).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);
}
}
};
}
});
readStatusCol.setCellValueFactory(new PropertyValueFactory<>("readStatus"));
readStatusCol.setStyle("-fx-alignment: CENTER");
readStatusCol.setCellFactory(new Callback<TableColumn<NotifyMessageRespVO, Boolean>, TableCell<NotifyMessageRespVO, Boolean>>() {
@Override
public TableCell<NotifyMessageRespVO, Boolean> call(TableColumn<NotifyMessageRespVO, Boolean> param) {
return new TableCell<>() {
@Override
protected void updateItem(Boolean item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
DictDataSimpleRespVO dict = AppStore.getDictDataValueMap(INFRA_BOOLEAN_STRING).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);
}
}
};
}
});
readTimeCol.setCellValueFactory(new PropertyValueFactory<>("readTime"));
readTimeCol.setStyle("-fx-alignment: CENTER");
createTimeCol.setCellValueFactory(new PropertyValueFactory<>("createTime"));
createTimeCol.setStyle("-fx-alignment: CENTER");
createTimeCol.setCellFactory(new Callback<TableColumn<NotifyMessageRespVO, LocalDateTime>, TableCell<NotifyMessageRespVO, LocalDateTime>>() {
@Override
public TableCell<NotifyMessageRespVO, LocalDateTime> call(TableColumn<NotifyMessageRespVO, LocalDateTime> param) {
return new TableCell<>() {
@Override
protected void updateItem(LocalDateTime item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
} else {
if (item != null) {
this.setText(DateUtil.format(item, "yyyy-MM-dd HH:mm:ss"));
}
}
}
};
}
});
readTimeCol.setCellFactory(new Callback<TableColumn<NotifyMessageRespVO, LocalDateTime>, TableCell<NotifyMessageRespVO, LocalDateTime>>() {
@Override
public TableCell<NotifyMessageRespVO, LocalDateTime> call(TableColumn<NotifyMessageRespVO, LocalDateTime> param) {
return new TableCell<>() {
@Override
protected void updateItem(LocalDateTime item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
} else {
if (item != null) {
this.setText(DateUtil.format(item, "yyyy-MM-dd HH:mm:ss"));
}
}
}
};
}
});
optCol.setCellValueFactory(new PropertyValueFactory<>("id"));
optCol.setCellFactory(new Callback<TableColumn<NotifyMessageRespVO, Long>, TableCell<NotifyMessageRespVO, Long>>() {
@Override
public TableCell<NotifyMessageRespVO, Long> call(TableColumn<NotifyMessageRespVO, Long> param) {
TableCell cell = new TableCell<NotifyMessageRespVO, Long>() {
@Override
protected void updateItem(Long item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
Button editBut = new Button("详情");
editBut.setOnAction(event -> showFormView(getTableRow().getItem()));
editBut.setGraphic(FontIcon.of(Feather.EYE));
editBut.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, delBut);
box.setAlignment(Pos.CENTER);
// box.setSpacing(7);
setGraphic(box);
}
}
};
return cell;
}
});
tableView.itemsProperty().bind(viewModel.tableItemsProperty());
userIdField.textProperty().bindBidirectional(viewModel.userIdProperty());
templateCodeField.textProperty().bindBidirectional(viewModel.templateCodeProperty());
searchBut.setOnAction(actionEvent -> viewModel.loadTableData());
resetBut.setOnAction(actionEvent -> {
userIdField.setText(null);
templateCodeField.setText(null);
userTypeComBox.setValue(null);
templateTypeComBox.setValue(null);
startDatePicker.setValue(null);
endDatePicker.setValue(null);
});
startDatePicker.valueProperty().bindBidirectional(viewModel.beginDateProperty());
endDatePicker.valueProperty().bindBidirectional(viewModel.endDateProperty());
}
private HBox createTextField(String text, String value) {
Label label = new Label(text);
label.setAlignment(Pos.CENTER_RIGHT);
label.setPrefWidth(80);
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 createTextAreaField(String text, String value) {
Label label = new Label(text);
label.setAlignment(Pos.CENTER_RIGHT);
label.setPrefWidth(80);
TextArea textField = new TextArea(value);
textField.setEditable(false);
textField.setWrapText(true);
HBox.setHgrow(textField, Priority.ALWAYS);
HBox hBox = new HBox(7, label, textField);
hBox.setAlignment(Pos.TOP_LEFT);
return hBox;
}
private HBox createDictBut(String text, Object value, DictTypeEnum dictTypeEnum) {
Label label = new Label(text);
label.setAlignment(Pos.CENTER_RIGHT);
label.setPrefWidth(80);
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;
}
/**
* 显示编辑对话框
*/
private void showFormView(NotifyMessageRespVO respVo) {
WFXGenericDialog dialog = new WFXGenericDialog();
dialog.addActions(
Map.entry(new Button("确定"), event -> {
dialog.close();
})
);
HBox templateContentBox = createTextAreaField("模版内容", respVo.getTemplateContent());
VBox.setVgrow(templateContentBox, Priority.ALWAYS);
VBox vBox = new VBox(10, createTextField("编号", respVo.getId()+"")
, createDictBut("用户类型", respVo.getUserType(), USER_TYPE)
, createTextField("用户编号", respVo.getUserId()+"")
, createTextField("模版编号", respVo.getTemplateId()+"")
, createTextField("模板编码", respVo.getTemplateCode()+"")
, createTextField("发送人名称", respVo.getTemplateNickname()+"")
, createTextField("模版参数", respVo.getTemplateParams()+"")
, createDictBut("模版类型", respVo.getTemplateType(), SYSTEM_NOTIFY_TEMPLATE_TYPE)
, createDictBut("是否已读", respVo.getReadStatus(), INFRA_BOOLEAN_STRING)
, createTextField("阅读时间",DateUtil.format(respVo.getReadTime(),"yyyy-MM-dd HH:mm:ss"))
, createTextField("创建时间",DateUtil.format(respVo.getCreateTime(),"yyyy-MM-dd HH:mm:ss"))
, templateContentBox
);
dialog.setHeaderIcon(FontIcon.of(Feather.INFO));
dialog.setHeaderText("详情");
dialog.setContent(vBox);
dialog.show(rootPane.getScene());
}
private void showDelDialog(NotifyMessageRespVO 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(OperateLogFeign.class).deleteOperateLog(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.getId() + "-" + respVO.getTemplateContent() + "的数据项?"));
dialog.show(rootPane.getScene());
}
}

View File

@ -0,0 +1,180 @@
package com.lw.fx.view.system.notice;
import cn.hutool.core.util.ObjectUtil;
import com.lw.dillon.admin.module.system.controller.admin.notify.vo.message.NotifyMessageRespVO;
import com.lw.fx.request.Request;
import com.lw.ui.request.api.system.NotifyMessageFeign;
import de.saxsys.mvvmfx.SceneLifecycle;
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 NotifyMessageViewModel implements ViewModel, SceneLifecycle {
private SimpleIntegerProperty total = new SimpleIntegerProperty(0);
private IntegerProperty pageNum = new SimpleIntegerProperty(0);
private IntegerProperty pageSize = new SimpleIntegerProperty(10);
private ObjectProperty<ObservableList<NotifyMessageRespVO>> tableItems = new SimpleObjectProperty<>();
private ObjectProperty<LocalDate> beginDate = new SimpleObjectProperty<>();
private ObjectProperty<LocalDate> endDate = new SimpleObjectProperty<>();
private StringProperty userId = new SimpleStringProperty();
private StringProperty userType = new SimpleStringProperty();
private StringProperty templateCode = new SimpleStringProperty();
private StringProperty templateType = new SimpleStringProperty();
public NotifyMessageViewModel() {
initData();
loadTableData();
}
public void initData() {
}
public void loadTableData() {
Map<String, Object> queryMap = new HashMap<>();
queryMap.put("pageNo", pageNum.get() + 1);
queryMap.put("pageSize", pageSize.get());
queryMap.put("userId", userId.get());
queryMap.put("userType", userType.get());
queryMap.put("templateCode", templateCode.get());
queryMap.put("templateType", templateType.get());
if (ObjectUtil.isAllNotEmpty(getBeginDate(), getEndDate())) {
String sd = getBeginDate().atTime(0, 0, 0).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
String ed = getEndDate().atTime(23, 59, 59).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
queryMap.put("createTime", new String[]{sd, ed});
}
ProcessChain.create()
.addSupplierInExecutor(() -> Request.connector(NotifyMessageFeign.class).getNotifyMessagePage(queryMap))
.addConsumerInPlatformThread(listCommonResult -> {
if (listCommonResult.isSuccess()) {
ObservableList<NotifyMessageRespVO> userRespVOS = FXCollections.observableArrayList();
userRespVOS.addAll(listCommonResult.getData().getList());
tableItems.set(userRespVOS);
totalProperty().set(listCommonResult.getData().getTotal().intValue());
}
})
.run();
}
public ObjectProperty<ObservableList<NotifyMessageRespVO>> tableItemsProperty() {
return tableItems;
}
public LocalDate getBeginDate() {
return beginDate.get();
}
public ObjectProperty<LocalDate> beginDateProperty() {
return beginDate;
}
public LocalDate getEndDate() {
return endDate.get();
}
public ObjectProperty<LocalDate> endDateProperty() {
return endDate;
}
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<NotifyMessageRespVO> getTableItems() {
return tableItems.get();
}
public String getUserId() {
return userId.get();
}
public StringProperty userIdProperty() {
return userId;
}
public String getUserType() {
return userType.get();
}
public StringProperty userTypeProperty() {
return userType;
}
public String getTemplateCode() {
return templateCode.get();
}
public StringProperty templateCodeProperty() {
return templateCode;
}
public String getTemplateType() {
return templateType.get();
}
public StringProperty templateTypeProperty() {
return templateType;
}
@Override
public void onViewAdded() {
}
@Override
public void onViewRemoved() {
}
}

View File

@ -0,0 +1,66 @@
package com.lw.fx.view.system.notice;
import com.lw.dillon.admin.module.system.controller.admin.dict.vo.data.DictDataSimpleRespVO;
import com.lw.fx.store.AppStore;
import de.saxsys.mvvmfx.FxmlView;
import de.saxsys.mvvmfx.InjectViewModel;
import javafx.collections.FXCollections;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import java.net.URL;
import java.util.ResourceBundle;
import static com.lw.ui.utils.DictTypeEnum.COMMON_STATUS;
import static com.lw.ui.utils.DictTypeEnum.SYSTEM_NOTIFY_TEMPLATE_TYPE;
public class NotifyTemplateFormView implements FxmlView<NotifyTemplateFormViewModel>, Initializable {
@InjectViewModel
private NotifyTemplateFormViewModel viewModel;
@FXML
private TextField codeTield;
@FXML
private TextArea contentArea;
@FXML
private TextField nameField;
@FXML
private TextField nicknameField;
@FXML
private TextField remarkField;
@FXML
private ComboBox<DictDataSimpleRespVO> statusComboBox;
@FXML
private ComboBox<DictDataSimpleRespVO> typeComboBox;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
typeComboBox.setItems(FXCollections.observableArrayList(AppStore.getDictDataList(SYSTEM_NOTIFY_TEMPLATE_TYPE)));
typeComboBox.valueProperty().bindBidirectional(viewModel.selTypeProperty());
statusComboBox.setItems(FXCollections.observableArrayList(AppStore.getDictDataList(COMMON_STATUS)));
statusComboBox.valueProperty().bindBidirectional(viewModel.selStatusProperty());
codeTield.textProperty().bindBidirectional(viewModel.codeProperty());
nameField.textProperty().bindBidirectional(viewModel.nameProperty());
nicknameField.textProperty().bindBidirectional(viewModel.nicknameProperty());
contentArea.textProperty().bindBidirectional(viewModel.contentProperty());
remarkField.textProperty().bindBidirectional(viewModel.remarkProperty());
}
}

View File

@ -0,0 +1,145 @@
package com.lw.fx.view.system.notice;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import com.lw.dillon.admin.framework.common.pojo.CommonResult;
import com.lw.dillon.admin.module.system.controller.admin.dict.vo.data.DictDataSimpleRespVO;
import com.lw.dillon.admin.module.system.controller.admin.notify.vo.template.NotifyTemplateSaveReqVO;
import com.lw.fx.request.Request;
import com.lw.fx.store.AppStore;
import com.lw.ui.request.api.system.NotifyTemplateFeign;
import de.saxsys.mvvmfx.ViewModel;
import de.saxsys.mvvmfx.utils.mapping.ModelWrapper;
import io.datafx.core.concurrent.ProcessChain;
import javafx.beans.property.*;
import static com.lw.ui.utils.DictTypeEnum.COMMON_STATUS;
import static com.lw.ui.utils.DictTypeEnum.SYSTEM_NOTIFY_TEMPLATE_TYPE;
public class NotifyTemplateFormViewModel implements ViewModel {
private ModelWrapper<NotifyTemplateSaveReqVO> wrapper = new ModelWrapper<>();
private ObjectProperty<DictDataSimpleRespVO> selType = new SimpleObjectProperty<>();
private ObjectProperty<DictDataSimpleRespVO> selStatus = new SimpleObjectProperty<>();
public NotifyTemplateFormViewModel() {
initData();
}
public NotifyTemplateSaveReqVO getUserSaveReqVO() {
if (selType != null) {
typeProperty().set(Convert.toInt(selType.get().getValue()));
}
if (selStatus != null) {
statusProperty().set(Convert.toInt(selStatus.get().getValue()));
}
wrapper.commit();
return wrapper.get();
}
public void initData() {
}
public void query(Long id) {
ProcessChain.create()
.addSupplierInExecutor(() -> {
if (id == null) {
return new NotifyTemplateSaveReqVO();
}
return Request.connector(NotifyTemplateFeign.class).getNotifyTemplate(id).getData();
})
.addConsumerInPlatformThread(r -> {
NotifyTemplateSaveReqVO reqVO = new NotifyTemplateSaveReqVO();
BeanUtil.copyProperties(r, reqVO);
setNotice(reqVO);
DictDataSimpleRespVO typeDict = AppStore.getDictDataValueMap(SYSTEM_NOTIFY_TEMPLATE_TYPE).get(reqVO.getType() + "");
selType.set(typeDict);
DictDataSimpleRespVO status = AppStore.getDictDataValueMap(COMMON_STATUS).get(reqVO.getStatus() + "");
selStatus.set(status);
})
.onException(e -> e.printStackTrace())
.run();
}
/**
* 系统设置菜单
*/
public void setNotice(NotifyTemplateSaveReqVO roleRespVO) {
wrapper.set(roleRespVO);
wrapper.reload();
}
public CommonResult save(boolean isAdd) {
if (isAdd) {
return Request.connector(NotifyTemplateFeign.class).createNotifyTemplate(getUserSaveReqVO());
} else {
return Request.connector(NotifyTemplateFeign.class).updateNotifyTemplate(getUserSaveReqVO());
}
}
public LongProperty idProperty() {
return wrapper.field("id", NotifyTemplateSaveReqVO::getId, NotifyTemplateSaveReqVO::setId);
}
public StringProperty nameProperty() {
return wrapper.field("name", NotifyTemplateSaveReqVO::getName, NotifyTemplateSaveReqVO::setName, "");
}
public StringProperty codeProperty() {
return wrapper.field("code", NotifyTemplateSaveReqVO::getCode, NotifyTemplateSaveReqVO::setCode, "");
}
public IntegerProperty typeProperty() {
return wrapper.field("type", NotifyTemplateSaveReqVO::getType, NotifyTemplateSaveReqVO::setType);
}
public StringProperty nicknameProperty() {
return wrapper.field("nickname", NotifyTemplateSaveReqVO::getNickname, NotifyTemplateSaveReqVO::setNickname, "");
}
public StringProperty contentProperty() {
return wrapper.field("content", NotifyTemplateSaveReqVO::getContent, NotifyTemplateSaveReqVO::setContent);
}
public StringProperty remarkProperty() {
return wrapper.field("remark", NotifyTemplateSaveReqVO::getRemark, NotifyTemplateSaveReqVO::setRemark);
}
public IntegerProperty statusProperty() {
return wrapper.field("status", NotifyTemplateSaveReqVO::getStatus, NotifyTemplateSaveReqVO::setStatus);
}
public DictDataSimpleRespVO getSelType() {
return selType.get();
}
public ObjectProperty<DictDataSimpleRespVO> selTypeProperty() {
return selType;
}
public void setSelType(DictDataSimpleRespVO selType) {
this.selType.set(selType);
}
public DictDataSimpleRespVO getSelStatus() {
return selStatus.get();
}
public ObjectProperty<DictDataSimpleRespVO> selStatusProperty() {
return selStatus;
}
}

View File

@ -0,0 +1,72 @@
package com.lw.fx.view.system.notice;
import atlantafx.base.controls.CustomTextField;
import com.lw.dillon.admin.module.system.controller.admin.dict.vo.data.DictDataSimpleRespVO;
import com.lw.fx.store.AppStore;
import de.saxsys.mvvmfx.FxmlView;
import de.saxsys.mvvmfx.InjectViewModel;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Pos;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import org.kordamp.ikonli.feather.Feather;
import org.kordamp.ikonli.javafx.FontIcon;
import java.net.URL;
import java.util.ResourceBundle;
import static com.lw.ui.utils.DictTypeEnum.*;
public class NotifyTemplateSendFormView implements FxmlView<NotifyTemplateSendFormViewModel>, Initializable {
@InjectViewModel
private NotifyTemplateSendFormViewModel viewModel;
@FXML
private TextArea contentArea;
@FXML
private ComboBox userComboBox;
@FXML
private ComboBox<DictDataSimpleRespVO> userTypeComboBox;
@FXML
private VBox paramsBox;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
userComboBox.setItems(viewModel.getUserItems());
userComboBox.valueProperty().bindBidirectional(viewModel.selUserProperty());
userTypeComboBox.setItems(FXCollections.observableArrayList(AppStore.getDictDataList(USER_TYPE)));
userTypeComboBox.valueProperty().bindBidirectional(viewModel.userTypeProperty());
contentArea.textProperty().bindBidirectional(viewModel.contentProperty());
viewModel.subscribe("params",(key, payload) -> {
for (String params : viewModel.paramsProperty()) {
paramsBox.getChildren().add(createTextField(params));
}
});
}
private HBox createTextField(String param) {
Label label = new Label("*参数{"+param+"}");
label.setAlignment(Pos.CENTER_RIGHT);
label.setPrefWidth(120);
TextField textField = new TextField();
textField.textProperty().addListener((observableValue, s, t1) -> viewModel.putParams(param,t1));
HBox.setHgrow(textField, Priority.ALWAYS);
HBox hBox = new HBox(7, label, textField);
hBox.setAlignment(Pos.CENTER_LEFT);
return hBox;
}
}

View File

@ -0,0 +1,131 @@
package com.lw.fx.view.system.notice;
import cn.hutool.core.convert.Convert;
import com.lw.dillon.admin.framework.common.pojo.CommonResult;
import com.lw.dillon.admin.module.system.controller.admin.dict.vo.data.DictDataSimpleRespVO;
import com.lw.dillon.admin.module.system.controller.admin.notify.vo.template.NotifyTemplateRespVO;
import com.lw.dillon.admin.module.system.controller.admin.notify.vo.template.NotifyTemplateSendReqVO;
import com.lw.dillon.admin.module.system.controller.admin.user.vo.user.UserSimpleRespVO;
import com.lw.fx.request.Request;
import com.lw.ui.request.api.system.NotifyTemplateFeign;
import com.lw.ui.request.api.system.UserFeign;
import de.saxsys.mvvmfx.ViewModel;
import de.saxsys.mvvmfx.utils.mapping.ModelWrapper;
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 NotifyTemplateSendFormViewModel implements ViewModel {
private ModelWrapper<NotifyTemplateRespVO> wrapper = new ModelWrapper<>();
private ObjectProperty<DictDataSimpleRespVO> userType = new SimpleObjectProperty<>();
private ObjectProperty<UserSimpleRespVO> selUser = new SimpleObjectProperty<>();
private Map<String, Object> templateParams = new HashMap<>();
private ObservableList<UserSimpleRespVO> userItems= FXCollections.observableArrayList();
public NotifyTemplateSendFormViewModel() {
initData();
}
public NotifyTemplateRespVO getUserSaveReqVO() {
wrapper.commit();
return wrapper.get();
}
public void initData() {
ProcessChain.create()
.addSupplierInExecutor(() -> {
return Request.connector(UserFeign.class).getSimpleUserList().getData();
})
.addConsumerInPlatformThread(r -> {
userItems.setAll(r);
})
.onException(e -> e.printStackTrace())
.run();
}
public void query(Long id) {
ProcessChain.create()
.addSupplierInExecutor(() -> {
return Request.connector(NotifyTemplateFeign.class).getNotifyTemplate(id).getData();
})
.addConsumerInPlatformThread(r -> {
setNotice(r);
})
.onException(e -> e.printStackTrace())
.run();
}
public CommonResult<Long> sendNotify() {
NotifyTemplateSendReqVO reqVO = new NotifyTemplateSendReqVO();
reqVO.setUserId(Convert.toLong(selUser.get().getId(), null));
reqVO.setUserType(Convert.toInt(userType.get().getValue(), null));
reqVO.setTemplateCode(codeProperty().get());
reqVO.setTemplateParams(templateParams.isEmpty() ? null : templateParams);
return Request.connector(NotifyTemplateFeign.class).sendNotify(reqVO);
}
/**
* 系统设置菜单
*/
public void setNotice(NotifyTemplateRespVO roleRespVO) {
wrapper.set(roleRespVO);
wrapper.reload();
publish("params");
}
public StringProperty contentProperty() {
return wrapper.field("content", NotifyTemplateRespVO::getContent, NotifyTemplateRespVO::setContent);
}
public ObservableList<String> paramsProperty() {
return wrapper.field("params", NotifyTemplateRespVO::getParams, NotifyTemplateRespVO::setParams);
}
public StringProperty codeProperty() {
return wrapper.field("code", NotifyTemplateRespVO::getCode, NotifyTemplateRespVO::setCode);
}
public DictDataSimpleRespVO getUserType() {
return userType.get();
}
public ObjectProperty<DictDataSimpleRespVO> userTypeProperty() {
return userType;
}
public void putParams(String params, String value) {
templateParams.put(params, value);
}
public ObservableList<UserSimpleRespVO> getUserItems() {
return userItems;
}
public UserSimpleRespVO getSelUser() {
return selUser.get();
}
public ObjectProperty<UserSimpleRespVO> selUserProperty() {
return selUser;
}
}

View File

@ -0,0 +1,413 @@
package com.lw.fx.view.system.notice;
import cn.hutool.core.date.DateUtil;
import com.dlsc.gemsfx.DialogPane;
import com.lw.dillon.admin.module.system.controller.admin.dict.vo.data.DictDataSimpleRespVO;
import com.lw.dillon.admin.module.system.controller.admin.notify.vo.template.NotifyTemplateRespVO;
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.system.NotifyTemplateFeign;
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.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.COMMON_STATUS;
import static com.lw.ui.utils.DictTypeEnum.SYSTEM_NOTIFY_TEMPLATE_TYPE;
public class NotifyTemplateView implements FxmlView<NotifyTemplateViewModel>, Initializable {
@InjectViewModel
private NotifyTemplateViewModel viewModel;
@FXML
private Button addBut;
@FXML
private TextField codeField;
@FXML
private TableColumn<NotifyTemplateRespVO, ?> contentCol;
@FXML
private VBox contentPane;
@FXML
private TableColumn<NotifyTemplateRespVO, LocalDateTime> createTimeCol;
@FXML
private TableColumn<NotifyTemplateRespVO, ?> idCol;
@FXML
private TableColumn<NotifyTemplateRespVO, ?> nameCol;
@FXML
private TextField nameField;
@FXML
private TableColumn<NotifyTemplateRespVO, ?> nicknameCol;
@FXML
private TableColumn<NotifyTemplateRespVO, Long> optCol;
@FXML
private TableColumn<NotifyTemplateRespVO, ?> remarkCol;
@FXML
private Button resetBut;
@FXML
private StackPane rootPane;
@FXML
private Button searchBut;
@FXML
private TableColumn<NotifyTemplateRespVO, Integer> statusCol;
@FXML
private ComboBox<DictDataSimpleRespVO> statusCombo;
@FXML
private TableView<NotifyTemplateRespVO> tableView;
@FXML
private TableColumn<NotifyTemplateRespVO, Integer> typeCol;
private PagingControl pagingControl;
private DialogPane dialogPane;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
statusCombo.setItems(FXCollections.observableArrayList(AppStore.getDictDataList(COMMON_STATUS)));
dialogPane = new DialogPane();
rootPane.getChildren().add(dialogPane);
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();
});
idCol.setCellValueFactory(new PropertyValueFactory<>("id"));
idCol.setStyle("-fx-alignment: CENTER");
nameCol.setCellValueFactory(new PropertyValueFactory<>("name"));
nameCol.setStyle("-fx-alignment: CENTER");
nicknameCol.setCellValueFactory(new PropertyValueFactory<>("nickname"));
nicknameCol.setStyle("-fx-alignment: CENTER");
contentCol.setCellValueFactory(new PropertyValueFactory<>("content"));
contentCol.setStyle("-fx-alignment: CENTER");
remarkCol.setCellValueFactory(new PropertyValueFactory<>("remark"));
remarkCol.setStyle("-fx-alignment: CENTER");
typeCol.setCellValueFactory(new PropertyValueFactory<>("type"));
typeCol.setStyle("-fx-alignment: CENTER");
typeCol.setCellFactory(new Callback<TableColumn<NotifyTemplateRespVO, Integer>, TableCell<NotifyTemplateRespVO, Integer>>() {
@Override
public TableCell<NotifyTemplateRespVO, Integer> call(TableColumn<NotifyTemplateRespVO, Integer> param) {
return new TableCell<>() {
@Override
protected void updateItem(Integer item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setText(null);
setGraphic(null);
} else {
DictDataSimpleRespVO dict = AppStore.getDictDataValueMap(SYSTEM_NOTIFY_TEMPLATE_TYPE).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);
}
}
};
}
});
statusCol.setCellValueFactory(new PropertyValueFactory<>("status"));
statusCol.setStyle("-fx-alignment: CENTER");
statusCol.setCellFactory(new Callback<TableColumn<NotifyTemplateRespVO, Integer>, TableCell<NotifyTemplateRespVO, Integer>>() {
@Override
public TableCell<NotifyTemplateRespVO, Integer> call(TableColumn<NotifyTemplateRespVO, Integer> param) {
return new TableCell<>() {
@Override
protected void updateItem(Integer item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setText(null);
setGraphic(null);
} else {
DictDataSimpleRespVO dict = AppStore.getDictDataValueMap(COMMON_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);
}
}
};
}
});
createTimeCol.setCellValueFactory(new PropertyValueFactory<>("createTime"));
createTimeCol.setStyle("-fx-alignment: CENTER");
createTimeCol.setCellFactory(new Callback<TableColumn<NotifyTemplateRespVO, LocalDateTime>, TableCell<NotifyTemplateRespVO, LocalDateTime>>() {
@Override
public TableCell<NotifyTemplateRespVO, LocalDateTime> call(TableColumn<NotifyTemplateRespVO, LocalDateTime> param) {
return new TableCell<>() {
@Override
protected void updateItem(LocalDateTime item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
} else {
if (item != null) {
this.setText(DateUtil.format(item, "yyyy-MM-dd HH:mm:ss"));
}
}
}
};
}
});
optCol.setCellValueFactory(new PropertyValueFactory<>("id"));
optCol.setCellFactory(new Callback<TableColumn<NotifyTemplateRespVO, Long>, TableCell<NotifyTemplateRespVO, Long>>() {
@Override
public TableCell<NotifyTemplateRespVO, Long> call(TableColumn<NotifyTemplateRespVO, Long> param) {
TableCell cell = new TableCell<NotifyTemplateRespVO, Long>() {
@Override
protected void updateItem(Long item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
Button editBut = new Button("修改");
editBut.setOnAction(event -> showFormView(getTableRow().getItem().getId()));
editBut.setGraphic(FontIcon.of(Feather.EDIT));
editBut.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);
Button pushBut = new Button("推送");
pushBut.setOnAction(actionEvent -> push(getTableRow().getItem().getId()));
pushBut.setGraphic(FontIcon.of(Feather.MESSAGE_SQUARE));
pushBut.getStyleClass().addAll(FLAT, ACCENT);
HBox box = new HBox(editBut, delBut, pushBut);
box.setAlignment(Pos.CENTER);
// box.setSpacing(7);
setGraphic(box);
}
}
};
return cell;
}
});
tableView.itemsProperty().bind(viewModel.tableItemsProperty());
codeField.textProperty().bindBidirectional(viewModel.codeProperty());
nameField.textProperty().bindBidirectional(viewModel.nameProperty());
statusCombo.getSelectionModel().selectedIndexProperty().addListener((observableValue, number, t1) -> viewModel.statusProperty().set(t1.intValue()));
searchBut.setOnAction(actionEvent -> viewModel.loadTableData());
resetBut.setOnAction(actionEvent -> {
codeField.setText(null);
nameField.setText(null);
statusCombo.getSelectionModel().select(null);
});
addBut.setOnAction(actionEvent -> showFormView(null));
}
/**
* 显示编辑对话框
*/
private void showFormView(Long id) {
WFXGenericDialog dialog = new WFXGenericDialog();
boolean isAdd = (id == null);
ViewTuple<NotifyTemplateFormView, NotifyTemplateFormViewModel> load = FluentViewLoader.fxmlView(NotifyTemplateFormView.class).load();
load.getViewModel().query(id);
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 ? "编辑" : "添加");
dialog.setContent(load.getView());
dialog.show(rootPane.getScene());
}
private void showDelDialog(NotifyTemplateRespVO 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(NotifyTemplateFeign.class).deleteNotifyTemplate(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 push(Long id) {
WFXGenericDialog dialog = new WFXGenericDialog();
ViewTuple<NotifyTemplateSendFormView, NotifyTemplateSendFormViewModel> load = FluentViewLoader.fxmlView(NotifyTemplateSendFormView.class).load();
load.getViewModel().query(id);
dialog.addActions(
Map.entry(new Button("取消"), event -> dialog.close()),
Map.entry(new Button("发送"), event -> {
ProcessChain.create()
.addSupplierInExecutor(() -> {
return load.getViewModel().sendNotify();
})
.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("消息发送");
dialog.setContent(load.getView());
dialog.show(rootPane.getScene());
}
}

View File

@ -0,0 +1,155 @@
package com.lw.fx.view.system.notice;
import cn.hutool.core.util.ObjectUtil;
import com.lw.dillon.admin.module.system.controller.admin.notify.vo.template.NotifyTemplateRespVO;
import com.lw.fx.request.Request;
import com.lw.ui.request.api.system.NotifyTemplateFeign;
import de.saxsys.mvvmfx.SceneLifecycle;
import de.saxsys.mvvmfx.ViewModel;
import io.datafx.core.concurrent.ProcessChain;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
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 NotifyTemplateViewModel implements ViewModel, SceneLifecycle {
private SimpleIntegerProperty total = new SimpleIntegerProperty(0);
private IntegerProperty pageNum = new SimpleIntegerProperty(0);
private IntegerProperty pageSize = new SimpleIntegerProperty(10);
private ObjectProperty<ObservableList<NotifyTemplateRespVO>> tableItems = new SimpleObjectProperty<>();
private ObjectProperty<LocalDate> beginDate = new SimpleObjectProperty<>();
private ObjectProperty<LocalDate> endDate = new SimpleObjectProperty<>();
private ObjectProperty<Integer> status = new SimpleObjectProperty<>();
private ObjectProperty<String> name = new SimpleObjectProperty<>();
private ObjectProperty<String> code = new SimpleObjectProperty<>();
public NotifyTemplateViewModel() {
loadTableData();
}
public void loadTableData() {
Map<String, Object> queryMap = new HashMap<>();
queryMap.put("pageNo", pageNum.get() + 1);
queryMap.put("pageSize", pageSize.get());
// queryMap.put("code", code.get());
// queryMap.put("name", name.get());
// queryMap.put("status", status.get());
if (ObjectUtil.isAllNotEmpty(getBeginDate(), getEndDate())) {
String sd = getBeginDate().atTime(0, 0, 0).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
String ed = getEndDate().atTime(23, 59, 59).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
queryMap.put("createTime", new String[]{sd, ed});
}
ProcessChain.create()
.addSupplierInExecutor(() -> Request.connector(NotifyTemplateFeign.class).getNotifyTemplatePage(queryMap))
.addConsumerInPlatformThread(listCommonResult -> {
if (listCommonResult.isSuccess()) {
ObservableList<NotifyTemplateRespVO> userRespVOS = FXCollections.observableArrayList();
userRespVOS.addAll(listCommonResult.getData().getList());
tableItems.set(userRespVOS);
totalProperty().set(listCommonResult.getData().getTotal().intValue());
}
})
.run();
}
public ObjectProperty<ObservableList<NotifyTemplateRespVO>> tableItemsProperty() {
return tableItems;
}
public Integer getStatus() {
return status.get();
}
public ObjectProperty<Integer> statusProperty() {
return status;
}
public ObservableList<NotifyTemplateRespVO> getTableItems() {
return tableItems.get();
}
public LocalDate getBeginDate() {
return beginDate.get();
}
public ObjectProperty<LocalDate> beginDateProperty() {
return beginDate;
}
public LocalDate getEndDate() {
return endDate.get();
}
public ObjectProperty<LocalDate> endDateProperty() {
return endDate;
}
public String getName() {
return name.get();
}
public ObjectProperty<String> nameProperty() {
return name;
}
public String getCode() {
return code.get();
}
public ObjectProperty<String> codeProperty() {
return code;
}
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;
}
@Override
public void onViewAdded() {
}
@Override
public void onViewRemoved() {
}
}

View File

@ -198,7 +198,7 @@ public class OperateLogView implements FxmlView<OperateLogViewModel>, Initializa
Button editBut = new Button("详情");
editBut.setOnAction(event -> showDictTypeFormView(getTableRow().getItem()));
editBut.setOnAction(event -> showFormView(getTableRow().getItem()));
editBut.setGraphic(FontIcon.of(Feather.EDIT));
editBut.getStyleClass().addAll(FLAT, ACCENT);
@ -243,7 +243,7 @@ public class OperateLogView implements FxmlView<OperateLogViewModel>, Initializa
/**
* 显示编辑对话框
*/
private void showDictTypeFormView(OperateLogRespVO operateLogRespVO) {
private void showFormView(OperateLogRespVO operateLogRespVO) {
WFXGenericDialog dialog = new WFXGenericDialog();
ViewTuple<OperateLogDetailView, OperateLogDetailViewModel> load = FluentViewLoader.fxmlView(OperateLogDetailView.class).load();

View File

@ -52,7 +52,7 @@ public class PostFormViewModel implements ViewModel {
wrapper.reload();
}
public CommonResult saveUser(boolean isAdd) {
public CommonResult save(boolean isAdd) {
if (isAdd) {
return Request.connector(PostFeign.class).createPost(getUserSaveReqVO());

View File

@ -192,7 +192,7 @@ public class PostView implements FxmlView<PostViewModel>, Initializable {
} else {
Button editBut = new Button("修改");
editBut.setOnAction(event -> showPostFormView(getTableRow().getItem().getId()));
editBut.setOnAction(event -> showFormView(getTableRow().getItem().getId()));
editBut.setGraphic(FontIcon.of(Feather.EDIT));
editBut.getStyleClass().addAll(FLAT, ACCENT);
@ -228,25 +228,25 @@ public class PostView implements FxmlView<PostViewModel>, Initializable {
startDatePicker.valueProperty().bindBidirectional(viewModel.beginDateProperty());
endDatePicker.valueProperty().bindBidirectional(viewModel.endDateProperty());
addBut.setOnAction(actionEvent -> showPostFormView(null));
addBut.setOnAction(actionEvent -> showFormView(null));
}
/**
* 显示编辑对话框
*/
private void showPostFormView(Long roleId) {
private void showFormView(Long id) {
WFXGenericDialog dialog = new WFXGenericDialog();
boolean isAdd = (roleId == null);
boolean isAdd = (id == null);
ViewTuple<PostFormView, PostFormViewModel> load = FluentViewLoader.fxmlView(PostFormView.class).load();
load.getViewModel().query(roleId);
load.getViewModel().query(id);
dialog.addActions(
Map.entry(new Button("取消"), event -> dialog.close()),
Map.entry(new Button("确定"), event -> {
ProcessChain.create()
.addSupplierInExecutor(() -> {
return load.getViewModel().saveUser(isAdd);
return load.getViewModel().save(isAdd);
})
.addConsumerInPlatformThread(r -> {
if (r.isSuccess()) {
@ -262,7 +262,7 @@ public class PostView implements FxmlView<PostViewModel>, Initializable {
);
dialog.setHeaderIcon(FontIcon.of(Feather.INFO));
dialog.setHeaderText(roleId != null ? "编辑角色" : "添加角色");
dialog.setHeaderText(id != null ? "编辑角色" : "添加角色");
dialog.setContent(load.getView());
dialog.show(rootPane.getScene());

View File

@ -52,7 +52,7 @@ public class RoleFormViewModel implements ViewModel {
wrapper.reload();
}
public CommonResult saveUser(boolean isAdd) {
public CommonResult save(boolean isAdd) {
if (isAdd) {
return Request.connector(RoleFeign.class).createRole(getUserSaveReqVO());

View File

@ -243,18 +243,18 @@ public class RoleView implements FxmlView<RoleViewModel>, Initializable {
/**
* 显示编辑对话框
*/
private void showRoleFormView(Long roleId) {
private void showRoleFormView(Long id) {
WFXGenericDialog dialog = new WFXGenericDialog();
boolean isAdd = (roleId == null);
boolean isAdd = (id == null);
ViewTuple<RoleFormView, RoleFormViewModel> load = FluentViewLoader.fxmlView(RoleFormView.class).load();
load.getViewModel().query(roleId);
load.getViewModel().query(id);
dialog.addActions(
Map.entry(new Button("取消"), event -> dialog.close()),
Map.entry(new Button("确定"), event -> {
ProcessChain.create()
.addSupplierInExecutor(() -> {
return load.getViewModel().saveUser(isAdd);
return load.getViewModel().save(isAdd);
})
.addConsumerInPlatformThread(r -> {
if (r.isSuccess()) {
@ -270,7 +270,7 @@ public class RoleView implements FxmlView<RoleViewModel>, Initializable {
);
dialog.setHeaderIcon(FontIcon.of(Feather.INFO));
dialog.setHeaderText(roleId != null ? "编辑角色" : "添加角色");
dialog.setHeaderText(id != null ? "编辑角色" : "添加角色");
dialog.setContent(load.getView());
dialog.show(rootPane.getScene());

View File

@ -214,7 +214,7 @@ public class UserFormViewModel implements ViewModel, SceneLifecycle {
return selectPostItems;
}
public CommonResult saveUser(boolean isAdd) {
public CommonResult save(boolean isAdd) {
if (isAdd) {
return Request.connector(UserFeign.class).createUser(getUserSaveReqVO());

View File

@ -289,7 +289,7 @@ public class UserView implements FxmlView<UserViewModel>, Initializable {
Map.entry(new Button("确定"), event -> {
ProcessChain.create()
.addSupplierInExecutor(() -> {
return load.getViewModel().saveUser(isAdd);
return load.getViewModel().save(isAdd);
})
.addConsumerInPlatformThread(r -> {
if (r.isSuccess()) {

View File

@ -0,0 +1,50 @@
package com.lw.fx.vo;
import com.lw.dillon.admin.module.system.controller.admin.notify.vo.message.NotifyMessageRespVO;
import io.swagger.v3.oas.annotations.media.Schema;
import javafx.beans.property.SimpleBooleanProperty;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.Map;
@Data
public class NotifyMessageVo {
private SimpleBooleanProperty selectd=new SimpleBooleanProperty();
private Long id;
private Long userId;
private Byte userType;
private Long templateId;
private String templateCode;
private String templateNickname;
private String templateContent;
private Integer templateType;
private Map<String, Object> templateParams;
private Boolean readStatus;
private LocalDateTime readTime;
private LocalDateTime createTime;
public boolean isSelectd() {
return selectd.get();
}
public SimpleBooleanProperty selectdProperty() {
return selectd;
}
public void setSelectd(boolean selectd) {
this.selectd.set(selectd);
}
}

View File

@ -99,13 +99,14 @@
-fx-background-color: -color-danger-emphasis;
}
#userBut .ikonli-font-icon {
-fx-icon-size: 90px;
#decorator-button .ikonli-font-icon {
-fx-icon-size: 28px;
}
.theme-icon {
-fx-background-color: -color-fg-default;
-size: 16;
-size: 25px;
-fx-min-height: -size;
-fx-min-width: -size;
-fx-max-height: -size;
@ -283,7 +284,14 @@
-fx-background-color: linear-gradient(to right, #FF7D05, #FFD422);
}
.tag {
-fx-min-width: 16;
-fx-padding: 4px 4px 4px 4px;
-fx-background-radius: 5px;
-fx-font-size: 0.75em;
-fx-background-color: -color-danger-emphasis;
-fx-text-fill: #ffffff;
}
}

View File

@ -2,8 +2,16 @@
<?import com.dlsc.gemsfx.AvatarView?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.control.ToggleButton?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<?import org.kordamp.ikonli.javafx.FontIcon?>
<BorderPane fx:id="rootPane" prefHeight="511.0" prefWidth="833.0" styleClass="main-pane" xmlns="http://javafx.com/javafx/22" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.lw.fx.view.main.MainView">
<bottom>
<HBox fx:id="statusBarBox" prefHeight="40.0" prefWidth="200.0" style="-fx-border-width: 1 0 0 0; -fx-border-color: -color-border-default;" BorderPane.alignment="CENTER">
@ -23,7 +31,31 @@
<children>
<Button id="decorator-button" fx:id="themeBut" contentDisplay="GRAPHIC_ONLY">
</Button>
<AvatarView fx:id="userBut" size="35.0" />
<AnchorPane>
<children>
<Button id="decorator-button" fx:id="noticeBut" contentDisplay="GRAPHIC_ONLY" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<graphic>
<FontIcon iconLiteral="fth-bell" iconSize="16" />
</graphic>
</Button>
<Label fx:id="tagLabel" alignment="CENTER" mouseTransparent="true" styleClass="tag" text="99+" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0">
<opaqueInsets>
<Insets />
</opaqueInsets>
</Label>
</children>
<HBox.margin>
<Insets />
</HBox.margin>
<padding>
<Insets bottom="5.0" top="5.0" />
</padding>
</AnchorPane>
<AvatarView fx:id="userBut" size="35.0">
<HBox.margin>
<Insets left="10.0" right="10.0" />
</HBox.margin>
</AvatarView>
<Button id="decorator-button" fx:id="minimizeBut" contentDisplay="GRAPHIC_ONLY" />
<Button id="decorator-button" fx:id="maximizeBut" contentDisplay="GRAPHIC_ONLY" />
<Button id="decorator-button-close" fx:id="closeBut" contentDisplay="GRAPHIC_ONLY" />

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Hyperlink?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Region?>
<?import javafx.scene.layout.VBox?>
<?import org.kordamp.ikonli.javafx.FontIcon?>
<VBox prefHeight="449.0" prefWidth="334.0" xmlns="http://javafx.com/javafx/22" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.lw.fx.view.main.MessageView">
<children>
<TabPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="200.0" prefWidth="200.0" tabClosingPolicy="UNAVAILABLE" VBox.vgrow="ALWAYS">
<tabs>
<Tab text="我的消息">
<content>
<ListView fx:id="listView" prefHeight="200.0" prefWidth="200.0" style="-fx-border-width: 0;" />
</content>
</Tab>
</tabs>
</TabPane>
<HBox alignment="CENTER">
<children>
<Hyperlink fx:id="markersBut" text="标记已读" />
<Region HBox.hgrow="ALWAYS" />
<Hyperlink fx:id="viewAllBut" text="查看全部">
<graphic>
<FontIcon iconLiteral="fth-eye" />
</graphic>
</Hyperlink>
</children>
<padding>
<Insets left="10.0" right="10.0" />
</padding>
</HBox>
</children>
</VBox>

View File

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.CheckBox?>
<?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.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.system.notice.MyNotifyMessageView">
<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="readStatusComboBox" 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="handleUpdateListBut" mnemonicParsing="false" text="标记已读">
<graphic>
<FontIcon iconLiteral="fth-columns" />
</graphic></Button>
<Button fx:id="handleUpdateAllBut" mnemonicParsing="false" text="全部已读">
<graphic>
<FontIcon iconLiteral="fth-columns" />
</graphic></Button>
</children>
<opaqueInsets>
<Insets />
</opaqueInsets>
</HBox>
<TableView fx:id="tableView" editable="true" VBox.vgrow="ALWAYS">
<columns>
<TableColumn fx:id="selCol" maxWidth="40.0" minWidth="40.0" prefWidth="40.0" sortable="false">
<graphic>
<CheckBox fx:id="selAllCheckBox" mnemonicParsing="false" />
</graphic>
</TableColumn>
<TableColumn fx:id="templateNicknameCol" prefWidth="-1.0" text="发送人" />
<TableColumn fx:id="createTimeCol" prefWidth="-1.0" text="发送时间" />
<TableColumn fx:id="templateTypeCol" prefWidth="-1.0" text="类型" />
<TableColumn fx:id="templateContentCol" prefWidth="-1.0" text="消息内容" />
<TableColumn fx:id="readStatusCol" prefWidth="-1.0" text="是否已读" />
<TableColumn fx:id="readTimeCol" prefWidth="-1.0" text="阅读时间" />
<TableColumn fx:id="optCol" prefWidth="-1.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

@ -0,0 +1,77 @@
<?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.system.notice.NotifyMessageView">
<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>
<TextField fx:id="userIdField" prefWidth="150.0" promptText="请输入用户编号" />
<ComboBox fx:id="userTypeComBox" promptText="请选择用户类型" />
<TextField fx:id="templateCodeField" promptText="请输入模板编码" />
<ComboBox fx:id="templateTypeComBox" 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="emptyBut" mnemonicParsing="false" text="清空">
<graphic>
<FontIcon iconLiteral="fth-trash" />
</graphic>
</Button>
</children>
<opaqueInsets>
<Insets />
</opaqueInsets>
</HBox>
<TableView fx:id="tableView" editable="true" VBox.vgrow="ALWAYS">
<columns>
<TableColumn fx:id="idCol" maxWidth="80.0" prefWidth="-1.0" text="编号" />
<TableColumn fx:id="userTypeCol" prefWidth="-1.0" text="用户类型" />
<TableColumn fx:id="userIdCol" maxWidth="80.0" prefWidth="-1.0" text="用户编号" />
<TableColumn fx:id="templateCodeCol" prefWidth="-1.0" text="模板编码" />
<TableColumn fx:id="templateNicknameCol" prefWidth="-1.0" text="发送人名称" />
<TableColumn fx:id="templateContentCol" prefWidth="-1.0" text="模版内容" />
<TableColumn fx:id="templateParamsCol" maxWidth="0.0" minWidth="0.0" prefWidth="0.0" text="模版参数" />
<TableColumn fx:id="templateTypeCol" prefWidth="-1.0" text="模版类型" />
<TableColumn fx:id="readStatusCol" prefWidth="-1.0" text="是否已读" />
<TableColumn fx:id="readTimeCol" prefWidth="-1.0" text="阅读时间" />
<TableColumn fx:id="createTimeCol" prefWidth="-1.0" text="创建时间" />
<TableColumn fx:id="optCol" minWidth="20.0" prefWidth="-1.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

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" spacing="10.0" xmlns="http://javafx.com/javafx/22" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.lw.fx.view.system.notice.NotifyTemplateFormView">
<children>
<HBox alignment="CENTER_LEFT" spacing="10.0">
<children>
<Label alignment="CENTER_RIGHT" maxWidth="80.0" minWidth="80.0" text="模版编码" />
<TextField fx:id="codeTield" promptText="请输入模版编码" HBox.hgrow="ALWAYS" />
</children>
</HBox>
<HBox alignment="CENTER_LEFT" spacing="10.0">
<children>
<Label alignment="CENTER_RIGHT" maxWidth="80.0" minWidth="80.0" text="模板名称" />
<TextField fx:id="nameField" promptText="请输入模版名称" HBox.hgrow="ALWAYS" />
</children>
</HBox>
<HBox alignment="CENTER_LEFT" spacing="10.0">
<children>
<Label alignment="CENTER_RIGHT" maxWidth="80.0" minWidth="80.0" text="发件人名称" />
<TextField fx:id="nicknameField" promptText="请输入发件人名称" HBox.hgrow="ALWAYS" />
</children>
</HBox>
<HBox alignment="CENTER_LEFT" spacing="10.0">
<children>
<Label alignment="CENTER_RIGHT" maxWidth="80.0" minWidth="80.0" text="类型" />
<ComboBox fx:id="typeComboBox" prefWidth="150.0" promptText="请选择类型" />
</children>
</HBox>
<HBox alignment="CENTER_LEFT" spacing="10.0">
<children>
<Label alignment="CENTER_RIGHT" maxWidth="80.0" minWidth="80.0" text="开启状态" />
<ComboBox fx:id="statusComboBox" prefWidth="150.0" />
</children>
</HBox>
<HBox spacing="10.0" VBox.vgrow="ALWAYS">
<children>
<Label alignment="CENTER_RIGHT" maxWidth="80.0" minWidth="80.0" text="模板内容" />
<TextArea fx:id="contentArea" prefHeight="200.0" prefWidth="200.0" promptText="请输入模板内容" HBox.hgrow="ALWAYS" />
</children>
</HBox>
<HBox alignment="CENTER_LEFT" spacing="10.0">
<children>
<Label alignment="CENTER_RIGHT" maxWidth="80.0" minWidth="80.0" text="备注" />
<TextField fx:id="remarkField" HBox.hgrow="ALWAYS" />
</children>
</HBox>
</children>
</VBox>

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" spacing="10.0" xmlns="http://javafx.com/javafx/22" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.lw.fx.view.system.notice.NotifyTemplateSendFormView">
<children>
<HBox spacing="10.0" VBox.vgrow="ALWAYS">
<children>
<Label alignment="CENTER_RIGHT" maxWidth="80.0" minWidth="80.0" text="模板内容" />
<TextArea fx:id="contentArea" prefHeight="200.0" prefWidth="200.0" promptText="请输入模板内容" HBox.hgrow="ALWAYS" />
</children>
</HBox>
<HBox alignment="CENTER_LEFT" spacing="10.0">
<children>
<Label alignment="CENTER_RIGHT" maxWidth="80.0" minWidth="80.0" text="用户类型" />
<ComboBox fx:id="userTypeComboBox" promptText="请选择类型" />
</children>
</HBox>
<HBox alignment="CENTER_LEFT" spacing="10.0">
<children>
<Label alignment="CENTER_RIGHT" maxWidth="80.0" minWidth="80.0" text="接收人" />
<ComboBox fx:id="userComboBox" prefWidth="150.0" />
</children>
</HBox>
<VBox fx:id="paramsBox" spacing="10.0" />
</children>
</VBox>

View File

@ -0,0 +1,72 @@
<?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.system.notice.NotifyTemplateView">
<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="151.0" promptText="请输入模板名称" />
<Label text="模板编号" />
<TextField fx:id="codeField" prefWidth="151.0" promptText="请输入模版编码" />
<Label text="状态" />
<ComboBox fx:id="statusCombo" promptText="请选择开启状态">
</ComboBox>
<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>
</children>
<opaqueInsets>
<Insets />
</opaqueInsets>
</HBox>
<TableView fx:id="tableView" editable="true" VBox.vgrow="ALWAYS">
<columns>
<TableColumn fx:id="idCol" prefWidth="-1.0" text="模板编码" />
<TableColumn fx:id="nameCol" prefWidth="-1.0" text="模板名称" />
<TableColumn fx:id="typeCol" prefWidth="-1.0" text="类型" />
<TableColumn fx:id="nicknameCol" prefWidth="-1.0" text="发送人名称" />
<TableColumn fx:id="contentCol" prefWidth="-1.0" text="模板内容" />
<TableColumn fx:id="statusCol" prefWidth="-1.0" text="开启状态" />
<TableColumn fx:id="remarkCol" prefWidth="-1.0" text="备注" />
<TableColumn fx:id="createTimeCol" prefWidth="-1.0" text="创建时间" />
<TableColumn fx:id="optCol" maxWidth="280.0" prefWidth="280.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>