diff --git a/.image/javafx/我的消息1.png b/.image/javafx/我的消息1.png new file mode 100644 index 0000000..148024c Binary files /dev/null and b/.image/javafx/我的消息1.png differ diff --git a/.image/javafx/我的消息2.png b/.image/javafx/我的消息2.png new file mode 100644 index 0000000..bcb8f27 Binary files /dev/null and b/.image/javafx/我的消息2.png differ diff --git a/.image/javafx/我的消息3.png b/.image/javafx/我的消息3.png new file mode 100644 index 0000000..5ee470c Binary files /dev/null and b/.image/javafx/我的消息3.png differ diff --git a/.image/javafx/消息模板1.png b/.image/javafx/消息模板1.png new file mode 100644 index 0000000..0c48c7e Binary files /dev/null and b/.image/javafx/消息模板1.png differ diff --git a/.image/javafx/消息模板2.png b/.image/javafx/消息模板2.png new file mode 100644 index 0000000..7d73fd8 Binary files /dev/null and b/.image/javafx/消息模板2.png differ diff --git a/.image/javafx/消息模板3.png b/.image/javafx/消息模板3.png new file mode 100644 index 0000000..6f370d4 Binary files /dev/null and b/.image/javafx/消息模板3.png differ diff --git a/.image/javafx/消息记录1.png b/.image/javafx/消息记录1.png new file mode 100644 index 0000000..4fedaac Binary files /dev/null and b/.image/javafx/消息记录1.png differ diff --git a/.image/javafx/消息记录2.png b/.image/javafx/消息记录2.png new file mode 100644 index 0000000..946557f Binary files /dev/null and b/.image/javafx/消息记录2.png differ diff --git a/.image/javafx/消息记录3.png b/.image/javafx/消息记录3.png new file mode 100644 index 0000000..194399e Binary files /dev/null and b/.image/javafx/消息记录3.png differ diff --git a/README.md b/README.md index dc90c6c..a219e3f 100644 --- a/README.md +++ b/README.md @@ -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 的 部分 + ```agsl sonatype-snapshots @@ -48,14 +44,52 @@ HTTP库:使用 OpenFeign HTTP库,该库提供了方便的 HTTP 请求和响 ``` + ## 启动说明 +## 快速启动(后端项目) + +### 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】: @@ -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) | - | - | diff --git a/dillon-module-system/dillon-module-system-biz/src/main/java/com/lw/dillon/admin/module/system/controller/admin/notify/vo/message/NotifyMessageRespVO.java b/dillon-module-system/dillon-module-system-biz/src/main/java/com/lw/dillon/admin/module/system/controller/admin/notify/vo/message/NotifyMessageRespVO.java index 645106c..651f143 100644 --- a/dillon-module-system/dillon-module-system-biz/src/main/java/com/lw/dillon/admin/module/system/controller/admin/notify/vo/message/NotifyMessageRespVO.java +++ b/dillon-module-system/dillon-module-system-biz/src/main/java/com/lw/dillon/admin/module/system/controller/admin/notify/vo/message/NotifyMessageRespVO.java @@ -46,4 +46,5 @@ public class NotifyMessageRespVO { @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; + } diff --git a/dillon-ui/dillon-ui-common/src/main/java/com/lw/ui/request/api/system/NotifyMessageFeign.java b/dillon-ui/dillon-ui-common/src/main/java/com/lw/ui/request/api/system/NotifyMessageFeign.java new file mode 100644 index 0000000..c95ffd4 --- /dev/null +++ b/dillon-ui/dillon-ui-common/src/main/java/com/lw/ui/request/api/system/NotifyMessageFeign.java @@ -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 getNotifyMessage(@Param("id") Long id); + + //获得站内信分页") + @RequestLine("GET /admin-api/system/notify-message/page") + CommonResult> getNotifyMessagePage(@QueryMap Map pageVO); + + // ========== 查看自己的站内信 ========== + //获得我的站内信分页" + @RequestLine("GET /admin-api/system/notify-message/my-page") + CommonResult> getMyMyNotifyMessagePage(@QueryMap Map pageVO); + + //标记站内信为已读") + @RequestLine("PUT /admin-api/system/notify-message/update-read?ids={ids}") + CommonResult updateNotifyMessageRead( @Param("ids")List ids); + + //标记所有站内信为已读") + @RequestLine("PUT /admin-api/system/notify-message/update-all-read") + CommonResult updateAllNotifyMessageRead(); + + @RequestLine("GET /admin-api/system/notify-message/get-unread-list?size={size}") + CommonResult> getUnreadNotifyMessageList(@Param("size") Integer size); + + //获得当前用户的未读站内信数量") + @RequestLine("GET /admin-api/system/notify-message/get-unread-count") + CommonResult getUnreadNotifyMessageCount(); + +} diff --git a/dillon-ui/dillon-ui-common/src/main/java/com/lw/ui/request/api/system/NotifyTemplateFeign.java b/dillon-ui/dillon-ui-common/src/main/java/com/lw/ui/request/api/system/NotifyTemplateFeign.java new file mode 100644 index 0000000..648f9c5 --- /dev/null +++ b/dillon-ui/dillon-ui-common/src/main/java/com/lw/ui/request/api/system/NotifyTemplateFeign.java @@ -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 createNotifyTemplate(NotifyTemplateSaveReqVO createReqVO); + + //"更新站内信模版") + @RequestLine("PUT /admin-api/system/notify-template/update") + CommonResult updateNotifyTemplate(NotifyTemplateSaveReqVO updateReqVO); + + //"删除站内信模版") + @RequestLine("DELETE /admin-api/system/notify-template/delete?id={id}") + CommonResult deleteNotifyTemplate(@Param("id") Long id); + + //"获得站内信模版") + @RequestLine("GET /admin-api/system/notify-template/get?id={id}") + CommonResult getNotifyTemplate(@Param("id") Long id); + + //"获得站内信模版分页") + @RequestLine("GET /admin-api/system/notify-template/page") + CommonResult> getNotifyTemplatePage(@QueryMap Map pageVO); + + //"发送站内信") + @RequestLine("POST /admin-api/system/notify-template/send-notify") + CommonResult sendNotify(NotifyTemplateSendReqVO sendReqVO); +} diff --git a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/request/Request.java b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/request/Request.java index a2a910d..0104c68 100644 --- a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/request/Request.java +++ b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/request/Request.java @@ -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()); // 默认重试策略 diff --git a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/main/MainView.java b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/main/MainView.java index 0ab4cca..16796c2 100644 --- a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/main/MainView.java +++ b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/main/MainView.java @@ -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, 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, Initializable { @FXML private VBox sideBox; + private Popover popover; + private NavTree sideMenu; private Lazy themeDialog; @@ -78,6 +90,10 @@ public class MainView implements FxmlView, 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, 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, Initializable { initListeners(); + noticeBut.setOnMouseClicked(actionEvent ->{ + ViewTuple 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 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, 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, 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, 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, Initializable { menuItem1.setOnAction(actionEvent -> { ViewTuple viewTuple = FluentViewLoader.fxmlView(UserInfoView.class).load(); - MvvmFX.getNotificationCenter().publish("addTab", "个人中心", "", viewTuple.getView()); + MvvmFX.getNotificationCenter().publish("addTab", "个人中心", Feather.USER, viewTuple.getView()); }); diff --git a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/main/MainViewModel.java b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/main/MainViewModel.java index 4aac3b6..26fcb21 100644 --- a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/main/MainViewModel.java +++ b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/main/MainViewModel.java @@ -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; + } } diff --git a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/main/MessageView.java b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/main/MessageView.java new file mode 100644 index 0000000..d09f71c --- /dev/null +++ b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/main/MessageView.java @@ -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, Initializable { + @FXML + private ListView 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 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(); + }); + } +} diff --git a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/main/MessageViewModel.java b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/main/MessageViewModel.java new file mode 100644 index 0000000..aef325d --- /dev/null +++ b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/main/MessageViewModel.java @@ -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 items = FXCollections.observableArrayList(); + + public MessageViewModel() { + getUnreadNotifyMessageList(); + } + + public CommonResult updateNotifyMessageRead() { + + Set 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 getItems() { + return items; + } +} diff --git a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/dept/DeptFromView.java b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/dept/DeptFromView.java index e23a11f..24df7a6 100644 --- a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/dept/DeptFromView.java +++ b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/dept/DeptFromView.java @@ -103,13 +103,12 @@ public class DeptFromView implements FxmlView, 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)); diff --git a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/dict/DictTypeFormViewModel.java b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/dict/DictTypeFormViewModel.java index f5494d4..d629004 100644 --- a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/dict/DictTypeFormViewModel.java +++ b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/dict/DictTypeFormViewModel.java @@ -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()); diff --git a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/dict/DictTypeView.java b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/dict/DictTypeView.java index 1c0f920..a2bd680 100644 --- a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/dict/DictTypeView.java +++ b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/dict/DictTypeView.java @@ -192,14 +192,14 @@ public class DictTypeView implements FxmlView, Initializable dataBut.setOnAction(event -> { ViewTuple 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, 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 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, Initializable ); dialog.setHeaderIcon(FontIcon.of(Feather.INFO)); - dialog.setHeaderText(roleId != null ? "编辑角色" : "添加角色"); + dialog.setHeaderText(id != null ? "编辑角色" : "添加角色"); dialog.setContent(load.getView()); dialog.show(rootPane.getScene()); diff --git a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/dict/data/DictDataFormViewModel.java b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/dict/data/DictDataFormViewModel.java index 364dccc..6a39ca3 100644 --- a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/dict/data/DictDataFormViewModel.java +++ b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/dict/data/DictDataFormViewModel.java @@ -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()); diff --git a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/dict/data/DictDataView.java b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/dict/data/DictDataView.java index 8924d50..8ee3e2d 100644 --- a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/dict/data/DictDataView.java +++ b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/dict/data/DictDataView.java @@ -247,7 +247,7 @@ public class DictDataView implements FxmlView, Initializable Map.entry(new Button("确定"), event -> { ProcessChain.create() .addSupplierInExecutor(() -> { - return load.getViewModel().saveUser(isAdd); + return load.getViewModel().save(isAdd); }) .addConsumerInPlatformThread(r -> { if (r.isSuccess()) { diff --git a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/loginlog/LoginLogView.java b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/loginlog/LoginLogView.java index ffaea5c..413fec9 100644 --- a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/loginlog/LoginLogView.java +++ b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/loginlog/LoginLogView.java @@ -264,7 +264,7 @@ public class LoginLogView implements FxmlView, 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, Initializable /** * 显示编辑对话框 */ - private void showDictTypeFormView(LoginLogRespVO operateLogRespVO) { + private void showFormView(LoginLogRespVO operateLogRespVO) { WFXGenericDialog dialog = new WFXGenericDialog(); ViewTuple load = FluentViewLoader.fxmlView(LoginLogDetailView.class).load(); diff --git a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/menu/MenuFromView.java b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/menu/MenuFromView.java index c111d8c..57e9ae2 100644 --- a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/menu/MenuFromView.java +++ b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/menu/MenuFromView.java @@ -166,11 +166,13 @@ public class MenuFromView implements FxmlView, 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)); diff --git a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/menu/MenuFromViewModel.java b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/menu/MenuFromViewModel.java index d7f1a47..4290f08 100644 --- a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/menu/MenuFromViewModel.java +++ b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/menu/MenuFromViewModel.java @@ -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()) diff --git a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/menu/MenuManageView.java b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/menu/MenuManageView.java index de9274f..2443ecd 100644 --- a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/menu/MenuManageView.java +++ b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/menu/MenuManageView.java @@ -41,7 +41,6 @@ public class MenuManageView implements FxmlView, Initializa private MenuManageViewModel viewModel; - @FXML private VBox content; @@ -157,7 +156,7 @@ public class MenuManageView implements FxmlView, 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, Initializa WFXGenericDialog dialog = new WFXGenericDialog(); ViewTuple 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, 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, 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, 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, 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, Initializa } - - - - } diff --git a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/MyNotifyMessageView.java b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/MyNotifyMessageView.java new file mode 100644 index 0000000..9916003 --- /dev/null +++ b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/MyNotifyMessageView.java @@ -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, Initializable { + + @InjectViewModel + private MyNotifyMessageViewModel viewModel; + @FXML + private VBox contentPane; + + @FXML + private TableColumn createTimeCol; + + @FXML + private DatePicker endDatePicker; + + @FXML + private TableColumn optCol; + @FXML + private TableColumn selCol; + + @FXML + private TableColumn readStatusCol; + + @FXML + private ComboBox readStatusComboBox; + + @FXML + private TableColumn 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 tableView; + + @FXML + private TableColumn templateContentCol; + + @FXML + private TableColumn templateNicknameCol; + + @FXML + private TableColumn 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, TableCell>() { + @Override + public TableCell call(TableColumn 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, TableCell>() { + @Override + public TableCell call(TableColumn 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, TableCell>() { + @Override + public TableCell call(TableColumn 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, TableCell>() { + @Override + public TableCell call(TableColumn 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, TableCell>() { + @Override + public TableCell call(TableColumn param) { + + TableCell cell = new TableCell() { + @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()); + } +} diff --git a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/MyNotifyMessageViewModel.java b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/MyNotifyMessageViewModel.java new file mode 100644 index 0000000..f7256ee --- /dev/null +++ b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/MyNotifyMessageViewModel.java @@ -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 tableItems = FXCollections.observableArrayList(); + private ObservableList stautsItems = FXCollections.observableArrayList(); + + private ObjectProperty beginDate = new SimpleObjectProperty<>(); + private ObjectProperty endDate = new SimpleObjectProperty<>(); + private ObjectProperty 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 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 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 beginDateProperty() { + return beginDate; + } + + public LocalDate getEndDate() { + return endDate.get(); + } + + public ObjectProperty 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 getTableItems() { + return tableItems; + } + + public ObservableList getStautsItems() { + return stautsItems; + } + + public Boolean getStatus() { + return status.get(); + } + + public ObjectProperty statusProperty() { + return status; + } + + @Override + public void onViewAdded() { + + } + + @Override + public void onViewRemoved() { + + } +} diff --git a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/NoticeFormViewModel.java b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/NoticeFormViewModel.java index 97c6932..9754f51 100644 --- a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/NoticeFormViewModel.java +++ b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/NoticeFormViewModel.java @@ -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()); diff --git a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/NoticeView.java b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/NoticeView.java index d933180..884682d 100644 --- a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/NoticeView.java +++ b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/NoticeView.java @@ -226,7 +226,7 @@ public class NoticeView implements FxmlView, 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, 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 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, Initializable { ); dialog.setHeaderIcon(FontIcon.of(Feather.INFO)); - dialog.setHeaderText(roleId != null ? "编辑角色" : "添加角色"); + dialog.setHeaderText(id != null ? "编辑角色" : "添加角色"); dialog.setContent(load.getView()); dialog.show(rootPane.getScene()); diff --git a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/NotifyMessageView.java b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/NotifyMessageView.java new file mode 100644 index 0000000..85c0f97 --- /dev/null +++ b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/NotifyMessageView.java @@ -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, Initializable { + + @InjectViewModel + private NotifyMessageViewModel viewModel; + @FXML + private VBox contentPane; + + @FXML + private TableColumn createTimeCol; + + @FXML + private Button emptyBut; + + @FXML + private DatePicker endDatePicker; + + @FXML + private TableColumn idCol; + + @FXML + private TableColumn optCol; + + @FXML + private TableColumn readStatusCol; + + @FXML + private TableColumn readTimeCol; + + @FXML + private Button resetBut; + + @FXML + private StackPane rootPane; + + @FXML + private Button searchBut; + + @FXML + private DatePicker startDatePicker; + + @FXML + private TableView tableView; + + @FXML + private TableColumn templateCodeCol; + + @FXML + private TextField templateCodeField; + + @FXML + private TableColumn templateContentCol; + + @FXML + private TableColumn templateNicknameCol; + + @FXML + private TableColumn templateParamsCol; + + @FXML + private TableColumn templateTypeCol; + + @FXML + private ComboBox templateTypeComBox; + + @FXML + private TableColumn userIdCol; + + @FXML + private TextField userIdField; + + @FXML + private TableColumn userTypeCol; + + @FXML + private ComboBox 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, TableCell>() { + @Override + public TableCell call(TableColumn 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, TableCell>() { + @Override + public TableCell call(TableColumn 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, TableCell>() { + @Override + public TableCell call(TableColumn 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, TableCell>() { + @Override + public TableCell call(TableColumn 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, TableCell>() { + @Override + public TableCell call(TableColumn 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, TableCell>() { + @Override + public TableCell call(TableColumn param) { + + TableCell cell = new TableCell() { + @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()); + } +} diff --git a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/NotifyMessageViewModel.java b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/NotifyMessageViewModel.java new file mode 100644 index 0000000..1d80981 --- /dev/null +++ b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/NotifyMessageViewModel.java @@ -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> tableItems = new SimpleObjectProperty<>(); + + + private ObjectProperty beginDate = new SimpleObjectProperty<>(); + private ObjectProperty 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 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 userRespVOS = FXCollections.observableArrayList(); + userRespVOS.addAll(listCommonResult.getData().getList()); + tableItems.set(userRespVOS); + totalProperty().set(listCommonResult.getData().getTotal().intValue()); + } + }) + .run(); + + + } + + + public ObjectProperty> tableItemsProperty() { + return tableItems; + } + + + + public LocalDate getBeginDate() { + return beginDate.get(); + } + + public ObjectProperty beginDateProperty() { + return beginDate; + } + + public LocalDate getEndDate() { + return endDate.get(); + } + + public ObjectProperty 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 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() { + + } +} diff --git a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/NotifyTemplateFormView.java b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/NotifyTemplateFormView.java new file mode 100644 index 0000000..472a00c --- /dev/null +++ b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/NotifyTemplateFormView.java @@ -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, 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 statusComboBox; + + @FXML + private ComboBox 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()); + + + + } + + + + +} diff --git a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/NotifyTemplateFormViewModel.java b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/NotifyTemplateFormViewModel.java new file mode 100644 index 0000000..796cc05 --- /dev/null +++ b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/NotifyTemplateFormViewModel.java @@ -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 wrapper = new ModelWrapper<>(); + + private ObjectProperty selType = new SimpleObjectProperty<>(); + private ObjectProperty 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 selTypeProperty() { + return selType; + } + + public void setSelType(DictDataSimpleRespVO selType) { + this.selType.set(selType); + } + + public DictDataSimpleRespVO getSelStatus() { + return selStatus.get(); + } + + public ObjectProperty selStatusProperty() { + return selStatus; + } +} + diff --git a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/NotifyTemplateSendFormView.java b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/NotifyTemplateSendFormView.java new file mode 100644 index 0000000..d49b676 --- /dev/null +++ b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/NotifyTemplateSendFormView.java @@ -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, Initializable { + @InjectViewModel + private NotifyTemplateSendFormViewModel viewModel; + @FXML + private TextArea contentArea; + + @FXML + private ComboBox userComboBox; + + @FXML + private ComboBox 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; + } + + +} diff --git a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/NotifyTemplateSendFormViewModel.java b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/NotifyTemplateSendFormViewModel.java new file mode 100644 index 0000000..ea27497 --- /dev/null +++ b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/NotifyTemplateSendFormViewModel.java @@ -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 wrapper = new ModelWrapper<>(); + + private ObjectProperty userType = new SimpleObjectProperty<>(); + private ObjectProperty selUser = new SimpleObjectProperty<>(); + + private Map templateParams = new HashMap<>(); + + private ObservableList 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 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 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 userTypeProperty() { + return userType; + } + + + + public void putParams(String params, String value) { + templateParams.put(params, value); + } + + public ObservableList getUserItems() { + return userItems; + } + + public UserSimpleRespVO getSelUser() { + return selUser.get(); + } + + public ObjectProperty selUserProperty() { + return selUser; + } +} + diff --git a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/NotifyTemplateView.java b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/NotifyTemplateView.java new file mode 100644 index 0000000..a08f4b9 --- /dev/null +++ b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/NotifyTemplateView.java @@ -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, Initializable { + + @InjectViewModel + private NotifyTemplateViewModel viewModel; + + @FXML + private Button addBut; + + @FXML + private TextField codeField; + + @FXML + private TableColumn contentCol; + + @FXML + private VBox contentPane; + + @FXML + private TableColumn createTimeCol; + + @FXML + private TableColumn idCol; + + @FXML + private TableColumn nameCol; + + @FXML + private TextField nameField; + + @FXML + private TableColumn nicknameCol; + + @FXML + private TableColumn optCol; + + @FXML + private TableColumn remarkCol; + + @FXML + private Button resetBut; + + @FXML + private StackPane rootPane; + + @FXML + private Button searchBut; + + @FXML + private TableColumn statusCol; + + @FXML + private ComboBox statusCombo; + + @FXML + private TableView tableView; + + @FXML + private TableColumn 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, TableCell>() { + @Override + public TableCell call(TableColumn 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, TableCell>() { + @Override + public TableCell call(TableColumn 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, TableCell>() { + @Override + public TableCell call(TableColumn 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, TableCell>() { + @Override + public TableCell call(TableColumn param) { + + TableCell cell = new TableCell() { + @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 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 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()); + } +} diff --git a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/NotifyTemplateViewModel.java b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/NotifyTemplateViewModel.java new file mode 100644 index 0000000..ed61080 --- /dev/null +++ b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/notice/NotifyTemplateViewModel.java @@ -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> tableItems = new SimpleObjectProperty<>(); + + private ObjectProperty beginDate = new SimpleObjectProperty<>(); + private ObjectProperty endDate = new SimpleObjectProperty<>(); + private ObjectProperty status = new SimpleObjectProperty<>(); + private ObjectProperty name = new SimpleObjectProperty<>(); + private ObjectProperty code = new SimpleObjectProperty<>(); + + public NotifyTemplateViewModel() { + + loadTableData(); + } + + + public void loadTableData() { + + Map 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 userRespVOS = FXCollections.observableArrayList(); + userRespVOS.addAll(listCommonResult.getData().getList()); + tableItems.set(userRespVOS); + totalProperty().set(listCommonResult.getData().getTotal().intValue()); + } + }) + .run(); + + + } + + + public ObjectProperty> tableItemsProperty() { + return tableItems; + } + + public Integer getStatus() { + return status.get(); + } + + public ObjectProperty statusProperty() { + return status; + } + + public ObservableList getTableItems() { + return tableItems.get(); + } + + public LocalDate getBeginDate() { + return beginDate.get(); + } + + public ObjectProperty beginDateProperty() { + return beginDate; + } + + public LocalDate getEndDate() { + return endDate.get(); + } + + public ObjectProperty endDateProperty() { + return endDate; + } + + public String getName() { + return name.get(); + } + + public ObjectProperty nameProperty() { + return name; + } + + public String getCode() { + return code.get(); + } + + public ObjectProperty 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() { + + } +} diff --git a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/operatelog/OperateLogView.java b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/operatelog/OperateLogView.java index 21a2c45..fe6e41c 100644 --- a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/operatelog/OperateLogView.java +++ b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/operatelog/OperateLogView.java @@ -198,7 +198,7 @@ public class OperateLogView implements FxmlView, 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, Initializa /** * 显示编辑对话框 */ - private void showDictTypeFormView(OperateLogRespVO operateLogRespVO) { + private void showFormView(OperateLogRespVO operateLogRespVO) { WFXGenericDialog dialog = new WFXGenericDialog(); ViewTuple load = FluentViewLoader.fxmlView(OperateLogDetailView.class).load(); diff --git a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/post/PostFormViewModel.java b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/post/PostFormViewModel.java index dec6d94..875038e 100644 --- a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/post/PostFormViewModel.java +++ b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/post/PostFormViewModel.java @@ -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()); diff --git a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/post/PostView.java b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/post/PostView.java index 22a075b..79281dd 100644 --- a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/post/PostView.java +++ b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/post/PostView.java @@ -192,7 +192,7 @@ public class PostView implements FxmlView, 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, 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 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, Initializable { ); dialog.setHeaderIcon(FontIcon.of(Feather.INFO)); - dialog.setHeaderText(roleId != null ? "编辑角色" : "添加角色"); + dialog.setHeaderText(id != null ? "编辑角色" : "添加角色"); dialog.setContent(load.getView()); dialog.show(rootPane.getScene()); diff --git a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/role/RoleFormViewModel.java b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/role/RoleFormViewModel.java index b1f98bc..63a26ff 100644 --- a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/role/RoleFormViewModel.java +++ b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/role/RoleFormViewModel.java @@ -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()); diff --git a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/role/RoleView.java b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/role/RoleView.java index cbf6db2..e36eadd 100644 --- a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/role/RoleView.java +++ b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/role/RoleView.java @@ -243,18 +243,18 @@ public class RoleView implements FxmlView, Initializable { /** * 显示编辑对话框 */ - private void showRoleFormView(Long roleId) { + private void showRoleFormView(Long id) { WFXGenericDialog dialog = new WFXGenericDialog(); - boolean isAdd = (roleId == null); + boolean isAdd = (id == null); ViewTuple 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, Initializable { ); dialog.setHeaderIcon(FontIcon.of(Feather.INFO)); - dialog.setHeaderText(roleId != null ? "编辑角色" : "添加角色"); + dialog.setHeaderText(id != null ? "编辑角色" : "添加角色"); dialog.setContent(load.getView()); dialog.show(rootPane.getScene()); diff --git a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/user/UserFormViewModel.java b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/user/UserFormViewModel.java index 727b9d6..93b5668 100644 --- a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/user/UserFormViewModel.java +++ b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/user/UserFormViewModel.java @@ -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()); diff --git a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/user/UserView.java b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/user/UserView.java index 57524b5..8494724 100644 --- a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/user/UserView.java +++ b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/view/system/user/UserView.java @@ -289,7 +289,7 @@ public class UserView implements FxmlView, Initializable { Map.entry(new Button("确定"), event -> { ProcessChain.create() .addSupplierInExecutor(() -> { - return load.getViewModel().saveUser(isAdd); + return load.getViewModel().save(isAdd); }) .addConsumerInPlatformThread(r -> { if (r.isSuccess()) { diff --git a/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/vo/NotifyMessageVo.java b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/vo/NotifyMessageVo.java new file mode 100644 index 0000000..e008c87 --- /dev/null +++ b/dillon-ui/dillon-ui-fx/src/main/java/com/lw/fx/vo/NotifyMessageVo.java @@ -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 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); + } +} diff --git a/dillon-ui/dillon-ui-fx/src/main/resources/com/lw/fx/assets/styles/scss/layout/_root.scss b/dillon-ui/dillon-ui-fx/src/main/resources/com/lw/fx/assets/styles/scss/layout/_root.scss index 4067a61..fb32dc0 100644 --- a/dillon-ui/dillon-ui-fx/src/main/resources/com/lw/fx/assets/styles/scss/layout/_root.scss +++ b/dillon-ui/dillon-ui-fx/src/main/resources/com/lw/fx/assets/styles/scss/layout/_root.scss @@ -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; + } } diff --git a/dillon-ui/dillon-ui-fx/src/main/resources/com/lw/fx/view/main/MainView.fxml b/dillon-ui/dillon-ui-fx/src/main/resources/com/lw/fx/view/main/MainView.fxml index 2548f98..3b09270 100644 --- a/dillon-ui/dillon-ui-fx/src/main/resources/com/lw/fx/view/main/MainView.fxml +++ b/dillon-ui/dillon-ui-fx/src/main/resources/com/lw/fx/view/main/MainView.fxml @@ -2,8 +2,16 @@ - - + + + + + + + + + + @@ -23,7 +31,31 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dillon-ui/dillon-ui-fx/src/main/resources/com/lw/fx/view/system/notice/NotifyMessageView.fxml b/dillon-ui/dillon-ui-fx/src/main/resources/com/lw/fx/view/system/notice/NotifyMessageView.fxml new file mode 100644 index 0000000..79af431 --- /dev/null +++ b/dillon-ui/dillon-ui-fx/src/main/resources/com/lw/fx/view/system/notice/NotifyMessageView.fxml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dillon-ui/dillon-ui-fx/src/main/resources/com/lw/fx/view/system/notice/NotifyTemplateFormView.fxml b/dillon-ui/dillon-ui-fx/src/main/resources/com/lw/fx/view/system/notice/NotifyTemplateFormView.fxml new file mode 100644 index 0000000..7ae94cd --- /dev/null +++ b/dillon-ui/dillon-ui-fx/src/main/resources/com/lw/fx/view/system/notice/NotifyTemplateFormView.fxml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +