Compare commits

..

55 Commits

Author SHA1 Message Date
57fbae90c5 feat: 实现文件类型枚举的本地化支持
新增文件类型枚举的本地化功能,包括供应商、项目、公司、合同和客户文件类型。添加了相关的SQL表结构、Repository、Service、ViewModel和StringConverter实现。同时更新了文档说明如何创建和使用枚举类型的本地化功能。

修改了客户文件类型的相关代码,统一使用CustomerFileTypeLocalVo替代原有的CompanyCustomerFileTypeLocal,优化了代码结构和一致性。添加了文件类型枚举的缓存支持,提高了性能。

更新了create_enum.md文档,详细说明了文件类型枚举本地化的实现方式和相关组件清单。
2025-09-23 22:34:59 +08:00
4b8c1d4038 refactor(文件类型): 重构文件类型相关仓库和服务
- 将CompanyVendorFileTypeLocalRepository重命名为VendorFileTypeLocalRepository
- 新增CustomerFileTypeLocalRepository
- 更新VendorFileTypeService使用新的仓库名称
- 新增CustomerFileTypeLocal实体类
- 更新文档结构
2025-09-23 18:42:46 +08:00
543311c676 refactor(controller): 重构枚举类型相关代码,优化类型转换和显示逻辑
重构枚举类型的处理逻辑,统一使用Vo对象替代Model对象
- 修改ComboBoxUtils初始化逻辑,支持更多类型转换
- 实现VendorCatalogStringConverter用于类型转换
- 更新ContractFileTypeListCell和ContractFileTypeTableCell显示逻辑
- 调整VendorTabSkinFile和CompanyVendorTabSkinBase使用新的类型转换方式
- 更新相关服务类接口,添加类型转换方法
- 修改FXML文件添加类型选择控件
2025-09-23 18:24:00 +08:00
73cbb4e19e feat: 添加合同文件类型相关类和文档
添加了VendorCatalogStringConverter转换器类、ContractFileTypeListCell列表单元格类和ContractFileTypeTableCell表格单元格类,并创建了相关文档文件
2025-09-23 18:21:26 +08:00
515b255567 feat: 添加供应商类型本地化支持及优化表格单元格显示
refactor: 重构供应商类型相关服务及控制器
fix: 修复供应商类型表格单元格初始化问题
style: 优化代码格式及导入顺序
2025-09-23 14:12:09 +08:00
386b6d01b4 feat: 添加项目文件和客户文件类型服务类
添加 ProjectFileTypeService 和 CompanyCustomerFileTypeService 服务类,用于处理文件和客户类型相关逻辑
2025-09-23 14:11:49 +08:00
39dbce013f feat(converter): 实现通用枚举转换器和供应商类型转换器
添加EnumEntityStringConverter作为通用枚举转换基类
实现VendorTypeStringConverter用于供应商类型本地化转换
在VendorTypeService中添加findByLocaleAndValue方法支持转换器
优化ComboBoxUtils的绑定逻辑使其支持可选属性
新增VendorCatalogService提供供应商目录CRUD功能
2025-09-22 23:54:50 +08:00
b84e011857 feat: 添加枚举和供应商类型转换器及供应商目录服务
添加三个新类:
1. EnumEntityStringConverter - 枚举实体字符串转换器
2. VendorTypeStringConverter - 供应商类型字符串转换器
3. VendorCatalogService - 供应商目录服务
2025-09-22 23:54:23 +08:00
866e08224a refactor(vo): 重构VO类及相关模型,添加Voable接口实现
feat(constant): 添加WebSocket错误码常量
docs(model): 为模型类添加注释
fix(service): 修复ProductUsageService缓存键问题
refactor(converter): 重构字符串转换器,移除EntityStringConverter依赖
feat(tab): 添加ComboBoxUtils工具类,优化下拉框初始化
style: 移除无用导入和字段
2025-09-22 23:11:21 +08:00
8aac509e51 feat(vendor): 添加VendorTypeService基础类结构 2025-09-22 23:10:45 +08:00
35a15f4702 refactor(contract): 重构客户文件类型相关代码,统一命名和继承结构
- 将 CompanyCustomerFileType 重命名为 CustomerFileType
- 统一相关 VO 和 model 的继承结构,使用 BaseEnumEntity
- 更新所有引用点,保持代码一致性
- 优化表格单元格显示逻辑,使用专用单元格工厂
2025-09-22 17:25:24 +08:00
3c3003fdf3 feat(contract): 添加供应商和客户文件类型相关类
添加VendorFileTypeLocalVo、CustomerFileType枚举和CustomerFileTypeLocalVo类,用于处理文件类型分类和本地化展示
2025-09-22 17:25:03 +08:00
35b33d401b feat: 添加VendorGroupRequireFileTypeVo及相关服务功能
refactor: 重构多个服务类和方法,优化代码结构
fix: 修复PermissionVo中code字段更名为key的问题
docs: 更新create_vo.md文档,添加新创建的VO记录
perf: 优化WebSocketClientService中的session关闭逻辑
style: 清理无用导入和注释,统一代码格式
2025-09-21 23:08:34 +08:00
039d753bab refactor(vo): 重构VO对象结构,统一字段命名和接口实现
重构所有VO对象,统一字段命名规范,移除冗余字段,优化接口实现
新增Voable接口用于VO对象转换
调整BaseViewModel和ProjectBasedViewModel接口定义
更新相关服务和控制器以适应VO对象变更
2025-09-21 17:47:52 +08:00
07c3f39a95 feat(vo): 新增并更新多个VO类实现ContractBasedVo接口
新增CloudTycVo、CloudYuVo、ExtendVendorInfoVo等VO类
更新SalesOrderVo、PurchaseOrderVo等实现ContractBasedVo接口
统一布尔类型字段为boolean并设置默认值false
2025-09-18 09:19:45 +08:00
f113cd8c48 feat(contract): 添加ContractBasedVo接口作为合同相关VO的基类 2025-09-18 09:19:29 +08:00
2752828094 refactor(client): 重构银行和公司相关代码
- 更新了多个类中的导入语句,替换了模型类为对应的VO类
- 优化了部分方法的参数和返回类型,使用VO类替代模型类
- 重构了自动补全功能,使用统一的泛型方法
- 添加了缓存注解,提高了数据访问性能
- 优化了部分代码结构,提高了可维护性
2025-09-18 09:08:57 +08:00
d0645c33f1 feat(common): 新增多个 VO 类
- 新增了多个与公司、合同、项目、库存等相关的 VO 类
- 这些类用于数据传输和接口定义,提高了系统的可维护性和扩展性
- 使用了 Lombok 注解,简化了类的编写
2025-09-18 08:45:08 +08:00
588779d611 feat(contract): 新增合同管理相关 VO 类
- 新增 CompanyContractVo 类,用于公司合同信息的传输
- 新增 CompanyCustomerEntityVo 类,用于公司客户实体信息的传输
- 新增 CompanyCustomerEvaluationFormFileVo 类,用于公司客户评估表文件信息的传输
2025-09-18 02:03:21 +08:00
9ffaac39cb feat(common): 新增 BankVo、CompanyBlackReasonVo 和 CompanyContactVo 类
- 新增 BankVo 类,用于表示银行信息
- 新增 CompanyBlackReasonVo 类,用于表示公司黑名单原因
- 新增 CompanyContactVo 类,用于表示公司联系人信息
2025-09-18 02:03:01 +08:00
9ef90f98c1 feat(contract): 添加公司银行账户价值对象
新增 CompanyBankAccountVo 类,用于表示公司银行账户相关信息。该类包含以下属性:
- id: 主键
- companyId:公司 ID,关联 CompanyVo- bankId: 银行 ID,关联 BankVo
- account: 银行账号
- openingBank: 开户行
- description: 描述信息
- active: 账户状态

此添加为合同模块提供了新的数据传输对象,有助于管理和展示公司银行账户信息。
2025-09-18 02:01:35 +08:00
c0e4916474 refactor: 重构供应商文件类型枚举及相关服务
feat: 为多个服务添加缓存支持
fix: 修复WebSocket任务管理和远程调用异常处理
refactor: 重命名CompanyVendorFileType为VendorFileType
refactor: 优化项目成本导入任务实现
fix: 修复ContractTabSkinBase中的空指针问题
refactor: 统一WebSocket客户端任务调用接口
2025-09-17 22:28:17 +08:00
7560250036 feat(contract): 添加供应商文件类型相关类及服务实现
添加供应商文件类型枚举、模型、视图模型及服务类
实现供应商文件类型的缓存查询、保存和删除功能
2025-09-17 22:27:05 +08:00
c42ff7501d refactor: 重构WebSocket服务及相关实体类
重构WebSocket服务名称从WebSocketService改为WebSocketClientService,并实现Serializable接口
添加WebSocket常量定义和消息处理实现
优化实体类equals和hashCode方法
修复控制器路径和日志配置
添加查询服务和任务接口方法
2025-09-17 11:45:50 +08:00
30deb0a280 feat: 实现WebSocket通信框架及任务管理功能
新增WebSocket客户端和服务端通信框架,包括会话管理、心跳检测和自动重连机制
添加任务管理器用于处理WebSocket任务创建和执行
实现消息回调处理和错误处理机制
重构销售类型服务并添加缓存支持
移除旧的销售类型服务实现
2025-09-17 11:44:39 +08:00
ada539bebf refactor(controller): 重构控制器类名和路径,优化代码结构
feat(service): 新增QueryService接口实现,支持通用查询功能

docs(util): 完善ProxyUtils工具类的注释说明

fix(model): 修复CustomerCatalog实现IdentityEntity接口

style: 优化代码格式和导入顺序

perf(util): 提升FileUtils工具类功能,新增文件处理方法

chore: 更新README.md文件,补充UI资源路径说明

build: 更新pom.xml文件中的mainClass配置

test: 调整测试类命名和路径

ci: 更新CI配置文件中的类引用

refactor(controller): 重构表格单元格异步更新逻辑

docs(constant): 新增常量定义和注释

style: 统一代码风格和命名规范

refactor(service): 重构服务类继承关系

perf(controller): 优化表格数据加载性能

fix(service): 修复文件类型服务缓存问题

docs(model): 完善视图模型类注释

refactor(util): 重构文件工具类方法

style: 清理无用导入和代码

chore: 更新.gitignore文件

build: 调整项目依赖配置

refactor(controller): 重构控制器基类

perf(service): 优化查询服务性能

fix(controller): 修复表格数据加载异常

docs: 更新代码注释和文档

style: 统一代码缩进和格式
2025-09-13 01:02:43 +08:00
5edb44f619 feat: 添加新模块的基础类和主应用类
添加了多个基础服务类和视图模型类,包括SysConfViewModel、CompanyConstant等
实现了客户端和服务端的主应用类,包含启动配置和默认连接参数
2025-09-12 21:29:59 +08:00
98e48c520f feat(proxy): 实现代理对象初始化检查与懒加载机制
添加ProxyUtils工具类用于检查代理对象初始化状态
实现代理对象创建和标记初始化功能
添加ProxyObjectDeserializerModifier处理反序列化时的代理对象创建
修改WebSocketService错误消息字段从errorMsg改为message
实现ContractItemService.findAllByInventory方法
优化ContractService查询条件处理并添加缓存支持
重构InventoryTabSkinHistoryPrice的service获取方式
2025-09-12 16:00:45 +08:00
422994efcd refactor: 重构服务依赖注入和上下文管理
移除硬编码的服务注入,改为使用缓存机制动态获取Bean
优化上下文类结构,统一服务获取方式
添加PageContent类支持分页数据封装
实现异步数据加载功能
2025-09-12 12:20:15 +08:00
fc263288e4 feat: 添加合约文件类型服务及错误处理改进
refactor: 重构合约文件类型相关代码,优化错误处理逻辑

fix: 修复WebSocket会话未绑定用户时的错误处理

style: 调整代码格式,提高可读性

docs: 更新部分代码注释

test: 添加合约文件类型服务的测试用例

chore: 移除无用代码,清理项目结构
2025-09-12 00:12:51 +08:00
a1b87de7c0 feat: 添加日志配置和Logback依赖
refactor: 重构实体类equals和hashCode方法

fix: 修复WebSocketService消息发送逻辑

style: 格式化代码和优化导入

docs: 更新JacksonConfig日期序列化格式

test: 添加CompanyFilePathTableCell测试类

chore: 清理无用代码和注释
2025-09-11 19:44:28 +08:00
375de610ef refactor(client): 重构服务类继承关系并统一使用QueryService
重构所有服务类,使其继承自QueryService接口,统一数据查询逻辑。同时为服务类添加@Service注解,确保Spring容器管理。更新相关FXML文件的控制器路径,从manager.ds调整为controller目录结构。调整pom.xml版本号至0.0.84-SNAPSHOT。新增MessageNotitfication和SimpleMessage消息类,提供基础消息结构支持。
2025-09-11 00:06:22 +08:00
23e1f98ae5 feat: 实现基于JSON的登录API和安全认证
refactor: 重构登录逻辑和会话管理

fix: 修复会话ID类型和WebSocket连接问题

build: 更新项目版本号和添加Servlet API依赖

style: 清理无用导入和注释代码
2025-09-08 17:46:48 +08:00
3b90db0450 refactor: 移除Hibernate依赖并重构代理对象初始化检查逻辑
feat(controller): 新增多个任务类用于合同和客户相关操作
feat(service): 新增ProxyUtils工具类替代Hibernate.isInitialized检查
refactor(controller): 重构多个控制器和皮肤类,使用ProxyUtils替代Hibernate
refactor(service): 重构服务类,移除Hibernate依赖并优化方法实现
fix(controller): 修复表格单元格初始化逻辑,确保代理对象正确加载
chore: 更新项目版本号至0.0.58-SNAPSHOT
docs: 添加MyProperties类用于管理下载路径配置
2025-09-06 17:22:12 +08:00
effd7b103c feat: 新增多个服务类及工具类,重构部分代码结构
重构服务类结构,将分散的服务统一整合到service包下
新增ProjectConstant常量类及多个实体服务类
添加SecurityUtils安全工具类和BeanCacher工具类
优化部分UI控件和转换器的实现
2025-09-06 13:43:52 +08:00
0e444508ff feat: 重构员工控制器并优化JSON序列化配置
refactor(EmployeeController): 重命名EmployyeController为EmployeeController并优化代码结构
feat(EmployeeController): 添加@JsonIgnoreProperties注解解决循环引用问题
feat(JacksonConfig): 新增Jackson配置类处理Hibernate代理和循环引用
fix(EmployeeService): 修复缓存注解格式问题
feat(Employee): 添加@JsonIgnoreProperties注解忽略可能导致循环引用的字段
feat(EmployeeRole): 添加@JsonIgnore注解忽略关联字段
fix(application.properties): 调整Redis缓存配置和错误处理设置
refactor(IndexController): 移除错误处理方法
feat(GlobalExceptionHandler): 新增全局异常处理类
refactor(SecurityConfig): 优化安全配置并启用方法级安全注解
refactor(AbstractCtx): 优化日期时间处理方法
build: 更新项目版本至0.0.53-SNAPSHOT
2025-09-04 16:06:47 +08:00
acb63116d5 docs: 优化README.md的格式和可读性
调整项目介绍中的模块说明格式,使用更清晰的列表展示方式
2025-09-03 23:11:54 +08:00
72f8e2e209 Merge branch 'main' of http://10.84.210.110/songqq/contract-manager 2025-09-03 23:09:48 +08:00
b927f9d572 build: 添加FixPackageNames相关编译文件
添加FixPackageNames.class及其内部类FixPackageNames$1.class的编译输出文件
2025-09-03 23:09:40 +08:00
a2f5e4864b 拆分模块 2025-09-03 20:56:44 +08:00
08cc2c29a5 拆分模块 2025-09-03 20:48:39 +08:00
7d684a5006 删除 null 2025-08-31 23:10:08 +08:00
8139a45f06 更新 docs/异步任务监控实现方案.md 2025-08-31 23:09:54 +08:00
cca51c6fcc feat(project): 新增项目资金计划功能 #2
添加项目资金计划模块,包括以下内容:
- 新增项目资金计划实体类及相关数据库表结构
- 实现资金计划Repository和服务层
- 添加资金计划Tab页及FXML界面
- 实现从合同付款计划同步资金计划功能
- 添加资金计划表格展示及更新操作
2025-08-28 19:54:20 +08:00
1514cb0f9f refactor(CloudTycService): 优化配置获取方式并移除多余空行
将SysConfRepository替换为SysConfService以获取配置参数,提升代码可维护性
清理类中多余的空行,保持代码整洁
2025-08-28 16:07:03 +08:00
cf73769ef2 refactor(配置管理): 重构配置绑定与保存逻辑
将配置绑定逻辑抽象到StringConfig类中,统一处理配置的保存与控件绑定
提取配置键常量到对应服务类中,提高代码可维护性
使用LocalDateTime替代Instant处理时间字段
简化SysConfRepository继承结构,使用自定义基础仓库
优化SysConfWindowController的配置管理逻辑,减少重复代码
2025-08-28 15:55:24 +08:00
c793c0925e refactor(配置管理): 重构配置绑定组件结构并添加布尔类型支持
将原有配置绑定组件重构为泛型抽象基类,统一处理不同类型配置的绑定逻辑。新增BooleanConfig支持布尔类型配置,并优化了LocalDateTimeConfig的转换器处理。

重构后的AbstractConfigBounder提供通用属性绑定和变更处理,子类只需实现特定类型的双向绑定逻辑。同时调整了相关UI界面,添加了布尔配置开关控件。
2025-08-28 15:09:54 +08:00
c69d3f1af2 refactor(ui): 重构BaseController及相关组件,优化代码结构和性能
重构BaseController,移除冗余属性,引入bean缓存机制
新增LocalDateTimeConfig类处理日期时间配置
优化AbstEntityManagerSkin的分页和表格数据处理逻辑
调整ContractTabSkinBase的依赖注入方式,使用缓存bean
统一日期、数字和货币的格式化处理,使用CurrentEmployee的配置
2025-08-27 19:36:30 +08:00
f810532824 fix: 将 AsyncUpdateTableCell 的日志级别从 debug 调整为 warn
修改日志级别以减少不必要的调试信息输出,仅保留警告及以上级别的日志
2025-08-27 14:44:45 +08:00
fb28bac53a refactor(ui): 优化表格数据加载和异步单元格更新逻辑
修复表格高度调整时频繁触发数据加载的问题,增加调整阈值判断
改进异步单元格更新逻辑,增加取消机制和状态检查
重构常量命名,使用更清晰的KEY_SYNC_BY前缀
添加日志记录和注释说明
2025-08-27 14:43:55 +08:00
9ff84ebe8a refactor(u8配置): 重构配置管理相关代码
将配置管理相关代码重构为ConfigBounder接口及其实现类,提取公共逻辑到AbstractConfigBounder基类
修复公司创建日期配置的显示问题,使用更直观的中文描述
将合同同步相关配置常量集中到ContractCtx中管理
2025-08-25 19:40:07 +08:00
6711657663 feat(u8): 添加用友U8配置窗口和数据迁移功能
新增用友U8配置窗口,支持日期和文本配置项的编辑与保存。实现从CloudInfo到CloudYu的数据迁移任务,优化任务执行方式。重构多个同步任务类继承Tasker基类,统一任务处理逻辑。扩展YongYouU8Service功能,添加配置相关接口。调整UI布局和菜单项,增加配置入口。

refactor: 重命名CompanyTableCell为EmployeeRoleTableCell

style: 清理无用导入和格式化代码

fix: 修复ContractTypeSyncTask中分类和方向字段设置错误
2025-08-25 18:57:17 +08:00
17e326b35c refactor(ui): 重命名并移动EvaluationFileTableCell为CompanyTableCell
将EvaluationFileTableCell从project.controller包移动到table.cell包,并重命名为CompanyTableCell。同时修改其实现以使用CompanyService而非CompanyCustomerFileService,使其更符合新的业务需求。
2025-08-25 18:56:55 +08:00
danyz
fa25130c9f Merge branch 'main' of http://10.84.210.110/songqq/contract-manager into main 2025-08-25 00:41:45 +08:00
danyz
b0b67b5d7f feat(任务监控): 添加Executor信息监控面板并重构界面
重构任务监控界面布局,将演示任务功能移至监控窗口工具栏
新增Executor信息监控面板,显示线程池详细状态信息
移除主界面中的演示任务按钮,更新项目版本号
2025-08-25 00:41:34 +08:00
1304 changed files with 42336 additions and 22191 deletions

View File

@@ -1,12 +1,22 @@
# server 模块
Java 21 Java 21
Spring Boot 3.3.7 Spring Boot 3.3.7
Spring Data JPA 3.3.7 Spring Data JPA 3.3.7
JavaFX 21
ControlsFX 11.1.2
MySQL 8.0.33 MySQL 8.0.33
Lombok 1.18.32 Lombok 1.18.32
POI 5.2.5 POI 5.2.5
PDFBox 3.0.1 PDFBox 3.0.1
Redis
# client 模块
Java 21
JavaFX 21
ControlsFX 11.1.2
Lombok 1.18.32
caffeine 3.1.8
.fxml 界面UI, /client/src/main/resources/ui/ 目录下
websocket 与 server 模块通信
ignore: ignore:
- .idea - .idea

View File

@@ -1,33 +1,13 @@
## 项目改进与优化分析报告 # 项目介绍
### 1. 同步任务与调度优化
- 调度策略优化 :各同步任务(如 ContractSyncTask 、 VendorSyncTask )使用不同的调度间隔和策略,建议统一调度配置,避免重复执行和资源浪费 分模块:
- 增量同步实现 多数同步任务缺乏断点续传机制建议添加基于最后同步ID或时间戳的增量同步功能 - common:
- 任务依赖管理 :部分任务存在隐式依赖关系(如 OldVersionSyncVendorTask 中的多步骤执行),建议引入任务依赖管理机制 公共模块,包含实体类、公共的类、枚举、异常、工具类等
### 2. 线程池与异步处理 - server:
- 线程池配置 :当前项目未明确配置线程池参数(核心线程数、最大线程数等),建议在 SpringApp 中添加显式线程池配置 服务端模块包含服务端的代码依赖common模块
- 线程池隔离 不同类型的任务IO密集型、CPU密集型应使用不同线程池避免资源竞争 - client:
- 异步任务监控 :添加异步任务执行状态监控和超时处理机制,避免任务长时间阻塞 客户端模块包含客户端的代码依赖common模块
### 3. 缓存机制优化 UI 的fxml文件在 /client/src/main/resources/ui/
- 缓存策略细化 :当前缓存配置较为简单( CaffeineCacheManager ),建议为不同类型数据配置差异化缓存策略(过期时间、最大容量等)
- 缓存一致性 :修复 CloudRkService 中缓存更新问题(注释中提到的"这个可以无法更新缓存"
- 缓存预热 :添加关键数据缓存预热机制,提高系统启动后响应速度
### 4. 依赖注入与懒加载
- 依赖注入规范化 :减少 SpringApp.getBean() 手动获取bean的方式推广构造函数注入或字段注入
- 懒加载优化 :充分利用 @Lazy 注解和 BootstrapMode.LAZY 配置,优化应用启动性能
- 服务解耦 :继续推进服务拆分工作(如之前的 ContractService 拆分为专用服务),减少服务间耦合
### 5. 异常处理与重试机制
- 异常处理统一 :规范异常处理策略,确保所有异常都被适当记录和处理
- 重试机制添加 :为网络请求和数据库操作添加重试机制(如使用 Spring Retry
- 熔断降级 对外部系统调用如用友U8接口添加熔断降级机制提高系统稳定性
### 6. 数据库操作优化
- 批量操作引入 对大量数据的CRUD操作建议使用批量处理API提高性能
- 查询优化 :添加适当索引,优化复杂查询,避免全表扫描
- 连接池配置 :优化 HikariDataSource 配置参数(如连接池大小、超时时间等)
### 7. 代码质量与维护性
- 重复代码消除 :提取同步任务中的共同逻辑(如进度更新、异常处理)为抽象基类
- 注释完善 :补充关键类和方法的文档注释,特别是复杂业务逻辑和优化点
- 技术债务清理 解决代码中的TODO项如 CloudRkService 中的缓存更新问题)
### 8. 配置管理优化
- 配置集中管理 :将分散在代码中的配置项(如同步间隔、批处理大小)集中到配置文件
- 动态配置支持 :添加动态配置更新机制,避免重启应用
以上优化点已按优先级和影响范围排序,建议逐步实施。实施过程中应注意性能测试和兼容性验证,确保优化不会引入新问题。

126
client/pom.xml Normal file
View File

@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.ecep.contract</groupId>
<artifactId>Contract-Manager</artifactId>
<version>0.0.84-SNAPSHOT</version>
</parent>
<groupId>com.ecep.contract</groupId>
<artifactId>client</artifactId>
<version>0.0.84-SNAPSHOT</version>
<properties>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.ecep.contract</groupId>
<artifactId>common</artifactId>
<version>0.0.84-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- JavaFX -->
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-web</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>org.controlsfx</groupId>
<artifactId>controlsfx</artifactId>
<version>11.2.0</version>
</dependency>
<!-- Caffeine Cache -->
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>3.1.8</version>
</dependency>
<!-- Spring Context Support for CaffeineCacheManager -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
<version>3.3.7</version>
</dependency>
<!-- OkHttp -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.12.0</version>
</dependency>
<!-- Logback 日志实现 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.14</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.8</version>
<configuration>
<mainClass>com.ecep.contract.ClientV2</mainClass>
<launcher>app</launcher>
<jlinkZipName>app-jlink</jlinkZipName>
<jlinkImageName>app-jlink-image</jlinkImageName>
<noManPages>true</noManPages>
<stripDebug>true</stripDebug>
<compress>2</compress>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId>
<version>2.16.2</version>
<executions>
<execution>
<inherited>true</inherited>
<id>increment-version</id>
<phase>install</phase>
<goals>
<goal>set</goal>
</goals>
<configuration>
<generateBackupPoms>false</generateBackupPoms>
<processAllModules>true</processAllModules>
<!-- <newVersion>${project.version}</newVersion> -->
<nextSnapshot>true</nextSnapshot>
<nextSnapshotIndexToIncrement>3</nextSnapshotIndexToIncrement>
<!-- <removeSnapshot>true</removeSnapshot>-->
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,14 @@
package com.ecep.contract;
import javafx.application.Application;
/**
* Created by Administrator on 2017/4/16.
*/
public class ClientV2 {
public static void main(String[] args) {
Application.launch(Desktop.class, args);
}
public static final String DEFAULT_HOST = "10.84.209.154";
}

View File

@@ -1,27 +1,4 @@
package com.ecep.contract.manager; package com.ecep.contract;
import com.ecep.contract.manager.ds.other.controller.LoginWidowController;
import com.ecep.contract.manager.ui.BaseController;
import com.ecep.contract.manager.ui.MessageHolder;
import com.ecep.contract.manager.ui.task.TaskMonitorCenter;
import com.ecep.contract.manager.util.UITools;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import lombok.Getter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
@@ -29,8 +6,42 @@ import java.io.IOException;
import java.net.URL; import java.net.URL;
import java.util.List; import java.util.List;
import java.util.Properties; import java.util.Properties;
import java.util.concurrent.*; import java.util.concurrent.CompletableFuture;
import java.util.logging.Level; import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import com.ecep.contract.controller.BaseController;
import com.ecep.contract.controller.HomeWindowController;
import com.ecep.contract.controller.OkHttpLoginController;
import com.ecep.contract.task.TaskMonitorCenter;
import com.ecep.contract.util.HibernateProxyUtils;
import com.ecep.contract.util.TextMessageHolder;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.CurrentEmployee;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.SimpleStringProperty;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import lombok.Getter;
import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
/** /**
* JavaFx 应用程序 * JavaFx 应用程序
@@ -58,9 +69,11 @@ public class Desktop extends Application {
private ScheduledExecutorService scheduledExecutorService = null; private ScheduledExecutorService scheduledExecutorService = null;
private final TaskMonitorCenter taskMonitorCenter = new TaskMonitorCenter(); private final TaskMonitorCenter taskMonitorCenter = new TaskMonitorCenter();
private final SimpleIntegerProperty sessionId = new SimpleIntegerProperty(0); private final SimpleStringProperty sessionId = new SimpleStringProperty("");
@Getter @Getter
private final CurrentEmployee activeEmployee = new CurrentEmployee(); private final CurrentEmployee activeEmployee = new CurrentEmployee();
@Getter
private OkHttpClient httpClient;
public void setActiveEmployeeId(int activeEmployeeId) { public void setActiveEmployeeId(int activeEmployeeId) {
activeEmployee.getId().set(activeEmployeeId); activeEmployee.getId().set(activeEmployeeId);
@@ -70,11 +83,11 @@ public class Desktop extends Application {
return activeEmployee.getId().get(); return activeEmployee.getId().get();
} }
public int getSessionId() { public String getSessionId() {
return sessionId.get(); return sessionId.get();
} }
public void setSessionId(int sessionId) { public void setSessionId(String sessionId) {
this.sessionId.set(sessionId); this.sessionId.set(sessionId);
} }
@@ -122,8 +135,12 @@ public class Desktop extends Application {
} }
} }
public CompletableFuture<Void> runAsync(Runnable runnable) {
return CompletableFuture.runAsync(runnable, getExecutorService());
}
private void startSpringApp(Stage primaryStage, Parent root, FXMLLoader loader) { private void startSpringApp(Stage primaryStage, Parent root, FXMLLoader loader) {
System.out.println("Desktop.startSpringApp"); logger.debug("startSpringApp");
// 更新窗口标题 // 更新窗口标题
Node titleNode = root.lookup("#title"); Node titleNode = root.lookup("#title");
if (titleNode != null) { if (titleNode != null) {
@@ -138,34 +155,26 @@ public class Desktop extends Application {
ScrollPane logPane = (ScrollPane) root.lookup("#logPane"); ScrollPane logPane = (ScrollPane) root.lookup("#logPane");
logBox.getChildren().clear(); logBox.getChildren().clear();
MessageHolder holder = (level, message) -> { TextMessageHolder holder = new TextMessageHolder() {
Text text = new Text(message); @Override
if (Level.WARNING == level) { // warning public void addTextMessage(Text text) {
text.setFill(Color.YELLOW);
} else if (Level.SEVERE == level) {// error
text.setFill(Color.RED);
} else if (Level.FINE == level) { // debug
text.setFill(Color.GRAY);
} else {
text.setFill(Color.WHITE);
}
Platform.runLater(() -> { Platform.runLater(() -> {
logBox.getChildren().add(text); logBox.getChildren().add(text);
logPane.layout(); logPane.layout();
logPane.setVvalue(1.0); logPane.setVvalue(1.0);
}); });
}
}; };
holder.info("启动中,请稍后..."); holder.info("启动中,请稍后...");
CompletableFuture.runAsync(() -> { runAsync(() -> {
try { try {
// //
holder.info("读取配置文件..."); holder.info("读取配置文件...");
Properties properties = new Properties(); Properties properties = new Properties();
File configFile = new File("config.properties"); File configFile = new File("config.properties");
if (configFile.exists()) { if (configFile.exists()) {
holder.debug("读取配置文件 " + configFile.getName() + "..."); holder.info("读取配置文件 " + configFile.getAbsolutePath() + "...");
try (FileInputStream input = new FileInputStream(configFile)) { try (FileInputStream input = new FileInputStream(configFile)) {
properties.load(input); properties.load(input);
holder.info("配置文件读取成功."); holder.info("配置文件读取成功.");
@@ -174,9 +183,12 @@ public class Desktop extends Application {
logger.error(e.getMessage(), e); logger.error(e.getMessage(), e);
return; return;
} }
} else {
logger.warn("配置文件{}不存在", configFile.getAbsolutePath());
} }
HibernateProxyUtils.useProxy(false);
CompletableFuture.runAsync(() -> { runAsync(() -> {
SpringApp.launch(properties, holder); SpringApp.launch(properties, holder);
ConfigurableListableBeanFactory beanFactory = SpringApp.context.getBeanFactory(); ConfigurableListableBeanFactory beanFactory = SpringApp.context.getBeanFactory();
@@ -185,16 +197,35 @@ public class Desktop extends Application {
}); });
try { try {
LoginWidowController controller = new LoginWidowController(); initHttpClient();
OkHttpLoginController controller = new OkHttpLoginController();
controller.setHttpClient(this.httpClient);
controller.setHolder(holder); controller.setHolder(holder);
controller.setPrimaryStage(primaryStage); controller.setPrimaryStage(primaryStage);
controller.setProperties(properties); controller.setProperties(properties);
while (true) { while (true) {
controller.tryLogin(); try {
break; controller.tryLogin().get();
holder.info("登录成功");
try {
while (!SpringApp.isRunning()) {
System.out.println("等待启动");
Thread.sleep(1000);
}
} catch (InterruptedException ex) {
throw new RuntimeException(ex);
}
// 必须要等待启动成功后才能关闭主场景否则进程结束程序退出
HomeWindowController.show().thenRun(() -> Platform.runLater(primaryStage::close));
break;
} catch (Exception ex) {
holder.error(ex.getMessage());
Thread.sleep(3000);
} }
if (logger.isDebugEnabled()) {
logger.debug("login in");
} }
} catch (Exception e) { } catch (Exception e) {
holder.error("登录失败:" + e.getMessage()); holder.error("登录失败:" + e.getMessage());
@@ -206,6 +237,27 @@ public class Desktop extends Application {
} }
}); });
System.out.println("Desktop.startSpringApp."); System.out.println("Desktop.startSpringApp.");
}
private void initHttpClient() {
this.httpClient = new OkHttpClient().newBuilder().cookieJar(new CookieJar() {
private final List<Cookie> cookies = new java.util.ArrayList<>();
@Override
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
// 保存服务器返回的Cookie如JSESSIONID
this.cookies.addAll(cookies);
System.out.println("保存Cookie: " + cookies);
}
@Override
public List<Cookie> loadForRequest(HttpUrl url) {
// 请求时自动携带Cookie
return cookies;
}
}).build();
} }
@Override @Override
@@ -253,5 +305,4 @@ public class Desktop extends Application {
} }
scheduledExecutorService.close(); scheduledExecutorService.close();
} }
} }

View File

@@ -1,4 +1,4 @@
package com.ecep.contract.manager.util; package com.ecep.contract;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@@ -6,8 +6,6 @@ import java.util.function.Consumer;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import com.ecep.contract.manager.Desktop;
public class DesktopUtils { public class DesktopUtils {
/** /**

View File

@@ -1,4 +1,4 @@
package com.ecep.contract.manager; package com.ecep.contract;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;

View File

@@ -1,4 +1,4 @@
package com.ecep.contract.manager; package com.ecep.contract;
import java.time.Duration; import java.time.Duration;
import java.time.Instant; import java.time.Instant;
@@ -25,7 +25,6 @@ import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.caffeine.CaffeineCacheManager; import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.event.ContextClosedEvent; import org.springframework.context.event.ContextClosedEvent;
import org.springframework.context.event.EventListener; import org.springframework.context.event.EventListener;
@@ -36,11 +35,7 @@ import org.springframework.core.metrics.StartupStep;
import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.EnableScheduling;
import com.ecep.contract.manager.cloud.CloudRepositoriesConfig; import com.ecep.contract.util.UITools;
import com.ecep.contract.manager.ds.DsRepositoriesConfig;
import com.ecep.contract.manager.ui.MessageHolder;
import com.ecep.contract.manager.util.MyDateTimeUtils;
import com.ecep.contract.manager.util.UITools;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
@@ -50,15 +45,20 @@ import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
@SpringBootApplication(exclude = { org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration.class }) @SpringBootApplication(exclude = {
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration.class,
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration.class,
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration.class,
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration.class
})
@EnableScheduling @EnableScheduling
@EnableAsync @EnableAsync
@EnableCaching @EnableCaching
public class SpringApp { public class SpringApp {
private static final Logger logger = LoggerFactory.getLogger(SpringApp.class); private static final Logger logger = LoggerFactory.getLogger(SpringApp.class);
static SpringApplication application; public static SpringApplication application;
static ConfigurableApplicationContext context; public static ConfigurableApplicationContext context;
public static <T> T getBean(Class<T> requiredType) throws BeansException { public static <T> T getBean(Class<T> requiredType) throws BeansException {
return context.getBean(requiredType); return context.getBean(requiredType);
@@ -92,11 +92,6 @@ public class SpringApp {
environment.getPropertySources().addLast(new PropertiesPropertySource("dynamicProperties", properties)); environment.getPropertySources().addLast(new PropertiesPropertySource("dynamicProperties", properties));
// app.getBeanFactory().registerSingleton("dataSource", dataSource()); // app.getBeanFactory().registerSingleton("dataSource", dataSource());
logger.debug("app = {}", app); logger.debug("app = {}", app);
if (app instanceof AnnotationConfigApplicationContext ctx) {
ctx.register(DsRepositoriesConfig.class);
ctx.register(CloudRepositoriesConfig.class);
}
}); });
startup.start(""); startup.start("");
@@ -108,7 +103,7 @@ public class SpringApp {
CompletableFuture.runAsync(() -> { CompletableFuture.runAsync(() -> {
// 在这里调用 startup 性能分析 // 在这里调用 startup 性能分析
analyzeStartupPerformance(startup); analyzeStartupPerformance(startup);
}); }, Desktop.instance.getExecutorService());
} }
/** /**
@@ -242,14 +237,18 @@ public class SpringApp {
public ObjectMapper objectMapper() { public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper(); ObjectMapper objectMapper = new ObjectMapper();
JavaTimeModule javaTimeModule = new JavaTimeModule(); JavaTimeModule javaTimeModule = new JavaTimeModule();
// LocalDate
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ISO_LOCAL_DATE)); javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ISO_LOCAL_DATE));
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(
DateTimeFormatter.ofPattern(MyDateTimeUtils.DEFAULT_DATETIME_FORMAT_PATTERN)));
javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ISO_LOCAL_DATE)); javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ISO_LOCAL_DATE));
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer( // LocalTime
DateTimeFormatter.ofPattern(MyDateTimeUtils.DEFAULT_DATETIME_FORMAT_PATTERN))); javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ISO_LOCAL_TIME));
javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ISO_LOCAL_TIME)); javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ISO_LOCAL_TIME));
// LocalDateTime
javaTimeModule.addSerializer(LocalDateTime.class,
new LocalDateTimeSerializer(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
javaTimeModule.addDeserializer(LocalDateTime.class,
new LocalDateTimeDeserializer(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
objectMapper.registerModule(javaTimeModule); objectMapper.registerModule(javaTimeModule);
return objectMapper; return objectMapper;
} }

View File

@@ -0,0 +1,361 @@
package com.ecep.contract;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ecep.contract.constant.WebSocketConstant;
import com.ecep.contract.controller.OkHttpLoginController;
import com.ecep.contract.msg.SimpleMessage;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import javafx.application.Platform;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import lombok.Getter;
import lombok.Setter;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import okio.ByteString;
/**
* WebSocket消息服务
* 提供向服务器端发送WebSocket消息的功能
*/
@Service
public class WebSocketClientService {
private static final Logger logger = LoggerFactory.getLogger(WebSocketClientService.class);
@Getter
@Setter
private WebSocket webSocket;
@Getter
@Autowired
private ObjectMapper objectMapper;
private static final int RECONNECT_DELAY_MS = 5000; // 重连延迟时间(毫秒)
private static final int HEARTBEAT_INTERVAL_MS = 30000; // 心跳间隔时间(毫秒)
@Getter
@Setter
private long readTimeout = 30000;
private String webSocketUrl = "ws://localhost:8080/ws";
private boolean isActive = false; // 标记连接是否活跃
private ScheduledFuture<?> heartbeatTask; // 心跳任务
private ScheduledFuture<?> reconnectFuture; // 修改类型为CompletableFuture<Void>
private SimpleBooleanProperty online = new SimpleBooleanProperty(false);
private SimpleStringProperty message = new SimpleStringProperty("");
// 存储所有活跃的WebSocket会话
private final Map<String, WebSocketClientSession> sessions = Collections.synchronizedMap(new HashMap<>());
// 存储所有活跃的WebSocket会话
private final Map<String, CompletableFuture<JsonNode>> callbacks = Collections.synchronizedMap(new HashMap<>());
WebSocketListener listener = new WebSocketListener() {
@Override
public void onOpen(WebSocket webSocket, Response response) {
Platform.runLater(() -> {
online.setValue(true);
message.setValue("已连接");
});
startHeartbeat(); // 启动心跳
}
@Override
public void onMessage(WebSocket webSocket, String text) {
// 处理收到的文本消息
logger.debug("收到WebSocket消息: {}", text);
// 这里可以根据需要处理从服务器接收的数据
if ("pong".equals(text)) {
// 收到pong响应说明连接正常
logger.debug("收到心跳响应");
return;
}
try {
JsonNode node = objectMapper.readTree(text);
if (node.has(WebSocketConstant.MESSAGE_ID_FIELD_NAME)) {
String messageId = node.get(WebSocketConstant.MESSAGE_ID_FIELD_NAME).asText();
CompletableFuture<JsonNode> future = callbacks.remove(messageId);
if (future != null) {
onCallbackMessage(future, node);
} else {
logger.error("未找到对应的回调future: {}", messageId);
}
return;
}
if (node.has(WebSocketConstant.SESSION_ID_FIELD_NAME)) {
String sessionId = node.get(WebSocketConstant.SESSION_ID_FIELD_NAME).asText();
WebSocketClientSession session = sessions.get(sessionId);
if (session != null) {
try {
session.onMessage(node);
} catch (Exception e) {
session.updateMessage(java.util.logging.Level.SEVERE, "会话异常: " + e.getMessage());
}
}
return;
}
if (node.has(WebSocketConstant.ERROR_CODE_FIELD_NAME)) {
int errorCode = node.get(WebSocketConstant.ERROR_CODE_FIELD_NAME).asInt();
String errorMsg = node.get(WebSocketConstant.MESSAGE_FIELD_NAME).asText();
logger.error("收到错误消息: 错误码={}, 错误信息={}", errorCode, errorMsg);
if (errorCode == WebSocketConstant.ERROR_CODE_UNAUTHORIZED) {
// 处理未授权错误,重新登录
OkHttpLoginController controller = new OkHttpLoginController();
controller.tryLogin();
// 需要把窗口顶置
}
return;
}
} catch (Exception e) {
logger.error("处理WebSocket消息失败: {}", e.getMessage(), e);
}
}
@Override
public void onMessage(WebSocket webSocket, ByteString bytes) {
// 处理收到的二进制消息
logger.debug("收到二进制WebSocket消息长度: " + bytes.size());
}
@Override
public void onClosing(WebSocket webSocket, int code, String reason) {
logger.debug("WebSocket连接正在关闭: 代码=" + code + ", 原因=" + reason);
stopHeartbeat(); // 停止心跳
}
@Override
public void onClosed(WebSocket webSocket, int code, String reason) {
logger.debug("WebSocket连接已关闭: 代码=" + code + ", 原因=" + reason);
stopHeartbeat(); // 停止心跳
// 处理重连逻辑
scheduleReconnect();
}
@Override
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
logger.error("WebSocket连接失败: " + t.getMessage() + ", response=" + response, t);
Platform.runLater(() -> {
online.setValue(false);
message.set("连接失败: " + t.getMessage());
});
stopHeartbeat(); // 停止心跳
// 处理重连逻辑
scheduleReconnect();
}
};
private void onCallbackMessage(CompletableFuture<JsonNode> future, JsonNode node) {
if (node.has(WebSocketConstant.SUCCESS_FIELD_VALUE)) {
if (!node.get(WebSocketConstant.SUCCESS_FIELD_VALUE).asBoolean()) {
future.completeExceptionally(
new RuntimeException(
"请求失败:来自服务器的消息=" + node.get(WebSocketConstant.MESSAGE_FIELD_NAME).asText()));
return;
}
}
// 使用具体类型后,这里不会再出现类型不匹配的错误
if (node.has("data")) {
future.complete(node.get("data"));
} else {
future.complete(node);
}
}
public void send(String string) {
if (webSocket != null && webSocket.send(string)) {
logger.debug("send message success:{}", string);
} else if (webSocket == null) {
logger.warn("Failed to send message: WebSocket is not initialized");
}
}
public void send(Object message) throws JsonProcessingException {
send(objectMapper.writeValueAsString(message));
}
public CompletableFuture<JsonNode> send(SimpleMessage msg) {
CompletableFuture<JsonNode> future = new CompletableFuture<>();
try {
if (webSocket == null) {
throw new IllegalStateException("WebSocket is not initialized");
}
if (!online.get()) {
throw new IllegalStateException("WebSocket is not online");
}
String json = objectMapper.writeValueAsString(msg);
callbacks.put(msg.getMessageId(), future);
if (webSocket.send(json)) {
logger.debug("send message success:{}", json);
} else {
if (isActive) {
future.completeExceptionally(new RuntimeException("Failed to send WebSocket message"));
} else {
future.completeExceptionally(new RuntimeException("WebSocket is not active"));
}
}
} catch (Exception e) {
logger.error("Failed to send WebSocket message: {}", e.getMessage());
future.completeExceptionally(e);
}
return future;
}
public CompletableFuture<JsonNode> invoke(String service, String method, Object... params) {
SimpleMessage msg = new SimpleMessage();
msg.setService(service);
msg.setMethod(method);
msg.setArguments(params);
return send(msg).orTimeout(getReadTimeout(), TimeUnit.MILLISECONDS);
}
public void initWebSocket() {
isActive = true;
OkHttpClient httpClient = Desktop.instance.getHttpClient();
try {
// 构建WebSocket请求包含认证信息
Request request = new Request.Builder()
.url(webSocketUrl)
.build();
webSocket = httpClient.newWebSocket(request, listener);
} catch (Exception e) {
logger.error("建立WebSocket连接失败: " + e.getMessage());
Platform.runLater(() -> {
online.setValue(false);
message.set("连接失败: " + e.getMessage());
});
// 处理重连逻辑
scheduleReconnect();
}
}
/**
* 启动心跳任务定期发送ping消息保持连接
*/
private void startHeartbeat() {
// 先停止可能存在的心跳任务
stopHeartbeat();
ScheduledExecutorService executorService = Desktop.instance.getExecutorService();
heartbeatTask = executorService.scheduleAtFixedRate(this::heartbeat, RECONNECT_DELAY_MS, HEARTBEAT_INTERVAL_MS,
TimeUnit.MILLISECONDS);
}
void heartbeat() {
if (!isActive) {
return;
}
try {
if (webSocket != null) {
logger.debug("发送心跳 ping");
webSocket.send("ping");
}
} catch (Exception e) {
logger.error("发送心跳失败: {}", e.getMessage());
}
}
/**
* 停止心跳任务
*/
private void stopHeartbeat() {
if (heartbeatTask != null && !heartbeatTask.isCancelled()) {
heartbeatTask.cancel(true);
heartbeatTask = null;
}
}
/**
* 安排重连任务
*/
private void scheduleReconnect() {
if (!isActive) {
return; // 如果连接已被主动关闭,则不再重连
}
// 取消之前可能存在的重连任务
if (reconnectFuture != null && !reconnectFuture.isDone()) {
reconnectFuture.cancel(true);
}
// 创建新的重连任务s
logger.info("计划在 {} 毫秒后尝试重连WebSocket", RECONNECT_DELAY_MS);
reconnectFuture = Desktop.instance.getExecutorService().schedule(() -> {
if (isActive) {
logger.info("尝试重新连接WebSocket");
Platform.runLater(() -> {
online.setValue(false);
message.set("正在重新连接WebSocket...");
});
initWebSocket();
}
}, RECONNECT_DELAY_MS, TimeUnit.MILLISECONDS);
}
/**
* 关闭WebSocket连接
*/
public void closeWebSocket() {
isActive = false;
stopHeartbeat();
if (reconnectFuture != null && !reconnectFuture.isDone()) {
reconnectFuture.cancel(false);
reconnectFuture = null;
}
if (webSocket != null) {
webSocket.close(1000, "主动关闭连接");
webSocket = null;
}
}
public StringProperty getMessageProperty() {
return message;
}
public BooleanProperty getOnlineProperty() {
return online;
}
public void withSession(Consumer<WebSocketClientSession> sessionConsumer) {
WebSocketClientSession session = createSession();
try {
sessionConsumer.accept(session);
} finally {
// closeSession(session);
}
}
public void closeSession(WebSocketClientSession session) {
if (session != null) {
sessions.remove(session.getSessionId());
// session.close();
}
}
public WebSocketClientSession createSession() {
WebSocketClientSession session = new WebSocketClientSession(this);
sessions.put(session.getSessionId(), session);
return session;
}
}

View File

@@ -0,0 +1,116 @@
package com.ecep.contract;
import com.ecep.contract.constant.WebSocketConstant;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.Getter;
import org.springframework.beans.BeanUtils;
import java.beans.PropertyDescriptor;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Level;
public class WebSocketClientSession {
@Getter
private String sessionId = UUID.randomUUID().toString();
private WebSocketClientTasker tasker;
private final WebSocketClientService webSocketService;
public WebSocketClientSession(WebSocketClientService webSocketService) {
this.webSocketService = webSocketService;
}
public void close() {
webSocketService.closeSession(this);
}
public void submitTask(WebSocketClientTasker tasker, Locale locale, Object... args) throws JsonProcessingException {
this.tasker = tasker;
send("createTask", tasker.getTaskName(), locale.toLanguageTag(), args);
}
public void send(String type, Object... args) throws JsonProcessingException {
Map<String, Object> arguments = Map.of(
WebSocketConstant.SESSION_ID_FIELD_NAME, getSessionId(),
"type", type,
WebSocketConstant.ARGUMENTS_FIELD_NAME, args);
webSocketService.send(arguments);
}
public void onMessage(JsonNode node) {
if (node.has("type")) {
String type = node.get("type").asText();
JsonNode args = node.get(WebSocketConstant.ARGUMENTS_FIELD_NAME);
if (type.equals("message")) {
handleAsMessage(args);
} else if (type.equals("title")) {
handleAsTitle(args);
} else if (type.equals("property")) {
handleAsProperty(args);
} else if (type.equals("progress")) {
handleAsProgress(args);
} else if (type.equals("start")) {
handleAsStart(args);
} else if (type.equals("done")) {
handleAsDone(args);
} else {
tasker.updateMessage(java.util.logging.Level.INFO, "未知的消息类型: " + node.toString());
}
} else {
tasker.updateMessage(java.util.logging.Level.INFO, "未知的消息: " + node.toString());
}
}
private void handleAsDone(JsonNode args) {
tasker.updateMessage(java.util.logging.Level.INFO, "任务完成");
close();
}
private void handleAsStart(JsonNode args) {
tasker.updateMessage(java.util.logging.Level.INFO, "任务开始");
}
private void handleAsProgress(JsonNode args) {
long current = args.get(0).asLong();
long total = args.get(1).asLong();
tasker.updateProgress(current, total);
}
private void handleAsProperty(JsonNode args) {
String name = args.get(0).asText();
Object value = args.get(1);
try {
PropertyDescriptor descriptor = BeanUtils.getPropertyDescriptor(tasker.getClass(), name);
System.out.println("descriptor = " + descriptor);
System.out.println("descriptor.getPropertyType() = " + descriptor.getPropertyType());
Object object = webSocketService.getObjectMapper().convertValue(value, descriptor.getPropertyType());
System.out.println("object = " + object);
System.out.println("descriptor.getWriteMethod() = " + descriptor.getWriteMethod());
System.out.println("descriptor.getWriteMethod().getParameterTypes() = " + descriptor.getWriteMethod().getParameterTypes());
descriptor.getWriteMethod().invoke(tasker, object);
} catch (Exception e) {
tasker.updateMessage(java.util.logging.Level.SEVERE, "属性设置失败: " + name + " = " + value);
}
}
private void handleAsTitle(JsonNode args) {
String message = args.get(0).asText();
tasker.updateTitle(message);
}
private void handleAsMessage(JsonNode args) {
String level = args.get(0).asText();
String message = args.get(1).asText();
updateMessage(java.util.logging.Level.parse(level), message);
}
public void updateMessage(Level level, String message) {
tasker.updateMessage(level, message);
}
}

View File

@@ -0,0 +1,29 @@
package com.ecep.contract;
import com.fasterxml.jackson.core.JsonProcessingException;
import java.util.Locale;
import java.util.logging.Level;
public interface WebSocketClientTasker {
String getTaskName();
void updateMessage(Level level, String message);
void updateTitle(String title);
void updateProgress(long current, long total);
default Object callRemoteTask(MessageHolder holder, Locale locale, Object... args) {
WebSocketClientService webSocketService = SpringApp.getBean(WebSocketClientService.class);
webSocketService.withSession(session -> {
try {
session.submitTask(this, locale, args);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
});
return null;
}
}

View File

@@ -1,7 +1,10 @@
package com.ecep.contract.manager.ui; package com.ecep.contract.controller;
import com.ecep.contract.manager.ds.other.model.IdentityEntity; import org.apache.poi.ss.formula.functions.T;
import com.ecep.contract.manager.ds.other.vo.IdentityViewModel;
import com.ecep.contract.model.IdentityEntity;
import com.ecep.contract.service.ViewModelService;
import com.ecep.contract.vm.IdentityViewModel;
import javafx.scene.control.TableView; import javafx.scene.control.TableView;
import javafx.stage.WindowEvent; import javafx.stage.WindowEvent;

View File

@@ -1,11 +1,21 @@
package com.ecep.contract.manager.ui; package com.ecep.contract.controller;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import com.ecep.contract.controller.tab.AbstEntityBasedTabSkin;
import com.ecep.contract.controller.tab.RefreshableSkin;
import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.model.IdentityEntity;
import com.ecep.contract.service.QueryService;
import com.ecep.contract.service.ViewModelService;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.BaseViewModel;
import com.ecep.contract.vm.IdentityViewModel;
import com.ecep.contract.manager.ds.other.model.IdentityEntity;
import com.ecep.contract.manager.ds.other.vo.BaseViewModel;
import com.ecep.contract.manager.ds.other.vo.IdentityViewModel;
import com.ecep.contract.manager.ui.tab.AbstEntityBasedTabSkin;
import com.ecep.contract.manager.ui.tab.TabSkin;
import com.ecep.contract.manager.util.UITools;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.beans.binding.Bindings; import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding; import javafx.beans.binding.BooleanBinding;
@@ -18,12 +28,6 @@ import javafx.stage.WindowEvent;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
public abstract class AbstEntityController<T extends IdentityEntity, TV extends IdentityViewModel<T>> public abstract class AbstEntityController<T extends IdentityEntity, TV extends IdentityViewModel<T>>
extends BaseController { extends BaseController {
@@ -43,15 +47,28 @@ public abstract class AbstEntityController<T extends IdentityEntity, TV extends
@Override @Override
public void onShown(WindowEvent windowEvent) { public void onShown(WindowEvent windowEvent) {
Class<?> aClass = getClass();
super.onShown(windowEvent); super.onShown(windowEvent);
loadedFuture = CompletableFuture.supplyAsync(() -> { ViewModelService<T, TV> service = getViewModelService();
T entity = loadEntity();
if (entity == null) { if (service instanceof QueryService<T, TV> queryService) {
setStatus("读取...");
loadedFuture = queryService.asyncFindById(viewModel.getId().get());
loadedFuture.thenAccept(entity -> {
// fixed, bind change if new view model create // fixed, bind change if new view model create
if (viewModel != null) { if (viewModel != null) {
viewModel.bindListener(); viewModel.bindListener();
} }
setStatus();
// BaseViewModel.updateInFxApplicationThread(entity, viewModel);
});
loadedFuture.exceptionally(ex -> {
handleException("载入失败,#" + viewModel.getId().get(), ex);
return null;
});
} else {
loadedFuture = CompletableFuture.supplyAsync(() -> {
T entity = getViewModelService().findById(viewModel.getId().get());
if (entity == null) {
return null; return null;
} }
Platform.runLater(() -> { Platform.runLater(() -> {
@@ -61,6 +78,7 @@ public abstract class AbstEntityController<T extends IdentityEntity, TV extends
viewModel.bindListener(); viewModel.bindListener();
return entity; return entity;
}); });
}
registerTabSkins(); registerTabSkins();
if (saveBtn != null) { if (saveBtn != null) {
@@ -71,10 +89,6 @@ public abstract class AbstEntityController<T extends IdentityEntity, TV extends
installTabSkins(); installTabSkins();
} }
protected T loadEntity() {
return getViewModelService().findById(viewModel.getId().get());
}
public T getEntity() { public T getEntity() {
return getLoadedFuture().join(); return getLoadedFuture().join();
} }
@@ -190,10 +204,20 @@ public abstract class AbstEntityController<T extends IdentityEntity, TV extends
public CompletableFuture<Void> refresh() { public CompletableFuture<Void> refresh() {
CompletableFuture<Void> future = new CompletableFuture<>(); CompletableFuture<Void> future = new CompletableFuture<>();
T entity = loadEntity(); ViewModelService<T, TV> service = getViewModelService();
if (service instanceof QueryService<T, TV> queryService) {
Platform.runLater(() -> { loadedFuture = queryService.asyncFindById(viewModel.getId().get());
loadedFuture.whenComplete((entity, ex) -> {
if (ex != null) {
future.completeExceptionally(ex);
return;
}
BaseViewModel.updateInFxApplicationThread(entity, viewModel);
});
} else {
T entity = service.findById(viewModel.getId().get());
setEntity(entity); setEntity(entity);
}
List<RefreshableSkin> list = tabSkins.stream() List<RefreshableSkin> list = tabSkins.stream()
.filter(v -> v instanceof RefreshableSkin) .filter(v -> v instanceof RefreshableSkin)
@@ -201,10 +225,10 @@ public abstract class AbstEntityController<T extends IdentityEntity, TV extends
if (list.isEmpty()) { if (list.isEmpty()) {
future.complete(null); future.complete(null);
return; return future;
} }
CompletableFuture.allOf(list return CompletableFuture.allOf(list
.stream() .stream()
.map(RefreshableSkin::refresh) .map(RefreshableSkin::refresh)
.filter(Objects::nonNull) .filter(Objects::nonNull)
@@ -216,9 +240,6 @@ public abstract class AbstEntityController<T extends IdentityEntity, TV extends
future.complete(null); future.complete(null);
} }
}); });
});
return future;
} }
public abstract ViewModelService<T, TV> getViewModelService(); public abstract ViewModelService<T, TV> getViewModelService();

View File

@@ -1,27 +1,31 @@
package com.ecep.contract.manager.ui; package com.ecep.contract.controller;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.Function; import java.util.function.Function;
import com.ecep.contract.manager.ui.table.EditableEntityTableTabSkin; import com.ecep.contract.util.ParamUtils;
import com.ecep.contract.manager.ui.table.TableTabSkin;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import com.ecep.contract.manager.ds.other.model.IdentityEntity; import com.ecep.contract.controller.table.EditableEntityTableTabSkin;
import com.ecep.contract.manager.ds.other.vo.IdentityViewModel; import com.ecep.contract.controller.table.TableTabSkin;
import com.ecep.contract.manager.util.TableViewUtils; import com.ecep.contract.model.IdentityEntity;
import com.ecep.contract.manager.util.UITools; import com.ecep.contract.service.QueryService;
import com.ecep.contract.service.ViewModelService;
import com.ecep.contract.util.TableViewUtils;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.IdentityViewModel;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.beans.property.Property; import javafx.beans.property.Property;
@@ -43,12 +47,15 @@ import javafx.scene.input.KeyEvent;
import javafx.util.converter.NumberStringConverter; import javafx.util.converter.NumberStringConverter;
/** /**
* 实体管理器皮肤
* 提供了实体管理器的基本功能如查询新增删除修改分页等
*
* @param <T> Entity 的类型 * @param <T> Entity 的类型
* @param <TV> Entity 对应的ViewModel * @param <TV> Entity 对应的ViewModel
* @param <Skin> Skin 的类型 * @param <SKIN> Skin 的类型
* @param <C> * @param <C>
*/ */
public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends IdentityViewModel<T>, Skin extends ManagerSkin, C extends AbstManagerWindowController<T, TV, Skin>> public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends IdentityViewModel<T>, SKIN extends ManagerSkin, C extends AbstManagerWindowController<T, TV, SKIN>>
implements ManagerSkin, TableTabSkin<T, TV>, EditableEntityTableTabSkin<T, TV> { implements ManagerSkin, TableTabSkin<T, TV>, EditableEntityTableTabSkin<T, TV> {
private static final Logger logger = LoggerFactory.getLogger(AbstEntityManagerSkin.class); private static final Logger logger = LoggerFactory.getLogger(AbstEntityManagerSkin.class);
/** /**
@@ -61,11 +68,20 @@ public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends
protected PageRequest currentPageable = PageRequest.ofSize(25); protected PageRequest currentPageable = PageRequest.ofSize(25);
protected final SimpleIntegerProperty currentPageNumber = new SimpleIntegerProperty(); protected final SimpleIntegerProperty currentPageNumber = new SimpleIntegerProperty();
// 是否允许调整表格高度
private boolean allowResize = true;
// 记录延时任务信息
private ScheduledFuture<?> loadTableDataSetFuture;
public AbstEntityManagerSkin(C controller) { public AbstEntityManagerSkin(C controller) {
this.controller = controller; this.controller = controller;
} }
@Override
public <TT> TT getBean(Class<TT> requiredType) throws BeansException {
return controller.getCachedBean(requiredType);
}
@Override @Override
public TableView<TV> getTableView() { public TableView<TV> getTableView() {
return controller.table; return controller.table;
@@ -199,6 +215,9 @@ public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends
* 根据表格高度重新计算分页的页大小 * 根据表格高度重新计算分页的页大小
*/ */
private void resizeTable(Object observable, Bounds old, Bounds newBounds) { private void resizeTable(Object observable, Bounds old, Bounds newBounds) {
if (!allowResize) {
return;
}
double tableHeight = newBounds.getHeight(); double tableHeight = newBounds.getHeight();
if (tableHeight <= 0) { if (tableHeight <= 0) {
return; return;
@@ -208,8 +227,13 @@ public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends
if (lookup != null) { if (lookup != null) {
double rowHeight = lookup.prefHeight(-1); double rowHeight = lookup.prefHeight(-1);
int rows = (int) Math.round(table.getHeight() / rowHeight) - 1; int rows = (int) Math.round(table.getHeight() / rowHeight) - 1;
int pageNumber = (int) Math.abs(currentPageable.getOffset() / rows); // 只有当行数变化超过一定阈值时才重新加载数据
int currentRows = currentPageable.getPageSize();
if (Math.abs(rows - currentRows) <= 2) {
return; // 避免微小变化导致频繁刷新
}
int pageNumber = (int) Math.abs(currentPageable.getOffset() / rows);
if (currentPageable.getPageNumber() == pageNumber && currentPageable.getPageSize() == rows) { if (currentPageable.getPageNumber() == pageNumber && currentPageable.getPageSize() == rows) {
return; return;
} }
@@ -259,9 +283,17 @@ public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends
} }
} }
protected <K> void acceptCellEditEvent(TableColumn.CellEditEvent<TV, K> event, Function<TV, Property<K>> function) { /**
* 处理单元格编辑事件
*
* @param <K>
* @param event
* @param propGetter
*/
protected <K> void acceptCellEditEvent(TableColumn.CellEditEvent<TV, K> event,
Function<TV, Property<K>> propGetter) {
TV row = event.getRowValue(); TV row = event.getRowValue();
Property<K> property = function.apply(row); Property<K> property = propGetter.apply(row);
property.setValue(event.getNewValue()); property.setValue(event.getNewValue());
try { try {
saveRowData(row); saveRowData(row);
@@ -317,21 +349,47 @@ public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends
row.saveInFxApplicationThread(service); row.saveInFxApplicationThread(service);
} }
/**
* 加载行数据
*
* @param row
* @return
*/
public T loadRowData(TV row) { public T loadRowData(TV row) {
return getViewModelService().findById(row.getId().get()); if (row.getId() == null) {
return null;
}
T entity = getViewModelService().findById(row.getId().get());
return entity;
} }
/**
* 删除行数据
*
* @param entity
*/
public void deleteRowData(T entity) { public void deleteRowData(T entity) {
if (entity == null) {
return;
}
ViewModelService<T, TV> service = getViewModelService();
getViewModelService().delete(entity); getViewModelService().delete(entity);
} }
/**
* 保存行数据
*
* @param entity
* @return
*/
public T saveRowData(T entity) { public T saveRowData(T entity) {
if (entity == null) {
return null;
}
ViewModelService<T, TV> service = getViewModelService();
return getViewModelService().save(entity); return getViewModelService().save(entity);
} }
// 记录延时任务信息
private ScheduledFuture<?> loadTableDataSetFuture;
@Override @Override
public void loadTableDataSet() { public void loadTableDataSet() {
loadTableDataSet(false); loadTableDataSet(false);
@@ -359,18 +417,18 @@ public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends
private CompletableFuture<Void> _reloadTableData() { private CompletableFuture<Void> _reloadTableData() {
CompletableFuture<Void> future = new CompletableFuture<>(); CompletableFuture<Void> future = new CompletableFuture<>();
Platform.runLater(() -> { Platform.runLater(() -> {
allowResize = false; // 禁用调整
dataSet.clear(); dataSet.clear();
runAsync(() -> { runAsync(() -> {
controller.setStatus("载入中..."); controller.setStatus("载入中...");
List<TV> models = loadTableData(); // 异步加载数据
Platform.runLater(() -> { if (getViewModelService() instanceof QueryService<T, TV> queryService) {
try { asyncLoadTableData(queryService, future);
updateTableDataSet(models); return;
future.complete(null);
} catch (Exception e) {
future.completeExceptionally(e);
} }
}); // 同步加载方法
List<TV> models = loadTableData();
_updateModels(models, future);
}).exceptionally(ex -> { }).exceptionally(ex -> {
future.completeExceptionally(ex); future.completeExceptionally(ex);
return null; return null;
@@ -379,20 +437,60 @@ public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends
return future; return future;
} }
private void _updateModels(List<TV> models, CompletableFuture<Void> future) {
Platform.runLater(() -> {
try {
updateTableDataSet(models);
allowResize = true; // 恢复调整
future.complete(null);
} catch (Exception e) {
allowResize = true; // 恢复调整
future.completeExceptionally(e);
}
});
}
/**
* 更新表格数据
*
* @param models
*/
protected void updateTableDataSet(List<TV> models) { protected void updateTableDataSet(List<TV> models) {
long timeMillis = System.currentTimeMillis(); long timeMillis = System.currentTimeMillis();
dataSet.setAll(models); // 清除所有选择状态避免选择状态混乱
if (getTableView() != null && getTableView().getSelectionModel() != null) {
getTableView().getSelectionModel().clearSelection();
}
// 先清空再设置新数据避免数据叠加
dataSet.clear();
if (models != null) {
dataSet.addAll(models);
}
// 强制刷新表格布局
if (getTableView() != null) {
getTableView().requestLayout();
getTableView().refresh();
}
long timeCost = System.currentTimeMillis() - timeMillis; long timeCost = System.currentTimeMillis() - timeMillis;
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("update table dataSet cost: {} ms", timeCost); logger.debug("update table dataSet cost: {} ms", timeCost);
} }
} }
/**
* 加载表格数据
*
* @return
*/
protected List<TV> loadTableData() { protected List<TV> loadTableData() {
Specification<T> spec = getSpecification(); ParamUtils.Builder params = getSpecification();
ViewModelService<T, TV> service = getViewModelService(); ViewModelService<T, TV> service = getViewModelService();
long timeMillis = System.currentTimeMillis(); long timeMillis = System.currentTimeMillis();
Page<T> page = service.findAll(spec, getPageable()); Page<T> page = service.findAll(params == null ? null : params.build(), getPageable());
long timeCost = System.currentTimeMillis() - timeMillis; long timeCost = System.currentTimeMillis() - timeMillis;
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("load table data cost: {} ms", timeCost); logger.debug("load table data cost: {} ms", timeCost);
@@ -404,17 +502,45 @@ public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends
return page.map(service::from).toList(); return page.map(service::from).toList();
} }
/**
* 异步加载表格数据
*
* @param queryService
* @param future
*/
private void asyncLoadTableData(QueryService<T, TV> queryService, CompletableFuture<Void> future) {
ParamUtils.Builder params = getSpecification();
queryService.asyncFindAll(params == null ? null : params.build(), getPageable()).whenComplete((result, ex) -> {
if (ex != null) {
future.completeExceptionally(ex);
return;
}
updateFooter(result);
List<TV> models = result.map(getViewModelService()::from).toList();
_updateModels(models, future);
});
}
/**
* 获取ViewModelService
*
* @return
*/
protected ViewModelService<T, TV> getViewModelService() { protected ViewModelService<T, TV> getViewModelService() {
ViewModelService<T, TV> service = controller.getViewModelService(); ViewModelService<T, TV> service = controller.getViewModelService();
if (service == null) { if (service == null) {
if (logger.isWarnEnabled()) { throw new IllegalArgumentException("ViewModelService is null");
logger.warn("ViewModelService is null");
}
} }
return service; return service;
} }
public Specification<T> getSpecification() { /**
* 获取查询条件
*
* @return
*/
public ParamUtils.Builder getSpecification() {
TextField field = controller.searchKeyField; TextField field = controller.searchKeyField;
if (field != null) { if (field != null) {
return getViewModelService().getSpecification(field.getText()); return getViewModelService().getSpecification(field.getText());
@@ -422,8 +548,14 @@ public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends
return null; return null;
} }
protected Specification<T> getSpecification(String searchText) { /**
return controller.getViewModelService().getSpecification(searchText); * 获取查询条件
*
* @param searchText
* @return
*/
protected ParamUtils.Builder getSpecification(String searchText) {
return getViewModelService().getSpecification(searchText);
} }
/** /**
@@ -434,6 +566,11 @@ public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends
protected void onTableRowDoubleClickedAction(TV item) { protected void onTableRowDoubleClickedAction(TV item) {
} }
/**
* 更新页脚
*
* @param page
*/
protected void updateFooter(Page<T> page) { protected void updateFooter(Page<T> page) {
Platform.runLater(() -> { Platform.runLater(() -> {
controller.previousPageBtn.setDisable(!page.hasPrevious()); controller.previousPageBtn.setDisable(!page.hasPrevious());
@@ -444,19 +581,44 @@ public abstract class AbstEntityManagerSkin<T extends IdentityEntity, TV extends
}); });
} }
/**
* 获取表格排序
*
* @return
*/
public List<Sort.Order> getTableOrders() { public List<Sort.Order> getTableOrders() {
return TableViewUtils.getOrders(getTableView()); return TableViewUtils.getOrders(getTableView());
} }
/**
* 获取表格排序
*
* @return
*/
public Sort getSortByTable() { public Sort getSortByTable() {
if (getTableView() == null) {
return Sort.unsorted();
}
return Sort.by(getTableOrders()); return Sort.by(getTableOrders());
} }
/**
* 获取分页参数
*
* @return
*/
public Pageable getPageable() { public Pageable getPageable() {
Sort sort = getSortByTable(); Sort sort = getSortByTable();
return currentPageable.withSort(sort); return currentPageable.withSort(sort);
} }
/**
* 显示在当前窗口为父窗口的新窗口
*
* @param <Controller> 控制器类型
* @param clz 控制器类
* @param model 数据
*/
protected <Controller extends AbstEntityController<T, TV>> void showInOwner(Class<Controller> clz, TV model) { protected <Controller extends AbstEntityController<T, TV>> void showInOwner(Class<Controller> clz, TV model) {
BaseController.show(clz, model, getTableView().getScene().getWindow()); BaseController.show(clz, model, getTableView().getScene().getWindow());
} }

View File

@@ -1,7 +1,7 @@
package com.ecep.contract.manager.ui; package com.ecep.contract.controller;
import com.ecep.contract.manager.ds.other.model.IdentityEntity; import com.ecep.contract.model.IdentityEntity;
import com.ecep.contract.manager.ds.other.vo.IdentityViewModel; import com.ecep.contract.vm.IdentityViewModel;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.scene.control.Button; import javafx.scene.control.Button;
import javafx.scene.control.Label; import javafx.scene.control.Label;
@@ -41,6 +41,4 @@ public abstract class AbstManagerWindowController<T extends IdentityEntity, TV e
} }
} }

View File

@@ -1,14 +1,33 @@
package com.ecep.contract.manager.ui; package com.ecep.contract.controller;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.FxmlUtils;
import com.ecep.contract.vo.EmployeeVo;
import org.apache.logging.log4j.util.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import com.ecep.contract.Desktop;
import com.ecep.contract.SpringApp;
import com.ecep.contract.model.Employee;
import com.ecep.contract.model.IdentityEntity;
import com.ecep.contract.service.EmployeeService;
import com.ecep.contract.service.SysConfService;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.CurrentEmployee;
import com.ecep.contract.vm.IdentityViewModel;
import com.ecep.contract.manager.Desktop;
import com.ecep.contract.manager.SpringApp;
import com.ecep.contract.manager.ds.other.model.Employee;
import com.ecep.contract.manager.ds.other.model.IdentityEntity;
import com.ecep.contract.manager.ds.other.service.EmployeeService;
import com.ecep.contract.manager.ds.other.service.SysConfService;
import com.ecep.contract.manager.ds.other.vo.IdentityViewModel;
import com.ecep.contract.manager.util.FxmlUtils;
import com.ecep.contract.manager.util.UITools;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty; import javafx.beans.property.StringProperty;
@@ -21,21 +40,6 @@ import javafx.stage.Stage;
import javafx.stage.Window; import javafx.stage.Window;
import javafx.stage.WindowEvent; import javafx.stage.WindowEvent;
import lombok.Getter; import lombok.Getter;
import lombok.Setter;
import org.apache.logging.log4j.util.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
public class BaseController { public class BaseController {
private static final Logger logger = LoggerFactory.getLogger(BaseController.class); private static final Logger logger = LoggerFactory.getLogger(BaseController.class);
@@ -45,7 +49,8 @@ public class BaseController {
return show(clz, owner, null); return show(clz, owner, null);
} }
public static <T extends BaseController> CompletableFuture<Void> show(Class<T> clz, Window owner, Consumer<T> consumer) { public static <T extends BaseController> CompletableFuture<Void> show(Class<T> clz, Window owner,
Consumer<T> consumer) {
String key = clz.getName(); String key = clz.getName();
if (toFront(key)) { if (toFront(key)) {
return null; return null;
@@ -65,8 +70,8 @@ public class BaseController {
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <K extends IdentityEntity, M extends IdentityViewModel<K>, T extends BaseController> public static <K extends IdentityEntity, M extends IdentityViewModel<K>, T extends BaseController> void show(
void show(Class<T> clz, M viewModel, Window owner) { Class<T> clz, M viewModel, Window owner) {
String key = getKey(clz, viewModel); String key = getKey(clz, viewModel);
if (toFront(key)) { if (toFront(key)) {
return; return;
@@ -76,7 +81,6 @@ public class BaseController {
throw new RuntimeException("@FxmlPath is required"); throw new RuntimeException("@FxmlPath is required");
} }
FxmlUtils.newLoaderAsyncWithRunLater(annotation.value(), null, loader -> { FxmlUtils.newLoaderAsyncWithRunLater(annotation.value(), null, loader -> {
T controller = loader.getController(); T controller = loader.getController();
if (controller instanceof AbstEntityController<?, ?>) { if (controller instanceof AbstEntityController<?, ?>) {
@@ -114,7 +118,6 @@ public class BaseController {
}); });
} }
public static boolean toFront(String key) { public static boolean toFront(String key) {
Stage stage = stages.get(key); Stage stage = stages.get(key);
if (stage != null) { if (stage != null) {
@@ -161,6 +164,11 @@ public class BaseController {
return future; return future;
} }
public CompletableFuture<Void> runAsync(Runnable runnable) {
return CompletableFuture.runAsync(runnable, Desktop.instance.getExecutorService())
.exceptionally(this::handleException);
}
/** /**
* 窗口标题 * 窗口标题
*/ */
@@ -177,42 +185,51 @@ public class BaseController {
private String stageKey; private String stageKey;
public Label leftStatusLabel; public Label leftStatusLabel;
public Label rightStatusLabel; public Label rightStatusLabel;
private EmployeeVo currentUser;
@Getter private HashMap<Class<?>, Object> cachedBeans = new HashMap<>();
@Setter
private Locale locale = Locale.getDefault();
@Setter public <T> T getBean(Class<T> requiredType) throws BeansException {
private SysConfService confService;
@Setter
private EmployeeService employeeService;
private Employee currentUser;
protected <T> T getBean(Class<T> requiredType) throws BeansException {
return SpringApp.getBean(requiredType); return SpringApp.getBean(requiredType);
} }
public SysConfService getConfService() { @SuppressWarnings("unchecked")
if (confService == null) { public <T> T getCachedBean(Class<T> requiredType) throws BeansException {
confService = getBean(SysConfService.class); Object object = cachedBeans.get(requiredType);
if (object == null) {
object = getBean(requiredType);
cachedBeans.put(requiredType, object);
} }
return confService; return (T) object;
}
public SysConfService getConfService() {
return getCachedBean(SysConfService.class);
} }
public EmployeeService getEmployeeService() { public EmployeeService getEmployeeService() {
if (employeeService == null) { return getCachedBean(EmployeeService.class);
employeeService = getBean(EmployeeService.class);
}
return employeeService;
} }
public Employee getCurrentUser() { public EmployeeVo getCurrentUser() {
if (currentUser == null) { if (currentUser == null) {
currentUser = getEmployeeService().findById(Desktop.instance.getActiveEmployeeId()); currentUser = getEmployeeService().findById(Desktop.instance.getActiveEmployeeId());
} }
return currentUser; return currentUser;
} }
public CurrentEmployee getCurrentEmployee() {
return Desktop.instance.getActiveEmployee();
}
public Locale getLocale() {
CurrentEmployee currentEmployee = getCurrentEmployee();
if (currentEmployee == null) {
return Locale.getDefault();
}
return currentEmployee.localeProperty().get();
}
public String getMessage(String code, Object... args) { public String getMessage(String code, Object... args) {
return SpringApp.getMessage(code, args, getLocale()); return SpringApp.getMessage(code, args, getLocale());
} }

View File

@@ -1,14 +1,14 @@
package com.ecep.contract.manager.cloud.rk; package com.ecep.contract.controller;
import org.hibernate.Hibernate; import com.ecep.contract.SpringApp;
import com.ecep.contract.controller.company.CompanyWindowController;
import com.ecep.contract.manager.SpringApp; import com.ecep.contract.controller.table.cell.CompanyTableCell;
import com.ecep.contract.manager.ui.table.cell.CompanyTableCell; import com.ecep.contract.controller.table.cell.LocalDateTimeTableCell;
import com.ecep.contract.manager.ds.company.controller.CompanyWindowController; import com.ecep.contract.service.CloudRkService;
import com.ecep.contract.manager.ds.company.model.Company; import com.ecep.contract.service.CompanyService;
import com.ecep.contract.manager.ds.company.service.CompanyService; import com.ecep.contract.vm.CloudRkViewModel;
import com.ecep.contract.manager.ui.AbstEntityManagerSkin; import com.ecep.contract.vo.CloudRkVo;
import com.ecep.contract.manager.ui.table.cell.LocalDateTimeTableCell; import com.ecep.contract.vo.CompanyVo;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
@@ -19,7 +19,7 @@ import javafx.scene.control.cell.CheckBoxTableCell;
import lombok.Setter; import lombok.Setter;
public class CloudRkManagerSkin public class CloudRkManagerSkin
extends AbstEntityManagerSkin<CloudRk, CloudRkInfoViewModel, CloudRkManagerSkin, CloudRkManagerWindowController> { extends AbstEntityManagerSkin<CloudRkVo, CloudRkViewModel, CloudRkManagerSkin, CloudRkManagerWindowController> {
@Setter @Setter
private CompanyService companyService; private CompanyService companyService;
@@ -47,13 +47,14 @@ public class CloudRkManagerSkin
controller.cloudIdColumn.setCellValueFactory(param -> param.getValue().getCloudId()); controller.cloudIdColumn.setCellValueFactory(param -> param.getValue().getCloudId());
controller.latestUpdateColumn.setCellValueFactory(param -> param.getValue().getLatest()); controller.latestUpdateColumn.setCellValueFactory(param -> param.getValue().getLatestUpdate());
controller.latestUpdateColumn.setCellFactory(param -> new LocalDateTimeTableCell<>()); controller.latestUpdateColumn.setCellFactory(param -> new LocalDateTimeTableCell<>());
controller.cloudLatestColumn.setCellValueFactory(param -> param.getValue().getCloudLatest()); controller.cloudLatestColumn.setCellValueFactory(param -> param.getValue().getCloudLatest());
controller.cloudLatestColumn.setCellFactory(param -> new LocalDateTimeTableCell<>()); controller.cloudLatestColumn.setCellFactory(param -> new LocalDateTimeTableCell<>());
controller.cloudBlackListUpdatedColumn.setCellValueFactory(param -> param.getValue().getCloudBlackListUpdated()); controller.cloudBlackListUpdatedColumn
.setCellValueFactory(param -> param.getValue().getCloudBlackListUpdated());
controller.cloudBlackListUpdatedColumn.setCellFactory(param -> new LocalDateTimeTableCell<>()); controller.cloudBlackListUpdatedColumn.setCellFactory(param -> new LocalDateTimeTableCell<>());
controller.cloudEntUpdateColumn.setCellValueFactory(param -> param.getValue().getCloudEntUpdate()); controller.cloudEntUpdateColumn.setCellValueFactory(param -> param.getValue().getCloudEntUpdate());
@@ -65,13 +66,12 @@ public class CloudRkManagerSkin
controller.descriptionColumn.setCellValueFactory(param -> param.getValue().getDescription()); controller.descriptionColumn.setCellValueFactory(param -> param.getValue().getDescription());
} }
private void onAutoUpdateColumnEditCommit(TableColumn.CellEditEvent<CloudRkInfoViewModel, Boolean> event) { private void onAutoUpdateColumnEditCommit(TableColumn.CellEditEvent<CloudRkViewModel, Boolean> event) {
CloudRkInfoViewModel row = event.getRowValue(); CloudRkViewModel row = event.getRowValue();
row.getAutoUpdate().set(event.getNewValue()); row.getAutoUpdate().set(event.getNewValue());
saveRowData(row); saveRowData(row);
} }
@Override @Override
protected void createContextMenu(ContextMenu contextMenu) { protected void createContextMenu(ContextMenu contextMenu) {
MenuItem item2 = new MenuItem("刷新"); MenuItem item2 = new MenuItem("刷新");
@@ -89,23 +89,21 @@ public class CloudRkManagerSkin
* @param event event * @param event event
*/ */
public void onTableClearDescriptionAction(ActionEvent event) { public void onTableClearDescriptionAction(ActionEvent event) {
ObservableList<CloudRkInfoViewModel> selectedItems = getTableView().getSelectionModel().getSelectedItems(); ObservableList<CloudRkViewModel> selectedItems = getTableView().getSelectionModel().getSelectedItems();
if (selectedItems.isEmpty()) { if (selectedItems.isEmpty()) {
return; return;
} }
CloudRkService service = getCloudRkService(); CloudRkService service = getCloudRkService();
for (CloudRkInfoViewModel selectedItem : selectedItems) { for (CloudRkViewModel selectedItem : selectedItems) {
selectedItem.getDescription().set(""); selectedItem.getDescription().set("");
selectedItem.saveInFxApplicationThread(service); selectedItem.saveInFxApplicationThread(service);
} }
} }
@Override @Override
protected void onTableRowDoubleClickedAction(CloudRkInfoViewModel item) { protected void onTableRowDoubleClickedAction(CloudRkViewModel item) {
Company company = item.getCompany().get(); Integer companyId = item.getCompany().get();
if (!Hibernate.isInitialized(item)) { CompanyVo company = getCompanyService().findById(companyId);
company = getCompanyService().findById(company.getId());
}
CompanyWindowController.show(company, getTableView().getScene().getWindow()); CompanyWindowController.show(company, getTableView().getScene().getWindow());
} }
} }

View File

@@ -0,0 +1,99 @@
package com.ecep.contract.controller;
import java.time.LocalDateTime;
import java.util.concurrent.ScheduledExecutorService;
import java.util.function.Consumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import com.ecep.contract.Message;
import com.ecep.contract.SpringApp;
import com.ecep.contract.service.CloudRkService;
import com.ecep.contract.task.CloudRkSyncTask;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.CloudRkViewModel;
import com.ecep.contract.vo.CloudRkVo;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.scene.control.TableColumn;
import javafx.stage.WindowEvent;
@Lazy
@Scope("prototype")
@Component
@FxmlPath("/ui/cloud/rk_manager.fxml")
public class CloudRkManagerWindowController
extends AbstManagerWindowController<CloudRkVo, CloudRkViewModel, CloudRkManagerSkin> {
private static final Logger logger = LoggerFactory.getLogger(CloudRkManagerWindowController.class);
public static void show() {
show(CloudRkManagerWindowController.class, null);
}
@Autowired
private CloudRkService cloudRkService;
public TableColumn<CloudRkViewModel, Number> idColumn;
public TableColumn<CloudRkViewModel, LocalDateTime> latestUpdateColumn;
/**
* 集团相关方, Company
*/
public TableColumn<CloudRkViewModel, Integer> companyColumn;
public TableColumn<CloudRkViewModel, String> cloudIdColumn;
public TableColumn<CloudRkViewModel, LocalDateTime> cloudLatestColumn;
public TableColumn<CloudRkViewModel, LocalDateTime> cloudBlackListUpdatedColumn;
public TableColumn<CloudRkViewModel, LocalDateTime> cloudEntUpdateColumn;
public TableColumn<CloudRkViewModel, Boolean> autoUpdateColumn;
public TableColumn<CloudRkViewModel, String> descriptionColumn;
@Override
protected CloudRkManagerSkin createDefaultSkin() {
return new CloudRkManagerSkin(this);
}
@Override
public void onShown(WindowEvent windowEvent) {
super.onShown(windowEvent);
getTitle().set("数据源:集团相关方");
}
private void initializeTask(Task<Object> task, String prefix, Consumer<String> consumer) {
task.setOnScheduled(e -> {
consumer.accept("正在从相关方平台同步" + prefix + ",请稍后...");
});
task.setOnRunning(e -> {
consumer.accept("开始" + prefix + "...");
});
task.setOnSucceeded(e -> {
consumer.accept(prefix + "完成...");
});
task.exceptionProperty().addListener((observable, oldValue, newValue) -> {
consumer.accept(newValue.getMessage());
logger.error("{} 发生异常", prefix, newValue);
});
SpringApp.getBean(ScheduledExecutorService.class).submit(task);
consumer.accept("任务已创建...");
}
public void onDataRepairAction(ActionEvent event) {
}
public void onSyncAction(ActionEvent event) {
CloudRkSyncTask task = new CloudRkSyncTask();
UITools.showTaskDialogAndWait("同步数据", task, consumer -> {
initializeTask(task, "同步数据", msg -> consumer.accept(Message.info(msg)));
});
}
@Override
public CloudRkService getViewModelService() {
return cloudRkService;
}
}

View File

@@ -1,21 +1,15 @@
package com.ecep.contract.manager.cloud.tyc; package com.ecep.contract.controller;
import java.util.List; import com.ecep.contract.SpringApp;
import com.ecep.contract.controller.company.CompanyWindowController;
import com.ecep.contract.controller.table.cell.CompanyTableCell;
import com.ecep.contract.controller.table.cell.LocalDateTimeTableCell;
import com.ecep.contract.service.CloudTycService;
import com.ecep.contract.service.CompanyService;
import com.ecep.contract.vm.CloudTycInfoViewModel;
import com.ecep.contract.vo.CloudTycVo;
import com.ecep.contract.vo.CompanyVo;
import org.hibernate.Hibernate;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.util.StringUtils;
import com.ecep.contract.manager.SpringApp;
import com.ecep.contract.manager.ui.table.cell.CompanyTableCell;
import com.ecep.contract.manager.ds.company.controller.CompanyWindowController;
import com.ecep.contract.manager.ds.company.model.Company;
import com.ecep.contract.manager.ds.company.service.CompanyService;
import com.ecep.contract.manager.ui.AbstEntityManagerSkin;
import com.ecep.contract.manager.ui.table.cell.LocalDateTimeTableCell;
import jakarta.persistence.criteria.Path;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.scene.control.ContextMenu; import javafx.scene.control.ContextMenu;
@@ -24,7 +18,7 @@ import lombok.Setter;
public class CloudTycManagerSkin public class CloudTycManagerSkin
extends extends
AbstEntityManagerSkin<CloudTyc, CloudTycInfoViewModel, CloudTycManagerSkin, CloudTycManagerWindowController> { AbstEntityManagerSkin<CloudTycVo, CloudTycInfoViewModel, CloudTycManagerSkin, CloudTycManagerWindowController> {
@Setter @Setter
private CloudTycService cloudTycService; private CloudTycService cloudTycService;
@@ -49,31 +43,6 @@ public class CloudTycManagerSkin
return companyService; return companyService;
} }
@Override
protected List<CloudTycInfoViewModel> loadTableData() {
String searchText = controller.searchKeyField.getText();
Specification<CloudTyc> spec = null;
if (StringUtils.hasText(searchText)) {
Specification<CloudTyc> companySpec = (root, query, builder) -> {
Path<Object> company = root.get("company");
return builder.or(
builder.like(company.get("name"), "%" + searchText + "%"),
builder.like(company.get("shortName"), "%" + searchText + "%"));
};
Specification<CloudTyc> cloudIdSpec = (root, query, builder) -> {
return builder.like(root.get("cloudId"), "%" + searchText + "%");
};
spec = Specification.anyOf(companySpec, cloudIdSpec);
}
Page<CloudTyc> page = getCloudTycService().findAll(spec, getPageable());
updateFooter(page);
return page.map(CloudTycInfoViewModel::from).toList();
}
@Override @Override
public void initializeTable() { public void initializeTable() {
controller.idColumn.setCellValueFactory(param -> param.getValue().getId()); controller.idColumn.setCellValueFactory(param -> param.getValue().getId());
@@ -114,21 +83,20 @@ public class CloudTycManagerSkin
return; return;
} }
for (CloudTycInfoViewModel selectedItem : selectedItems) { for (CloudTycInfoViewModel selectedItem : selectedItems) {
CloudTyc cloudTyc = getCloudTycService().findById(selectedItem.getId().get()); CloudTycVo cloudTyc = getCloudTycService().findById(selectedItem.getId().get());
// selectedItem.getDescription().set(""); // selectedItem.getDescription().set("");
if (selectedItem.copyTo(cloudTyc)) { if (selectedItem.copyTo(cloudTyc)) {
CloudTyc saved = getCloudTycService().save(cloudTyc); CloudTycVo saved = getCloudTycService().save(cloudTyc);
selectedItem.update(saved); selectedItem.update(saved);
} }
} }
} }
//
@Override @Override
protected void onTableRowDoubleClickedAction(CloudTycInfoViewModel item) { protected void onTableRowDoubleClickedAction(CloudTycInfoViewModel item) {
Company company = item.getCompany().get(); Integer companyId = item.getCompany().get();
if (!Hibernate.isInitialized(item)) { CompanyVo company = getCompanyService().findById(companyId);
company = getCompanyService().findById(company.getId());
}
CompanyWindowController.show(company, getTableView().getScene().getWindow()); CompanyWindowController.show(company, getTableView().getScene().getWindow());
} }
} }

View File

@@ -0,0 +1,75 @@
package com.ecep.contract.controller;
import java.time.LocalDateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import com.ecep.contract.service.CloudTycService;
import com.ecep.contract.service.CompanyService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.vm.CloudTycInfoViewModel;
import com.ecep.contract.vo.CloudTycVo;
import javafx.fxml.FXML;
import javafx.scene.control.TableColumn;
import javafx.stage.Stage;
/**
* 天眼查信息管理窗口控制器
*/
@Lazy
@Scope("prototype")
@Component
@FxmlPath("/ui/cloud/tyc_manager.fxml")
public class CloudTycManagerWindowController
extends AbstManagerWindowController<CloudTycVo, CloudTycInfoViewModel, CloudTycManagerSkin> {
public static void show() {
show(CloudTycManagerWindowController.class, null);
}
@Autowired
private CloudTycService cloudTycService;
@Autowired
private CompanyService companyService;
@FXML
public TableColumn<CloudTycInfoViewModel, Number> idColumn;
@FXML
public TableColumn<CloudTycInfoViewModel, LocalDateTime> latestUpdateColumn;
/**
* 公司, Company
*/
@FXML
public TableColumn<CloudTycInfoViewModel, Integer> companyColumn;
@FXML
public TableColumn<CloudTycInfoViewModel, String> cloudIdColumn;
@FXML
public TableColumn<CloudTycInfoViewModel, LocalDateTime> cloudLatestColumn;
@FXML
public TableColumn<CloudTycInfoViewModel, Number> scoreColumn;
@FXML
public TableColumn<CloudTycInfoViewModel, String> descriptionColumn;
@Override
public CloudTycService getViewModelService() {
return cloudTycService;
}
@Override
protected CloudTycManagerSkin createDefaultSkin() {
return new CloudTycManagerSkin(this);
}
@Override
public void show(Stage stage) {
super.show(stage);
getTitle().set("数据源:天眼查");
}
}

View File

@@ -1,17 +1,20 @@
package com.ecep.contract.manager.ui; package com.ecep.contract.controller;
import java.util.List;
import org.springframework.util.StringUtils;
import com.ecep.contract.model.BaseEnumEntity;
import com.ecep.contract.model.BasedEntity;
import com.ecep.contract.model.IdentityEntity;
import com.ecep.contract.model.NamedEntity;
import com.ecep.contract.service.IEntityService;
import com.ecep.contract.manager.ds.other.model.BaseEnumEntity;
import com.ecep.contract.manager.ds.other.model.Entity;
import com.ecep.contract.manager.ds.other.model.IdentityEntity;
import com.ecep.contract.manager.ds.other.model.NamedEntity;
import javafx.beans.property.Property; import javafx.beans.property.Property;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
import javafx.scene.control.ComboBox; import javafx.scene.control.ComboBox;
import javafx.scene.control.ListCell; import javafx.scene.control.ListCell;
import org.springframework.util.StringUtils;
import java.util.List;
public class ComboBoxUtils { public class ComboBoxUtils {
@@ -19,7 +22,7 @@ public class ComboBoxUtils {
if (t == null) { if (t == null) {
return "全部"; return "全部";
} }
if (t instanceof Entity e) { if (t instanceof BasedEntity e) {
return e.toPrettyString(); return e.toPrettyString();
} }
if (t instanceof BaseEnumEntity<?> e) { if (t instanceof BaseEnumEntity<?> e) {
@@ -44,7 +47,7 @@ public class ComboBoxUtils {
if (t == null) { if (t == null) {
continue; continue;
} }
if (t instanceof Entity e) { if (t instanceof BasedEntity e) {
if (e.toPrettyString().equals(string)) { if (e.toPrettyString().equals(string)) {
return t; return t;
} }
@@ -66,9 +69,7 @@ public class ComboBoxUtils {
return null; return null;
} }
private static class ComboBoxStringConverter<T> extends javafx.util.StringConverter<T> {
private static
class ComboBoxStringConverter<T> extends javafx.util.StringConverter<T> {
private final List<T> dataset; private final List<T> dataset;
public ComboBoxStringConverter(ObservableList<T> list) { public ComboBoxStringConverter(ObservableList<T> list) {
@@ -115,9 +116,48 @@ public class ComboBoxUtils {
} }
} }
public static <T extends IdentityEntity> void initialComboBox(
ComboBox<T> comboBox, Property<Integer> property, IEntityService<T> queryService, boolean hasNull) {
ObservableList<T> list = FXCollections.observableArrayList();
if (hasNull) {
list.add(null);
}
list.addAll(queryService.findAll());
comboBox.setItems(list);
EntityStringConverter<T> converter = new EntityStringConverter<>(list);
comboBox.setConverter(converter);
if (property != null) {
// 从ComboBox选择到property的单向绑定
comboBox.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
property.setValue(newValue != null ? newValue.getId() : null);
});
// 从property到ComboBox的单向绑定
property.addListener((observable, oldValue, newValue) -> {
if (newValue == null) {
comboBox.getSelectionModel().clearSelection();
return;
}
list.stream()
.filter(item -> item != null && newValue.equals(item.getId()))
.findFirst()
.ifPresent(comboBox.getSelectionModel()::select);
});
// 初始化ComboBox的值
if (property.getValue() != null) {
list.stream()
.filter(item -> item != null && property.getValue().equals(item.getId()))
.findFirst()
.ifPresent(comboBox.getSelectionModel()::select);
}
}
}
public static <T extends IdentityEntity & NamedEntity> void initialComboBox( public static <T extends IdentityEntity & NamedEntity> void initialComboBox(
ComboBox<T> comboBox, Property<T> property, List<T> dataSet, boolean hasNull ComboBox<T> comboBox, Property<T> property, List<T> dataSet, boolean hasNull) {
) {
ObservableList<T> list = FXCollections.observableArrayList(); ObservableList<T> list = FXCollections.observableArrayList();
if (hasNull) { if (hasNull) {
list.add(null); list.add(null);
@@ -148,7 +188,8 @@ public class ComboBoxUtils {
}); });
} }
public static <K extends Enum<?>, T extends BaseEnumEntity<K>> void bindComboBox(ComboBox<T> comboBox, Property<K> property, List<T> dataSet) { public static <K extends Enum<?>, T extends BaseEnumEntity<K>> void bindComboBox(ComboBox<T> comboBox,
Property<K> property, List<T> dataSet) {
property.addListener((observable, oldValue, newValue) -> { property.addListener((observable, oldValue, newValue) -> {
dataSet.stream().filter(l -> l.getType() == newValue).findFirst().ifPresent(comboBox::setValue); dataSet.stream().filter(l -> l.getType() == newValue).findFirst().ifPresent(comboBox::setValue);
}); });

View File

@@ -0,0 +1,12 @@
package com.ecep.contract.controller;
import com.ecep.contract.MessageHolder;
import com.ecep.contract.task.Tasker;
public class ContractGroupSyncTask extends Tasker<Object>{
@Override
public Object execute(MessageHolder holder) {
return null;
}
}

View File

@@ -0,0 +1,11 @@
package com.ecep.contract.controller;
import com.ecep.contract.MessageHolder;
import com.ecep.contract.task.Tasker;
public class ContractKindSyncTask extends Tasker<Object> {
@Override
public Object execute(MessageHolder holder) {
return null;
}
}

View File

@@ -0,0 +1,12 @@
package com.ecep.contract.controller;
import com.ecep.contract.MessageHolder;
import com.ecep.contract.task.Tasker;
public class ContractSyncAllTask extends Tasker<Object> {
@Override
public Object execute(MessageHolder holder) {
return null;
}
}

View File

@@ -0,0 +1,11 @@
package com.ecep.contract.controller;
import com.ecep.contract.MessageHolder;
import com.ecep.contract.task.Tasker;
public class ContractTypeSyncTask extends Tasker<Object> {
@Override
public Object execute(MessageHolder holder) {
return null;
}
}

View File

@@ -1,7 +1,10 @@
package com.ecep.contract.manager; package com.ecep.contract.controller;
import org.springframework.context.ApplicationEvent;
import com.ecep.contract.vm.CurrentEmployee;
import lombok.Getter; import lombok.Getter;
import org.springframework.context.ApplicationEvent;
@Getter @Getter
public class CurrentEmployeeInitialedEvent extends ApplicationEvent { public class CurrentEmployeeInitialedEvent extends ApplicationEvent {

View File

@@ -0,0 +1,14 @@
package com.ecep.contract.controller;
import com.ecep.contract.MessageHolder;
import com.ecep.contract.task.Tasker;
public class CustomerClassSyncTask extends Tasker<Object> {
@Override
protected Object execute(MessageHolder holder) throws Exception {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'execute'");
}
}

View File

@@ -1,11 +1,13 @@
package com.ecep.contract.manager.ds.other.controller; package com.ecep.contract.controller;
import java.time.LocalDateTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.controlsfx.control.TaskProgressView; import org.controlsfx.control.TaskProgressView;
import org.controlsfx.glyphfont.Glyph;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
@@ -14,32 +16,26 @@ import org.springframework.context.annotation.Scope;
import org.springframework.context.event.EventListener; import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.ecep.contract.manager.CurrentEmployee; import com.ecep.contract.Desktop;
import com.ecep.contract.manager.CurrentEmployeeInitialedEvent; import com.ecep.contract.DesktopUtils;
import com.ecep.contract.manager.Desktop; import com.ecep.contract.WebSocketClientService;
import com.ecep.contract.manager.cloud.old.OldVersionService; import com.ecep.contract.controller.bank.BankManagerWindowController;
import com.ecep.contract.manager.cloud.rk.CloudRkManagerWindowController; import com.ecep.contract.controller.company.CompanyManagerWindowController;
import com.ecep.contract.manager.cloud.rk.CloudRkService; import com.ecep.contract.controller.contract.ContractManagerWindowController;
import com.ecep.contract.manager.cloud.tyc.CloudTycManagerWindowController; import com.ecep.contract.controller.customer.CompanyCustomerManagerWindowController;
import com.ecep.contract.manager.cloud.u8.ContractSyncTask; import com.ecep.contract.controller.department.DepartmentManagerWindowController;
import com.ecep.contract.manager.cloud.u8.YongYouU8ManagerWindowController; import com.ecep.contract.controller.employee.EmployeeManagerWindowController;
import com.ecep.contract.manager.cloud.u8.YongYouU8Service; import com.ecep.contract.controller.inventory.InventoryManagerWindowController;
import com.ecep.contract.manager.ds.company.controller.CompanyManagerWindowController; import com.ecep.contract.controller.permission.EmployeeFunctionsManagerWindowController;
import com.ecep.contract.manager.ds.contract.controller.ContractManagerWindowController; import com.ecep.contract.controller.permission.EmployeeRoleManagerWindowController;
import com.ecep.contract.manager.ds.customer.controller.CompanyCustomerManagerWindowController; import com.ecep.contract.controller.project.ProjectManagerWindowController;
import com.ecep.contract.manager.ds.other.controller.bank.BankManagerWindowController; import com.ecep.contract.controller.vendor.CompanyVendorManagerWindowController;
import com.ecep.contract.manager.ds.other.controller.department.DepartmentManagerWindowController; import com.ecep.contract.service.CloudRkService;
import com.ecep.contract.manager.ds.other.controller.employee.EmployeeManagerWindowController; import com.ecep.contract.service.YongYouU8Service;
import com.ecep.contract.manager.ds.other.controller.inventory.InventoryManagerWindowController; import com.ecep.contract.task.ContractSyncTask;
import com.ecep.contract.manager.ds.other.controller.permission.EmployeeFunctionsManagerWindowController; import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.manager.ds.other.controller.permission.EmployeeRoleManagerWindowController; import com.ecep.contract.util.FxmlUtils;
import com.ecep.contract.manager.ds.project.controller.ProjectManagerWindowController; import com.ecep.contract.vm.CurrentEmployee;
import com.ecep.contract.manager.ds.vendor.controller.CompanyVendorManagerWindowController;
import com.ecep.contract.manager.ui.BaseController;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.ui.task.TaskMonitorViewController;
import com.ecep.contract.manager.util.DesktopUtils;
import com.ecep.contract.manager.util.FxmlUtils;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
@@ -75,6 +71,8 @@ public class HomeWindowController extends BaseController {
public Button openCustomManagerWindow; public Button openCustomManagerWindow;
public TaskProgressView<Task<?>> taskProgressView; public TaskProgressView<Task<?>> taskProgressView;
public Label taskMonitorLabel; public Label taskMonitorLabel;
public Label webSocketMonitorLabel;
public Glyph webSocketMonitorIcon;
public Label employeeStatusLabel; public Label employeeStatusLabel;
public void initialize() { public void initialize() {
@@ -102,6 +100,15 @@ public class HomeWindowController extends BaseController {
employeeStatusLabel.textProperty().bind(Desktop.instance.getActiveEmployee().getName()); employeeStatusLabel.textProperty().bind(Desktop.instance.getActiveEmployee().getName());
Desktop.instance.getTaskMonitorCenter().bindStatusLabel(taskMonitorLabel); Desktop.instance.getTaskMonitorCenter().bindStatusLabel(taskMonitorLabel);
Desktop.instance.getActiveEmployee().initialize(); Desktop.instance.getActiveEmployee().initialize();
WebSocketClientService webSocketService = getBean(WebSocketClientService.class);
webSocketMonitorIcon.iconProperty()
.bind(webSocketService.getOnlineProperty().map(b -> b ? "CHAIN" : "CHAIN_BROKEN"));
webSocketMonitorLabel.textProperty().bind(webSocketService.getMessageProperty());
webSocketMonitorLabel.setOnMouseClicked(event -> {
webSocketService.send("webSocketUrl - " + LocalDateTime.now().toString());
});
webSocketService.initWebSocket();
} }
@EventListener @EventListener
@@ -112,10 +119,6 @@ public class HomeWindowController extends BaseController {
logger.info("You are administrator, try schedule sync tasks."); logger.info("You are administrator, try schedule sync tasks.");
} }
Desktop.instance.getExecutorService().schedule(() -> { Desktop.instance.getExecutorService().schedule(() -> {
try {
getBean(OldVersionService.class).scheduledTasks(taskProgressView);
} catch (BeansException ignored) {
}
try { try {
getBean(YongYouU8Service.class).scheduledTasks(taskProgressView); getBean(YongYouU8Service.class).scheduledTasks(taskProgressView);
} catch (BeansException ignored) { } catch (BeansException ignored) {
@@ -140,14 +143,6 @@ public class HomeWindowController extends BaseController {
// scheduledExecutorService.shutdownNow(); // scheduledExecutorService.shutdownNow();
} }
@Override
public void onHidden(WindowEvent windowEvent) {
System.out.println("windowEvent = " + windowEvent);
super.onHidden(windowEvent);
// Platform.exit();
}
/** /**
* 打开 配置 窗口 * 打开 配置 窗口
*/ */
@@ -221,12 +216,11 @@ public class HomeWindowController extends BaseController {
showInOwner(TaskMonitorViewController.class); showInOwner(TaskMonitorViewController.class);
} }
/** @Override
* 运行任务监控演示 public void onHidden(WindowEvent windowEvent) {
*/ System.out.println("windowEvent = " + windowEvent);
public void onRunTaskMonitorDemo(ActionEvent event) { WebSocketClientService webSocketService = getBean(WebSocketClientService.class);
com.ecep.contract.manager.ui.task.DemoTask.runDemo(); webSocketService.closeWebSocket(); // 在窗口隐藏时关闭WebSocket连接
// 自动打开任务监控窗口 super.onHidden(windowEvent);
showInOwner(TaskMonitorViewController.class);
} }
} }

View File

@@ -1,39 +1,51 @@
package com.ecep.contract.manager.ds.other.controller; package com.ecep.contract.controller;
import com.ecep.contract.manager.Desktop;
import com.ecep.contract.manager.SpringApp;
import com.ecep.contract.manager.ui.MessageHolder;
import com.zaxxer.hikari.HikariDataSource;
import javafx.application.Platform;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
import lombok.Setter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.util.StringUtils;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.net.Inet4Address; import java.net.Inet4Address;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.NetworkInterface; import java.net.NetworkInterface;
import java.net.SocketException; import java.net.SocketException;
import java.sql.*; import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.*; import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Properties;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level; import java.util.logging.Level;
import static com.ecep.contract.manager.AppV2.*; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import com.ecep.contract.Desktop;
import com.ecep.contract.MessageHolder;
import com.ecep.contract.SpringApp;
import javafx.application.Platform;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
import lombok.Setter;
public class LoginWidowController implements MessageHolder { public class LoginWidowController implements MessageHolder {
private static final Logger logger = LoggerFactory.getLogger(LoginWidowController.class); private static final Logger logger = LoggerFactory.getLogger(LoginWidowController.class);
@@ -60,23 +72,7 @@ public class LoginWidowController implements MessageHolder {
} }
String getHost() { String getHost() {
return properties.getProperty("db.server.host", DEFAULT_DB_HOST); return properties.getProperty("server.host");
}
String getPort() {
return properties.getProperty("db.server.port", DEFAULT_DB_PORT);
}
String getDatabase() {
return properties.getProperty("db.server.database", DEFAULT_DB_DATABASE);
}
public String getUserName() {
return properties.getProperty("db.server.username", DEFAULT_DB_USERNAME);
}
public String getPassword() {
return properties.getProperty("db.server.password", DEFAULT_DB_PASSWORD);
} }
public void tryLogin() { public void tryLogin() {
@@ -99,6 +95,15 @@ public class LoginWidowController implements MessageHolder {
} }
} }
private String getPassword() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'getPassword'");
}
private String getUserName() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'getUserName'");
}
CompletableFuture<List<LoginWidowController.MacIP>> getMacAndIP() { CompletableFuture<List<LoginWidowController.MacIP>> getMacAndIP() {
return CompletableFuture.supplyAsync(() -> { return CompletableFuture.supplyAsync(() -> {
@@ -123,7 +128,8 @@ public class LoginWidowController implements MessageHolder {
// -分割16进制表示法 // -分割16进制表示法
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
for (int i = 0; i < hardwareAddress.length; i++) { for (int i = 0; i < hardwareAddress.length; i++) {
sb.append(String.format("%02X%s", hardwareAddress[i], i < hardwareAddress.length - 1 ? "-" : "")); sb.append(
String.format("%02X%s", hardwareAddress[i], i < hardwareAddress.length - 1 ? "-" : ""));
} }
while (inetAddresses.hasMoreElements()) { while (inetAddresses.hasMoreElements()) {
@@ -146,40 +152,20 @@ public class LoginWidowController implements MessageHolder {
String database = getDatabase(); String database = getDatabase();
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("try to connect db server host:{},port:{},database:{},user:{},pwd:{}", host, port, database, userName, "*"); logger.debug("try to connect db server host:{},port:{},database:{},user:{},pwd:{}", host, port, database,
userName, "*");
}
return null;
} }
try (HikariDataSource source = DataSourceBuilder.create() private String getDatabase() {
.type(HikariDataSource.class) // TODO Auto-generated method stub
.url("jdbc:mysql://" + host + ":" + port + "/" + database) throw new UnsupportedOperationException("Unimplemented method 'getDatabase'");
.username(userName)
.password(password)
.driverClassName("com.mysql.cj.jdbc.Driver")
.build()) {
CompletableFuture<List<MacIP>> macAndIP = getMacAndIP();
macAndIP.thenAccept(map -> {
if (map.isEmpty()) {
error("查询本地地址信息失败,请联系管理员或重启应用!");
logger.error("查询本地地址信息失败");
}
});
try (Connection connection = source.getConnection()) {
info("连接到数据库 " + host + ", 请稍后,正在查询账户与本绑定的登录信息...");
if (logger.isDebugEnabled()) {
logger.debug("connection.getClientInfo() = {}", connection.getClientInfo());
}
// 必须要阻塞否则 connection 会断开
EmployeeInfo employeeInfo = tryLoginWithEmployeeBind(connection, macAndIP).get();
createSession(connection, employeeInfo);
return employeeInfo;
} catch (ExecutionException | InterruptedException e) {
throw new RuntimeException(e);
}
} }
private String getPort() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'getPort'");
} }
private void createSession(Connection connection, EmployeeInfo employeeInfo) { private void createSession(Connection connection, EmployeeInfo employeeInfo) {
@@ -242,7 +228,8 @@ public class LoginWidowController implements MessageHolder {
} }
} }
private CompletableFuture<EmployeeInfo> tryLoginWithEmployeeBind(Connection connection, CompletableFuture<List<MacIP>> macAndIP) { private CompletableFuture<EmployeeInfo> tryLoginWithEmployeeBind(Connection connection,
CompletableFuture<List<MacIP>> macAndIP) {
CompletableFuture<EmployeeInfo> future = new CompletableFuture<>(); CompletableFuture<EmployeeInfo> future = new CompletableFuture<>();
macAndIP.thenAccept(macIPS -> { macAndIP.thenAccept(macIPS -> {
if (macIPS.isEmpty()) { if (macIPS.isEmpty()) {
@@ -409,8 +396,7 @@ public class LoginWidowController implements MessageHolder {
} catch (SQLException e) { } catch (SQLException e) {
throw new RuntimeException( throw new RuntimeException(
String.format("查询本机绑定信息异常请联系管理员或重启应用MAC: %s, IP: %s", macIP.mac, macIP.ip), String.format("查询本机绑定信息异常请联系管理员或重启应用MAC: %s, IP: %s", macIP.mac, macIP.ip),
e e);
);
} }
return list; return list;
} }
@@ -479,14 +465,12 @@ public class LoginWidowController implements MessageHolder {
borderPane.setCenter(grid); borderPane.setCenter(grid);
// 登录按钮 // 登录按钮
Button loginButton = new Button("登录"); Button loginButton = new Button("登录");
loginButton.setDefaultButton(true); loginButton.setDefaultButton(true);
borderPane.setBottom(loginButton); borderPane.setBottom(loginButton);
BorderPane.setAlignment(loginButton, javafx.geometry.Pos.CENTER); BorderPane.setAlignment(loginButton, javafx.geometry.Pos.CENTER);
// 登录按钮点击事件 // 登录按钮点击事件
loginButton.setOnAction(event -> { loginButton.setOnAction(event -> {
String username = userField.getText(); String username = userField.getText();
@@ -526,7 +510,6 @@ public class LoginWidowController implements MessageHolder {
stage.close(); stage.close();
}); });
// 创建场景并设置到窗口 // 创建场景并设置到窗口
Scene scene = new Scene(borderPane, 400, 260); Scene scene = new Scene(borderPane, 400, 260);
stage.setScene(scene); stage.setScene(scene);
@@ -535,14 +518,13 @@ public class LoginWidowController implements MessageHolder {
stage.showAndWait(); stage.showAndWait();
} }
private void logined(EmployeeInfo employeeInfo) { private void logined(EmployeeInfo employeeInfo) {
info("欢迎 " + employeeInfo.name.get()); info("欢迎 " + employeeInfo.name.get());
if (!SpringApp.isRunning()) { if (!SpringApp.isRunning()) {
info("请稍后..."); info("请稍后...");
} }
Desktop.instance.setActiveEmployeeId(employeeInfo.employeeId); Desktop.instance.setActiveEmployeeId(employeeInfo.employeeId);
Desktop.instance.setSessionId(employeeInfo.sessionId); // Desktop.instance.setSessionId(employeeInfo.sessionId);
tryShowHomeWindow(); tryShowHomeWindow();
} }

View File

@@ -1,4 +1,6 @@
package com.ecep.contract.manager.ui; package com.ecep.contract.controller;
import com.ecep.contract.controller.tab.Skin;
public interface ManagerSkin extends Skin { public interface ManagerSkin extends Skin {

View File

@@ -0,0 +1,390 @@
package com.ecep.contract.controller;
import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.CompletableFuture;
import java.util.logging.Level;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import com.ecep.contract.Desktop;
import com.ecep.contract.MessageHolder;
import com.ecep.contract.SpringApp;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
import lombok.Setter;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.WebSocket;
public class OkHttpLoginController implements MessageHolder {
private static final Logger logger = LoggerFactory.getLogger(OkHttpLoginController.class);
public static final MediaType JSON = MediaType.get("application/json; charset=utf-8");
@Setter
private MessageHolder holder;
@Setter
private Stage primaryStage;
@Setter
private Properties properties;
@Setter
private OkHttpClient httpClient;
private WebSocket webSocket;
private String serverUrl;
private String webSocketUrl;
public OkHttpLoginController() {
this.httpClient = new OkHttpClient().newBuilder().cookieJar(new CookieJar() {
private final List<Cookie> cookies = new java.util.ArrayList<>();
@Override
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
// 保存服务器返回的Cookie如JSESSIONID
this.cookies.addAll(cookies);
System.out.println("保存Cookie: " + cookies);
}
@Override
public List<Cookie> loadForRequest(HttpUrl url) {
// 请求时自动携带Cookie
return cookies;
}
}).build();
}
@Override
public void addMessage(Level level, String message) {
if (holder != null) {
holder.addMessage(level, message);
}
}
private void initServerUrls() {
String host = properties.getProperty("server.host", "localhost");
String port = properties.getProperty("server.port", "8080");
this.serverUrl = "http://" + host + ":" + port;
this.webSocketUrl = "ws://" + host + ":" + port + "/ws";
}
public CompletableFuture<Void> tryLogin() {
initServerUrls();
// 检查配置文件中是否保存用户名和密码
String userName = getUserName();
String password = getPassword();
if (StringUtils.hasText(userName) && StringUtils.hasText(password)) {
return login(userName, password);
} else {
CompletableFuture<Void> loginFuture = new CompletableFuture<>();
Platform.runLater(() -> {
showLoginDialog();
loginFuture.complete(null);
});
return loginFuture;
}
}
private String getUserName() {
return properties.getProperty("user.name", "");
}
private String getPassword() {
return properties.getProperty("user.password", "");
}
private void showLoginDialog() {
Stage stage = new Stage();
stage.initOwner(primaryStage);
stage.setTitle("系统登录");
// 创建 BorderPane 并设置边距
BorderPane borderPane = new BorderPane();
borderPane.setPadding(new Insets(20));
// 创建布局
GridPane grid = new GridPane();
grid.setHgap(10);
grid.setVgap(15);
// 账户输入框
Label userLabel = new Label("用户名:");
TextField userField = new TextField();
{
String username = getUserName();
if (StringUtils.hasText(username)) {
userField.setText(username);
}
grid.add(userLabel, 0, 0);
grid.add(userField, 1, 0);
}
// 密码输入框
Label passwordLabel = new Label("密码:");
PasswordField passwordField = new PasswordField();
{
String password = getPassword();
if (StringUtils.hasText(password)) {
passwordField.setText(password);
}
grid.add(passwordLabel, 0, 1);
grid.add(passwordField, 1, 1);
}
// 记住密码复选框
CheckBox rememberCheckBox = new CheckBox("记住密码");
{
String property = properties.getProperty("remember.password", "false");
if (Boolean.parseBoolean(property)) {
rememberCheckBox.setSelected(true);
}
}
grid.add(rememberCheckBox, 1, 2);
// 错误消息提示
Label errorLabel = new Label();
errorLabel.setStyle("-fx-text-fill: red;");
errorLabel.setVisible(false);
grid.add(errorLabel, 0, 3);
GridPane.setColumnSpan(errorLabel, 2);
borderPane.setCenter(grid);
// 登录按钮
Button loginButton = new Button("登录");
loginButton.setDefaultButton(true);
loginButton.setPrefWidth(100);
borderPane.setBottom(loginButton);
BorderPane.setAlignment(loginButton, javafx.geometry.Pos.CENTER);
BorderPane.setMargin(loginButton, new Insets(20, 0, 0, 0));
// 登录按钮点击事件
loginButton.setOnAction(event -> {
String username = userField.getText();
String password = passwordField.getText();
boolean remember = rememberCheckBox.isSelected();
if (!StringUtils.hasText(username) || !StringUtils.hasText(password)) {
errorLabel.setText("用户名和密码不能为空");
errorLabel.setVisible(true);
return;
}
errorLabel.setVisible(false);
// 保存配置
properties.setProperty("user.name", username);
if (remember) {
properties.setProperty("user.password", password);
properties.setProperty("remember.password", "true");
} else {
properties.setProperty("user.password", "");
properties.setProperty("remember.password", "false");
}
// 执行登录
login(username, password).whenComplete((v, e) -> {
if (e != null) {
Platform.runLater(() -> {
errorLabel.setText(e.getMessage());
errorLabel.setVisible(true);
// showError("登录失败", e.getMessage());
});
return;
}
Platform.runLater(() -> {
stage.close();
});
});
});
// 创建场景并设置到窗口
Scene scene = new Scene(borderPane, 400, 280);
stage.setScene(scene);
stage.setResizable(false);
stage.showAndWait();
System.out.println("登录窗口关闭");
}
private CompletableFuture<Void> login(String username, String password) {
// 添加详细日志记录服务器URL和请求准备情况
info("正在连接服务器: " + serverUrl);
logger.debug("login方法被调用用户名: " + username);
CompletableFuture<Void> future = new CompletableFuture<>();
try {
while (!SpringApp.isRunning()) {
holder.info("环境准备中,请稍后...");
Thread.sleep(1000);
}
ObjectMapper objectMapper = SpringApp.getBean(ObjectMapper.class);
ObjectNode objectNode = objectMapper.createObjectNode();
objectNode.put("username", username);
objectNode.put("password", password);
objectNode.put("type", "client");
// 将MacIP列表转换为Map<String, String>格式MAC地址->IP地址
List<MacIP> macIpList = getMacAndIP().join();
ObjectNode signNode = objectMapper.createObjectNode();
for (MacIP macIp : macIpList) {
signNode.put(macIp.mac, macIp.ip);
}
objectNode.set("sign", signNode);
// 构建JSON格式的登录请求
RequestBody body = RequestBody.create(objectNode.toString(), JSON);
// 构建并记录完整的请求URL
String loginUrl = serverUrl + "/api/login";
logger.debug("构建登录请求URL: " + loginUrl);
Request request = new Request.Builder()
.url(loginUrl)
.post(body)
.build();
httpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
future.completeExceptionally(
new IOException("登录失败: 无法连接到服务器,请检查网络连接或服务器配置 - " + e.getMessage(), e));
}
@Override
public void onResponse(Call call, Response response) throws IOException {
try {
if (!response.isSuccessful()) {
future.completeExceptionally(
new IOException("登录失败: 服务器返回错误码 - " + response.toString()));
return;
}
ResponseBody body = response.body();
System.out.println("contentType = " + body.contentType());
JsonNode jsonNode = objectMapper.readTree(body.string());
boolean success = jsonNode.get("success").asBoolean(false);
if (!success) {
future.completeExceptionally(
new IOException("登录失败: 服务器返回错误 - " + jsonNode.get("error").asText()));
return;
}
System.out.println("登录成功: " + jsonNode.toString());
// 登录成功后调用新的API端点获取用户信息
Desktop.instance.setActiveEmployeeId(jsonNode.get("employeeId").asInt());
Desktop.instance.setSessionId(jsonNode.get("sessionId").asText());
future.complete(null);
} finally {
// 确保主响应体被关闭
response.close();
}
}
});
} catch (Exception e) {
future.completeExceptionally(new IOException("登录过程中发生错误: " + e.getMessage(), e));
}
return future;
}
CompletableFuture<List<MacIP>> getMacAndIP() {
return CompletableFuture.supplyAsync(() -> {
List<MacIP> list = new ArrayList<>();
try {
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
NetworkInterface anInterface = interfaces.nextElement();
if (anInterface.isLoopback() || !anInterface.isUp()) {
continue;
}
byte[] hardwareAddress = anInterface.getHardwareAddress();
if (hardwareAddress == null) {
continue;
}
Enumeration<InetAddress> inetAddresses = anInterface.getInetAddresses();
if (!inetAddresses.hasMoreElements()) {
continue;
}
// -分割16进制表示法
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hardwareAddress.length; i++) {
sb.append(
String.format("%02X%s", hardwareAddress[i], i < hardwareAddress.length - 1 ? "-" : ""));
}
String mac = sb.toString();
while (inetAddresses.hasMoreElements()) {
InetAddress inetAddress = inetAddresses.nextElement();
if (inetAddress.getHostAddress().contains(":")) {
continue; // 跳过IPv6地址
}
list.add(new MacIP(mac, inetAddress.getHostAddress()));
}
}
} catch (SocketException e) {
throw new RuntimeException(e);
}
return list;
});
}
// WebSocket消息发送方法
public void sendMessage(String message) {
if (webSocket != null) {
webSocket.send(message);
}
}
// 关闭WebSocket连接
public void closeWebSocket() {
if (webSocket != null) {
webSocket.close(1000, "正常关闭");
webSocket = null;
}
}
static class MacIP {
String mac;
String ip;
public MacIP(String mac, String ip) {
this.mac = mac;
this.ip = ip;
}
}
}

View File

@@ -0,0 +1,133 @@
package com.ecep.contract.controller;
import java.io.File;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import com.ecep.contract.constant.CompanyCustomerConstant;
import com.ecep.contract.constant.CompanyVendorConstant;
import com.ecep.contract.constant.ContractConstant;
import com.ecep.contract.util.StringConfig;
import jakarta.annotation.PreDestroy;
import javafx.event.ActionEvent;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser;
@Lazy
@Scope("prototype")
@Component
public class SysConfWindowController extends BaseController {
private static final Logger logger = LoggerFactory.getLogger(SysConfWindowController.class);
public Label companyContractPathLabel;
public TextField u8DataBaseServerHostField;
public TextField u8DataBaseCatalogField;
public TextField u8DataBaseUserNameField;
public TextField u8DataBasePasswordField;
public Label vendorPathLabel;
public Label vendorEvaluationFormTemplateLabel;
public Label customerPathLabel;
public Label customerEvaluationFormTemplateLabel;
public Label customerSaleBookPathLabel;
StringConfig contractPathConfig = new StringConfig(ContractConstant.KEY_BASE_PATH);
StringConfig vendorPathConfig = new StringConfig(CompanyVendorConstant.KEY_BASE_PATH);
StringConfig vendorEvaluationFormTemplateConfig = new StringConfig(
CompanyVendorConstant.KEY_EVALUATION_FORM_TEMPLATE);
StringConfig customerPathConfig = new StringConfig(CompanyCustomerConstant.KEY_BASE_PATH);
StringConfig customerEvaluationFormTemplateConfig = new StringConfig(
CompanyCustomerConstant.KEY_EVALUATION_FORM_TEMPLATE);
StringConfig customerSaleBookPathConfig = new StringConfig(CompanyCustomerConstant.KEY_SALEBOOK_PATH);
public void initialize() {
contractPathConfig.setControl(companyContractPathLabel);
contractPathConfig.initialize();
vendorPathConfig.setControl(vendorPathLabel);
vendorPathConfig.initialize();
vendorEvaluationFormTemplateConfig.setControl(vendorEvaluationFormTemplateLabel);
vendorEvaluationFormTemplateConfig.initialize();
customerPathConfig.setControl(customerPathLabel);
customerPathConfig.initialize();
customerEvaluationFormTemplateConfig.setControl(customerEvaluationFormTemplateLabel);
customerEvaluationFormTemplateConfig.initialize();
customerSaleBookPathConfig.setControl(customerSaleBookPathLabel);
customerSaleBookPathConfig.initialize();
logger.debug("#initialize()");
}
private void directoryChoose(StringConfig config, String title, String key, ActionEvent event) {
DirectoryChooser chooser = new DirectoryChooser();
chooser.setTitle(title);
File value = new File(config.getProperty().getValue());
chooser.setInitialDirectory(value);
Node node = (Node) event.getSource();
File selected = chooser.showDialog(node.getScene().getWindow());
if (selected != null) {
config.getProperty().setValue(selected.getAbsolutePath());
config.save();
}
}
public void changeCompanyContractPath(ActionEvent actionEvent) {
directoryChoose(contractPathConfig, "请选择合同目录", ContractConstant.KEY_BASE_PATH, actionEvent);
}
public void changeVendorPath(ActionEvent actionEvent) {
directoryChoose(vendorPathConfig, "请选择供应商目录", CompanyVendorConstant.KEY_BASE_PATH, actionEvent);
}
public void changeCustomerPath(ActionEvent actionEvent) {
directoryChoose(customerPathConfig, "请选择客户目录", CompanyCustomerConstant.KEY_BASE_PATH, actionEvent);
}
public void changeCustomerSaleBookPath(ActionEvent actionEvent) {
directoryChoose(customerSaleBookPathConfig, "请选择销售台账目录", CompanyCustomerConstant.KEY_SALEBOOK_PATH, actionEvent);
}
// 模拟销毁方法
@PreDestroy
public void destroy() {
}
private void fileChoose(StringConfig config, String title, String key, ActionEvent event) {
FileChooser chooser = new FileChooser();
chooser.setTitle(title);
File value = new File(config.getProperty().getValue());
chooser.setInitialDirectory(value.getParentFile());
chooser.setInitialFileName(value.getName());
chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(" 模板文件(*.xlsx)", "*.xlsx"));
Node node = (Node) event.getSource();
File selected = chooser.showOpenDialog(node.getScene().getWindow());
if (selected != null) {
config.getProperty().setValue(selected.getAbsolutePath());
config.save();
}
}
public void changeCustomerEvaluationFormTemplate(ActionEvent actionEvent) {
fileChoose(customerEvaluationFormTemplateConfig, "请选择客户资信评估表模板",
CompanyCustomerConstant.KEY_EVALUATION_FORM_TEMPLATE, actionEvent);
}
public void changeVendorEvaluationFormTemplate(ActionEvent actionEvent) {
fileChoose(vendorEvaluationFormTemplateConfig, "请选择供方调查评价表模板",
CompanyVendorConstant.KEY_EVALUATION_FORM_TEMPLATE,
actionEvent);
}
}

View File

@@ -1,18 +1,25 @@
package com.ecep.contract.manager.ui.task; package com.ecep.contract.controller;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level; import java.util.logging.Level;
import com.ecep.contract.util.FxmlPath;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.ecep.contract.manager.Desktop; import com.ecep.contract.Desktop;
import com.ecep.contract.manager.ui.BaseController; import com.ecep.contract.Message;
import com.ecep.contract.manager.ui.FxmlPath; import com.ecep.contract.MyDateTimeUtils;
import com.ecep.contract.manager.ui.Message; import com.ecep.contract.task.MonitoredTask;
import com.ecep.contract.manager.util.MyDateTimeUtils; import com.ecep.contract.task.TaskHistory;
import com.ecep.contract.task.TaskMonitorCenter;
import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.SimpleStringProperty;
import javafx.event.ActionEvent;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.scene.control.Alert; import javafx.scene.control.Alert;
import javafx.scene.control.Button; import javafx.scene.control.Button;
@@ -69,10 +76,47 @@ public class TaskMonitorViewController extends BaseController {
private Button cancelTaskButton; private Button cancelTaskButton;
@FXML @FXML
private Button clearHistoryButton; private Button clearHistoryButton;
@FXML
private Button refreshExecutorInfoButton;
@FXML
private TableView<ExecutorInfo> executorInfoTable;
@FXML
private TableColumn<ExecutorInfo, String> executorFieldColumn;
@FXML
private TableColumn<ExecutorInfo, String> executorValueColumn;
@FXML
private TableColumn<ExecutorInfo, String> executorDescriptionColumn;
public TaskMonitorViewController() { public TaskMonitorViewController() {
} }
/**
* 用于存储ExecutorService信息的内部类
*/
public static class ExecutorInfo {
private final String field;
private final String value;
private final String description;
public ExecutorInfo(String field, String value, String description) {
this.field = field;
this.value = value;
this.description = description;
}
public String getField() {
return field;
}
public String getValue() {
return value;
}
public String getDescription() {
return description;
}
}
@Override @Override
public void onShown(WindowEvent windowEvent) { public void onShown(WindowEvent windowEvent) {
super.onShown(windowEvent); super.onShown(windowEvent);
@@ -144,6 +188,94 @@ public class TaskMonitorViewController extends BaseController {
}); });
cancelTaskButton.disableProperty().bind(activeTasksTable.getSelectionModel().selectedItemProperty().isNull()); cancelTaskButton.disableProperty().bind(activeTasksTable.getSelectionModel().selectedItemProperty().isNull());
// 初始化Executor信息表格
initializeExecutorInfoTable();
}
/**
* 初始化Executor信息表格
*/
private void initializeExecutorInfoTable() {
executorFieldColumn.setCellValueFactory(param -> new SimpleStringProperty(param.getValue().getField()));
executorValueColumn.setCellValueFactory(param -> new SimpleStringProperty(param.getValue().getValue()));
executorDescriptionColumn
.setCellValueFactory(param -> new SimpleStringProperty(param.getValue().getDescription()));
// 初始加载Executor信息
refreshExecutorInfo();
// 绑定刷新按钮事件
refreshExecutorInfoButton.setOnAction(event -> refreshExecutorInfo());
}
/**
* 刷新Executor信息
*/
@FXML
private void refreshExecutorInfo() {
executorInfoTable.getItems().clear();
try {
ExecutorService executorService = Desktop.instance.getExecutorService();
if (executorService instanceof ThreadPoolExecutor threadPoolExecutor) {
executorInfoTable.getItems().add(new ExecutorInfo(
"PoolSize",
String.valueOf(threadPoolExecutor.getPoolSize()),
"PoolSize"));
executorInfoTable.getItems().add(new ExecutorInfo(
"活动线程数",
String.valueOf(threadPoolExecutor.getActiveCount()),
"当前正在执行任务的线程数"));
// 添加线程池信息
executorInfoTable.getItems().add(new ExecutorInfo(
"核心线程数",
String.valueOf(threadPoolExecutor.getCorePoolSize()),
"线程池维护的最小线程数"));
executorInfoTable.getItems().add(new ExecutorInfo(
"最大线程数",
String.valueOf(threadPoolExecutor.getMaximumPoolSize()),
"线程池允许的最大线程数"));
executorInfoTable.getItems().add(new ExecutorInfo(
"KeepAliveTime",
String.valueOf(threadPoolExecutor.getKeepAliveTime(TimeUnit.SECONDS)),
"the thread keep-alive time, which is the amount of time that threads may remain idle before being terminated. Threads that wait this amount of time without processing a task will be terminated if there are more than the core number of threads currently in the pool, or if this pool allows core thread timeout."));
executorInfoTable.getItems().add(new ExecutorInfo(
"任务队列大小",
String.valueOf(threadPoolExecutor.getQueue().size()),
"等待执行的任务数量"));
executorInfoTable.getItems().add(new ExecutorInfo(
"已完成任务数",
String.valueOf(threadPoolExecutor.getCompletedTaskCount()),
"已完成执行的任务总数"));
executorInfoTable.getItems().add(new ExecutorInfo(
"LargestPoolSize",
String.valueOf(threadPoolExecutor.getLargestPoolSize()),
"线程池当前状态"));
// 如果是ScheduledExecutorService添加额外信息
if (executorService instanceof ScheduledExecutorService) {
executorInfoTable.getItems().add(new ExecutorInfo(
"线程池类型",
"ScheduledExecutorService",
"可调度的线程池"));
} else {
executorInfoTable.getItems().add(new ExecutorInfo(
"线程池类型",
"ThreadPoolExecutor",
"普通线程池"));
}
} else {
executorInfoTable.getItems().add(new ExecutorInfo(
"错误",
"未知的ExecutorService类型",
"无法获取线程池详细信息"));
}
} catch (Exception e) {
executorInfoTable.getItems().add(new ExecutorInfo(
"异常",
e.getMessage(),
"获取ExecutorService信息时发生错误"));
}
} }
/** /**
@@ -218,4 +350,11 @@ public class TaskMonitorViewController extends BaseController {
alert.getDialogPane().setContent(scrollPane); alert.getDialogPane().setContent(scrollPane);
alert.showAndWait(); alert.showAndWait();
} }
/**
* 运行任务监控演示
*/
public void onRunTaskMonitorDemo(ActionEvent event) {
com.ecep.contract.task.DemoTask.runDemo();
}
} }

View File

@@ -0,0 +1,11 @@
package com.ecep.contract.controller;
import com.ecep.contract.MessageHolder;
import com.ecep.contract.task.Tasker;
public class VendorClassSyncTask extends Tasker<Object> {
@Override
public Object execute(MessageHolder holder) {
return null;
}
}

View File

@@ -0,0 +1,69 @@
package com.ecep.contract.controller;
import org.controlsfx.control.ToggleSwitch;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import com.ecep.contract.constant.CloudYuConstant;
import com.ecep.contract.util.BooleanConfig;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.LocalDateConfig;
import com.ecep.contract.util.LocalDateTimeConfig;
import com.ecep.contract.util.StringConfig;
import javafx.fxml.FXML;
import javafx.scene.control.DatePicker;
import javafx.scene.control.TextField;
import javafx.stage.WindowEvent;
@Lazy
@Scope("prototype")
@Component
@FxmlPath("/ui/cloud/u8_config.fxml")
public class YongYouU8ConfigWindowController extends BaseController {
@FXML
private DatePicker auto_create_company_after;
@FXML
private TextField contract_latest_date;
@FXML
private TextField contract_latest_id;
@FXML
private TextField sync_elapse;
@FXML
private ToggleSwitch use_latest_id;
LocalDateConfig config1 = new LocalDateConfig(CloudYuConstant.KEY_AUTO_CREATE_COMPANY_AFTER);
LocalDateTimeConfig config2 = new LocalDateTimeConfig(CloudYuConstant.KEY_SYNC_BY_LATEST_DATE);
StringConfig config3 = new StringConfig(CloudYuConstant.KEY_SYNC_BY_LATEST_ID);
StringConfig config4 = new StringConfig(CloudYuConstant.KEY_SYNC_ELAPSE);
BooleanConfig config5 = new BooleanConfig(CloudYuConstant.KEY_SYNC_USE_LATEST_ID);
@Override
public void onShown(WindowEvent windowEvent) {
super.onShown(windowEvent);
getTitle().set("用友U8配置");
auto_create_company_after.setConverter(getCurrentEmployee().getLocalDateStringConverter());
config1.setControl(auto_create_company_after);
config1.initialize();
config2.setControl(contract_latest_date);
config2.setControlConverter(getCurrentEmployee().getLocalDateTimeStringConverter());
config2.initialize();
config3.setControl(contract_latest_id);
config3.initialize();
config4.setControl(sync_elapse);
config4.initialize();
config5.setControl(use_latest_id);
config5.initialize();
}
}

View File

@@ -0,0 +1,90 @@
package com.ecep.contract.controller;
import com.ecep.contract.controller.company.CompanyWindowController;
import com.ecep.contract.controller.table.cell.CompanyTableCell;
import com.ecep.contract.controller.table.cell.LocalDateTimeTableCell;
import com.ecep.contract.model.Company;
import com.ecep.contract.service.CompanyService;
import com.ecep.contract.service.YongYouU8Service;
import com.ecep.contract.util.ProxyUtils;
import com.ecep.contract.vm.CloudYuInfoViewModel;
import com.ecep.contract.vo.CloudYuVo;
import com.ecep.contract.vo.CompanyVo;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
public class YongYouU8ManagerSkin
extends
AbstEntityManagerSkin<CloudYuVo, CloudYuInfoViewModel, YongYouU8ManagerSkin, YongYouU8ManagerWindowController>
implements ManagerSkin {
public YongYouU8ManagerSkin(YongYouU8ManagerWindowController controller) {
super(controller);
}
YongYouU8Service getU8Service() {
return getBean(YongYouU8Service.class);
}
CompanyService getCompanyService() {
return getBean(CompanyService.class);
}
@Override
public void initializeTable() {
controller.idColumn.setCellValueFactory(param -> param.getValue().getId());
controller.companyColumn.setCellValueFactory(param -> param.getValue().getCompany());
controller.companyColumn.setCellFactory(param -> new CompanyTableCell<>(getCompanyService()));
controller.cloudIdColumn.setCellValueFactory(param -> param.getValue().getCloudId());
controller.latestUpdateColumn.setCellValueFactory(param -> param.getValue().getLatest());
controller.latestUpdateColumn.setCellFactory(param -> new LocalDateTimeTableCell<>());
controller.cloudLatestColumn.setCellValueFactory(param -> param.getValue().getCloudLatest());
controller.cloudLatestColumn.setCellFactory(param -> new LocalDateTimeTableCell<>());
controller.descriptionColumn.setCellValueFactory(param -> param.getValue().getVendorCode());
}
@Override
protected void createContextMenu(ContextMenu contextMenu) {
MenuItem item2 = new MenuItem("刷新");
item2.setOnAction(this::onTableRefreshAction);
MenuItem item3 = new MenuItem("清空备注");
item3.setOnAction(this::onTableClearDescriptionAction);
contextMenu.getItems().addAll(item2, item3);
}
/**
* 请空选择行的注释
*
* @param event event
*/
public void onTableClearDescriptionAction(ActionEvent event) {
ObservableList<CloudYuInfoViewModel> selectedItems = getTableView().getSelectionModel().getSelectedItems();
if (selectedItems.isEmpty()) {
return;
}
for (CloudYuInfoViewModel selectedItem : selectedItems) {
CloudYuVo yongYouU8Vo = getU8Service().findById(selectedItem.getId().get());
selectedItem.getCustomerCode().set("");
if (selectedItem.copyTo(yongYouU8Vo)) {
CloudYuVo saved = getU8Service().save(yongYouU8Vo);
selectedItem.update(saved);
}
}
}
@Override
protected void onTableRowDoubleClickedAction(CloudYuInfoViewModel item) {
Integer companyId = item.getCompany().get();
CompanyVo company = getCompanyService().findById(companyId);
CompanyWindowController.show(company, getTableView().getScene().getWindow());
}
}

View File

@@ -0,0 +1,118 @@
package com.ecep.contract.controller;
import java.time.LocalDateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import com.ecep.contract.Desktop;
import com.ecep.contract.service.YongYouU8Service;
import com.ecep.contract.task.ContractSyncTask;
import com.ecep.contract.task.CustomerSyncTask;
import com.ecep.contract.task.EmployeesSyncTask;
import com.ecep.contract.task.VendorSyncTask;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.CloudYuInfoViewModel;
import com.ecep.contract.vo.CloudYuVo;
import javafx.event.ActionEvent;
import javafx.scene.control.TableColumn;
import javafx.stage.Stage;
@Lazy
@Scope("prototype")
@Component
@FxmlPath("/ui/cloud/u8_manager.fxml")
public class YongYouU8ManagerWindowController
extends AbstManagerWindowController<CloudYuVo, CloudYuInfoViewModel, YongYouU8ManagerSkin> {
private static final Logger logger = LoggerFactory.getLogger(YongYouU8ManagerWindowController.class);
public static void show() {
show(YongYouU8ManagerWindowController.class, null);
}
public TableColumn<CloudYuInfoViewModel, Number> idColumn;
public TableColumn<CloudYuInfoViewModel, LocalDateTime> latestUpdateColumn;
public TableColumn<CloudYuInfoViewModel, Integer> companyColumn;
public TableColumn<CloudYuInfoViewModel, String> cloudIdColumn;
public TableColumn<CloudYuInfoViewModel, LocalDateTime> cloudLatestColumn;
public TableColumn<CloudYuInfoViewModel, String> descriptionColumn;
@Override
public YongYouU8Service getViewModelService() {
return getSkin().getU8Service();
}
@Override
protected YongYouU8ManagerSkin createDefaultSkin() {
return new YongYouU8ManagerSkin(this);
}
@Override
public void show(Stage stage) {
super.show(stage);
getTitle().set("用友U8");
}
/**
* 打开配置窗口
*/
public void onConfigAction(ActionEvent event) {
BaseController.show(YongYouU8ConfigWindowController.class, null);
}
public void onPersonSyncAction(ActionEvent event) {
EmployeesSyncTask task = new EmployeesSyncTask();
UITools.showTaskDialogAndWait("员工数据同步", task, null);
}
public void onContractSyncAction(ActionEvent event) {
ContractSyncTask task = new ContractSyncTask();
UITools.showTaskDialogAndWait("合同数据增量同步", task, null);
}
public void onContractAllSyncAction(ActionEvent event) {
ContractSyncAllTask task = new ContractSyncAllTask();
UITools.showTaskDialogAndWait("合同数据全量同步", task, null);
}
public void onVendorSyncAction(ActionEvent event) {
VendorSyncTask task = new VendorSyncTask();
UITools.showTaskDialogAndWait("供应商数据同步", task, null);
}
public void onCustomerSyncAction(ActionEvent event) {
CustomerSyncTask task = new CustomerSyncTask();
UITools.showTaskDialogAndWait("客户数据同步", task, null);
}
public void onContractGroupSyncAction(ActionEvent event) {
ContractGroupSyncTask task = new ContractGroupSyncTask();
Desktop.instance.getTaskMonitorCenter().registerAndStartTask(task);
}
public void onContractTypeSyncAction(ActionEvent event) {
ContractTypeSyncTask task = new ContractTypeSyncTask();
Desktop.instance.getTaskMonitorCenter().registerAndStartTask(task);
}
public void onContractKindSyncAction(ActionEvent event) {
ContractKindSyncTask task = new ContractKindSyncTask();
Desktop.instance.getTaskMonitorCenter().registerAndStartTask(task);
}
public void onVendorClassSyncAction(ActionEvent event) {
VendorClassSyncTask task = new VendorClassSyncTask();
Desktop.instance.getTaskMonitorCenter().registerAndStartTask(task);
}
public void onCustomerClassSyncAction(ActionEvent event) {
CustomerClassSyncTask task = new CustomerClassSyncTask();
Desktop.instance.getTaskMonitorCenter().registerAndStartTask(task);
}
}

View File

@@ -1,17 +1,18 @@
package com.ecep.contract.manager.ds.other.controller.bank; package com.ecep.contract.controller.bank;
import com.ecep.contract.controller.AbstEntityManagerSkin;
import com.ecep.contract.controller.ManagerSkin;
import com.ecep.contract.controller.table.EditableEntityTableTabSkin;
import com.ecep.contract.vm.BankViewModel;
import com.ecep.contract.vo.BankVo;
import com.ecep.contract.manager.ds.other.model.Bank;
import com.ecep.contract.manager.ds.other.vo.BankViewModel;
import com.ecep.contract.manager.ui.AbstEntityManagerSkin;
import com.ecep.contract.manager.ui.table.EditableEntityTableTabSkin;
import com.ecep.contract.manager.ui.ManagerSkin;
import javafx.scene.control.TableColumn; import javafx.scene.control.TableColumn;
import javafx.scene.control.cell.TextFieldTableCell; import javafx.scene.control.cell.TextFieldTableCell;
public class BankManagerSkin public class BankManagerSkin
extends AbstEntityManagerSkin<Bank, BankViewModel, BankManagerSkin, BankManagerWindowController> extends AbstEntityManagerSkin<BankVo, BankViewModel, BankManagerSkin, BankManagerWindowController>
implements ManagerSkin, EditableEntityTableTabSkin<Bank, BankViewModel> { implements ManagerSkin, EditableEntityTableTabSkin<BankVo, BankViewModel> {
public BankManagerSkin(BankManagerWindowController controller) { public BankManagerSkin(BankManagerWindowController controller) {
super(controller); super(controller);

View File

@@ -1,23 +1,25 @@
package com.ecep.contract.manager.ds.other.controller.bank; package com.ecep.contract.controller.bank;
import com.ecep.contract.manager.ds.other.model.Bank;
import com.ecep.contract.manager.ds.other.service.BankService;
import com.ecep.contract.manager.ds.other.vo.BankViewModel;
import com.ecep.contract.manager.ui.AbstManagerWindowController;
import com.ecep.contract.manager.ui.FxmlPath;
import javafx.event.ActionEvent;
import javafx.scene.control.TableColumn;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.ecep.contract.controller.AbstManagerWindowController;
import com.ecep.contract.service.BankService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.vm.BankViewModel;
import com.ecep.contract.vo.BankVo;
import javafx.event.ActionEvent;
import javafx.scene.control.TableColumn;
@Lazy @Lazy
@Scope("prototype") @Scope("prototype")
@Component @Component
@FxmlPath("/ui/bank-manager.fxml") @FxmlPath("/ui/bank-manager.fxml")
public class BankManagerWindowController public class BankManagerWindowController
extends AbstManagerWindowController<Bank, BankViewModel, BankManagerSkin> { extends AbstManagerWindowController<BankVo, BankViewModel, BankManagerSkin> {
@Autowired @Autowired
private BankService bankService; private BankService bankService;

View File

@@ -0,0 +1,59 @@
package com.ecep.contract.controller.bank.account;
import com.ecep.contract.controller.company.CompanyWindowController;
import com.ecep.contract.controller.tab.AbstEntityBasedTabSkin;
import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.service.BankService;
import com.ecep.contract.service.CompanyService;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.CompanyBankAccountViewModel;
import com.ecep.contract.vo.CompanyBankAccountVo;
import com.ecep.contract.vo.CompanyVo;
import javafx.scene.control.Tab;
public class BankAccountBaseTabSkin
extends AbstEntityBasedTabSkin<BankAccountWindowController, CompanyBankAccountVo, CompanyBankAccountViewModel>
implements TabSkin {
public BankAccountBaseTabSkin(BankAccountWindowController controller) {
super(controller);
viewModel = controller.getViewModel();
}
@Override
public Tab getTab() {
return controller.baseInfoTab;
}
@Override
public void initializeTab() {
UITools.autoCompletion(controller.companyField, viewModel.getCompanyId(), getCompanyService());
UITools.autoCompletion(controller.bankField, viewModel.getBankId(), getBankService());
controller.openingBankField.textProperty().bindBidirectional(viewModel.getOpeningBank());
controller.bankAccountField.textProperty().bindBidirectional(viewModel.getAccount());
// controller.descriptionField.textProperty().bindBidirectional(viewModel.getDescription());
controller.createdField.textProperty().bind(viewModel.getCreated().asString());
controller.versionLabel.textProperty().bind(viewModel.getVersion().asString());
controller.relativeCompanyBtn.disableProperty().bind(viewModel.getCompanyId().isNull());
controller.relativeCompanyBtn.setOnAction(event -> {
Integer companyId = viewModel.getCompanyId().get();
if (companyId != null) {
CompanyVo company = getCompanyService().findById(companyId);
CompanyWindowController.show(company, controller.root.getScene().getWindow());
}
});
}
public BankService getBankService() {
return getCachedBean(BankService.class);
}
public CompanyService getCompanyService() {
return getCachedBean(CompanyService.class);
}
}

View File

@@ -1,24 +1,32 @@
package com.ecep.contract.manager.ds.company.controller.bank_account; package com.ecep.contract.controller.bank.account;
import com.ecep.contract.manager.ds.company.model.CompanyBankAccount;
import com.ecep.contract.manager.ds.company.service.CompanyBankAccountService;
import com.ecep.contract.manager.ds.company.vo.CompanyBankAccountViewModel;
import com.ecep.contract.manager.ui.AbstEntityController;
import com.ecep.contract.manager.ui.FxmlPath;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.stage.Window;
import javafx.stage.WindowEvent;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.ecep.contract.controller.AbstEntityController;
import com.ecep.contract.model.CompanyBankAccount;
import com.ecep.contract.service.CompanyBankAccountService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.vm.CompanyBankAccountViewModel;
import com.ecep.contract.vo.CompanyBankAccountVo;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.stage.Window;
import javafx.stage.WindowEvent;
@Lazy @Lazy
@Scope("prototype") @Scope("prototype")
@Component @Component
@FxmlPath("/ui/company/bank-account.fxml") @FxmlPath("/ui/company/bank-account.fxml")
public class BankAccountWindowController extends AbstEntityController<CompanyBankAccount, CompanyBankAccountViewModel> { public class BankAccountWindowController extends AbstEntityController<CompanyBankAccountVo, CompanyBankAccountViewModel> {
public BorderPane root; public BorderPane root;
public TabPane tabPane; public TabPane tabPane;

View File

@@ -0,0 +1,28 @@
package com.ecep.contract.controller.company;
import com.ecep.contract.controller.tab.AbstEntityBasedTabSkin;
import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.service.CompanyService;
import com.ecep.contract.vm.CompanyViewModel;
import com.ecep.contract.vo.CompanyVo;
import javafx.concurrent.Task;
public abstract class AbstCompanyBasedTabSkin
extends AbstEntityBasedTabSkin<CompanyWindowController, CompanyVo, CompanyViewModel>
implements TabSkin {
public AbstCompanyBasedTabSkin(CompanyWindowController controller) {
super(controller);
}
protected CompanyService getCompanyService() {
Task<CompanyService> task = new Task<>() {
@Override
protected CompanyService call() throws Exception {
return controller.getViewModelService();
}
};
return controller.getViewModelService();
}
}

View File

@@ -0,0 +1,45 @@
package com.ecep.contract.controller.company;
import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.controller.table.AbstEntityTableTabSkin;
import com.ecep.contract.controller.table.TableOfTabSkin;
import com.ecep.contract.model.IdentityEntity;
import com.ecep.contract.service.CompanyService;
import com.ecep.contract.util.ParamUtils;
import com.ecep.contract.vm.CompanyBasedViewModel;
import com.ecep.contract.vm.CompanyViewModel;
import com.ecep.contract.vm.IdentityViewModel;
import com.ecep.contract.vo.CompanyVo;
public abstract class AbstCompanyTableTabSkin<T extends IdentityEntity, TV extends IdentityViewModel<T>>
extends AbstEntityTableTabSkin<CompanyWindowController, CompanyVo, CompanyViewModel, T, TV>
implements TabSkin, TableOfTabSkin<CompanyVo, T, TV> {
public AbstCompanyTableTabSkin(CompanyWindowController controller) {
super(controller);
viewModel = controller.getViewModel();
}
@Override
protected TV createNewViewModel() {
TV model = super.createNewViewModel();
if (model instanceof CompanyBasedViewModel m) {
m.getCompanyId().set(getEntity().getId());
}
return model;
}
protected CompanyService getCompanyService() {
return getParentService();
}
protected CompanyService getParentService() {
return controller.getViewModelService();
}
@Override
public ParamUtils.Builder getSpecification(CompanyVo parent) {
return ParamUtils.builder().equals("company", parent.getId());
}
}

View File

@@ -1,13 +1,32 @@
package com.ecep.contract.manager.ds.company.controller.contact; package com.ecep.contract.controller.company;
import java.lang.reflect.InvocationTargetException;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.CompletableFuture;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import com.ecep.contract.controller.BaseController;
import com.ecep.contract.model.CompanyContact;
import com.ecep.contract.service.CompanyContactService;
import com.ecep.contract.util.FxmlUtils;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.CompanyContactViewModel;
import com.ecep.contract.vo.CompanyContactVo;
import com.ecep.contract.manager.ds.company.model.CompanyContact;
import com.ecep.contract.manager.ds.company.repository.CompanyContactRepository;
import com.ecep.contract.manager.ui.BaseController;
import com.ecep.contract.manager.ds.company.vo.CompanyContactViewModel;
import com.ecep.contract.manager.util.FxmlUtils;
import com.ecep.contract.manager.util.UITools;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.scene.control.*; import javafx.scene.control.Button;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane; import javafx.scene.layout.BorderPane;
import javafx.stage.Modality; import javafx.stage.Modality;
import javafx.stage.Stage; import javafx.stage.Stage;
@@ -16,22 +35,13 @@ import javafx.stage.WindowEvent;
import javafx.util.converter.LocalDateStringConverter; import javafx.util.converter.LocalDateStringConverter;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.lang.reflect.InvocationTargetException;
import java.time.format.DateTimeFormatter;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
@Lazy @Lazy
@Scope("prototype") @Scope("prototype")
@Component @Component
public class CompanyContactWindowController extends BaseController { public class CompanyContactWindowController extends BaseController {
private static final Logger logger = LoggerFactory.getLogger(CompanyContactWindowController.class); private static final Logger logger = LoggerFactory.getLogger(CompanyContactWindowController.class);
/** /**
* 显示界面 * 显示界面
*/ */
@@ -59,8 +69,9 @@ public class CompanyContactWindowController extends BaseController {
@Getter @Getter
@Setter @Setter
private CompanyContactViewModel viewModel; private CompanyContactViewModel viewModel;
@Autowired @Autowired
private CompanyContactRepository companyContactRepository; private CompanyContactService companyContactService;
public TextField nameField; public TextField nameField;
public TextField positionField; public TextField positionField;
@@ -73,12 +84,13 @@ public class CompanyContactWindowController extends BaseController {
public Label versionLabel; public Label versionLabel;
public Button saveBtn; public Button saveBtn;
private CompletableFuture<CompanyContact> companyContactLoadedFuture; private CompletableFuture<CompanyContactVo> companyContactLoadedFuture;
@Override @Override
public void show(Stage stage) { public void show(Stage stage) {
super.show(stage); super.show(stage);
getTitle().bind(viewModel.getName().map(v -> "[" + viewModel.getId().get() + "] " + viewModel.getName().getValue() + " 曾用名详情")); getTitle().bind(viewModel.getName()
.map(v -> "[" + viewModel.getId().get() + "] " + viewModel.getName().getValue() + " 曾用名详情"));
} }
@Override @Override
@@ -91,9 +103,7 @@ public class CompanyContactWindowController extends BaseController {
initializeBaseTab(); initializeBaseTab();
companyContactLoadedFuture = CompletableFuture.supplyAsync(() -> { companyContactLoadedFuture = CompletableFuture.supplyAsync(() -> {
Optional<CompanyContact> optional = companyContactRepository.findById(viewModel.getId().get()); CompanyContactVo oldName = companyContactService.findById(viewModel.getId().get());
if (optional.isPresent()) {
CompanyContact oldName = optional.get();
Platform.runLater(() -> { Platform.runLater(() -> {
viewModel.update(oldName); viewModel.update(oldName);
viewModel.bindListener(); viewModel.bindListener();
@@ -103,12 +113,9 @@ public class CompanyContactWindowController extends BaseController {
tabPane.getSelectionModel().getSelectedItem().getOnSelectionChanged().handle(null); tabPane.getSelectionModel().getSelectedItem().getOnSelectionChanged().handle(null);
}); });
return oldName; return oldName;
}
return null;
}); });
} }
private void initializeBaseTab() { private void initializeBaseTab() {
baseInfoTab.setOnSelectionChanged(event -> { baseInfoTab.setOnSelectionChanged(event -> {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
@@ -121,9 +128,9 @@ public class CompanyContactWindowController extends BaseController {
saveBtn.disableProperty().bind(viewModel.getChanged().not()); saveBtn.disableProperty().bind(viewModel.getChanged().not());
saveBtn.setOnAction(event -> { saveBtn.setOnAction(event -> {
try { try {
CompanyContact contact = companyContactLoadedFuture.join(); CompanyContactVo contact = companyContactLoadedFuture.join();
viewModel.copyTo(contact); viewModel.copyTo(contact);
CompanyContact saved = companyContactRepository.save(contact); CompanyContactVo saved = companyContactService.save(contact);
viewModel.update(saved); viewModel.update(saved);
companyContactLoadedFuture = CompletableFuture.completedFuture(saved); companyContactLoadedFuture = CompletableFuture.completedFuture(saved);
} catch (Exception e) { } catch (Exception e) {
@@ -176,4 +183,3 @@ public class CompanyContactWindowController extends BaseController {
super.onHidden(windowEvent); super.onHidden(windowEvent);
} }
} }

View File

@@ -1,22 +1,22 @@
package com.ecep.contract.manager.ds.company.controller; package com.ecep.contract.controller.company;
import java.util.List;
import java.util.Optional;
import com.ecep.contract.controller.AbstEntityManagerSkin;
import com.ecep.contract.service.CompanyOldNameService;
import com.ecep.contract.service.CompanyService;
import com.ecep.contract.vm.CompanyViewModel;
import com.ecep.contract.vo.CompanyVo;
import com.ecep.contract.manager.ds.company.model.Company;
import com.ecep.contract.manager.ds.company.service.CompanyOldNameService;
import com.ecep.contract.manager.ds.company.service.CompanyService;
import com.ecep.contract.manager.ds.company.vo.CompanyViewModel;
import com.ecep.contract.manager.ui.AbstEntityManagerSkin;
import com.ecep.contract.manager.ui.ManagerSkin;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.scene.control.Alert; import javafx.scene.control.Alert;
import javafx.scene.control.TextInputDialog; import javafx.scene.control.TextInputDialog;
import lombok.Setter; import lombok.Setter;
import java.util.List;
import java.util.Optional;
public class CompanyManagerSkin public class CompanyManagerSkin
extends AbstEntityManagerSkin<Company, CompanyViewModel, CompanyManagerSkin, CompanyManagerWindowController> { extends AbstEntityManagerSkin<CompanyVo, CompanyViewModel, CompanyManagerSkin, CompanyManagerWindowController> {
@Setter @Setter
private CompanyOldNameService companyOldNameService; private CompanyOldNameService companyOldNameService;
@@ -65,11 +65,11 @@ public class CompanyManagerSkin
if (optional.isPresent()) { if (optional.isPresent()) {
CompanyService companyService = getCompanyService(); CompanyService companyService = getCompanyService();
String newCompanyName = optional.get(); String newCompanyName = optional.get();
List<Company> list = companyService.findAllByName(newCompanyName); List<CompanyVo> list = companyService.findAllByName(newCompanyName);
if (list == null || list.isEmpty()) { if (list == null || list.isEmpty()) {
// 未登记过 // 未登记过
Company company = companyService.createNewCompany(newCompanyName); CompanyVo company = companyService.createNewCompany(newCompanyName);
Company saved = companyService.save(company); CompanyVo saved = companyService.save(company);
CompanyWindowController.show(saved, getTableView().getScene().getWindow()); CompanyWindowController.show(saved, getTableView().getScene().getWindow());
} else { } else {
Alert alert = new Alert(Alert.AlertType.INFORMATION); Alert alert = new Alert(Alert.AlertType.INFORMATION);

View File

@@ -1,4 +1,4 @@
package com.ecep.contract.manager.ds.company.controller; package com.ecep.contract.controller.company;
import java.time.LocalDate; import java.time.LocalDate;
@@ -7,13 +7,13 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.ecep.contract.manager.ds.company.model.Company; import com.ecep.contract.controller.AbstManagerWindowController;
import com.ecep.contract.manager.ds.company.service.CompanyService; import com.ecep.contract.service.CompanyService;
import com.ecep.contract.manager.ds.company.tasker.CompanyFilesRebuildTasker; import com.ecep.contract.task.CompanyFilesRebuildTasker;
import com.ecep.contract.manager.ds.company.vo.CompanyViewModel; import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.manager.ui.AbstManagerWindowController; import com.ecep.contract.util.UITools;
import com.ecep.contract.manager.ui.FxmlPath; import com.ecep.contract.vo.CompanyVo;
import com.ecep.contract.manager.util.UITools; import com.ecep.contract.vm.CompanyViewModel;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.fxml.FXML; import javafx.fxml.FXML;
@@ -25,7 +25,7 @@ import javafx.stage.Stage;
@Component @Component
@FxmlPath("/ui/company/company-manager.fxml") @FxmlPath("/ui/company/company-manager.fxml")
public class CompanyManagerWindowController public class CompanyManagerWindowController
extends AbstManagerWindowController<Company, CompanyViewModel, CompanyManagerSkin> { extends AbstManagerWindowController<CompanyVo, CompanyViewModel, CompanyManagerSkin> {
// columns // columns
@FXML @FXML

View File

@@ -1,11 +1,12 @@
package com.ecep.contract.manager.ds.company.controller; package com.ecep.contract.controller.company;
import com.ecep.contract.manager.ui.BaseController;
import com.ecep.contract.manager.ui.FxmlPath;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.ecep.contract.controller.BaseController;
import com.ecep.contract.util.FxmlPath;
@Lazy @Lazy
@Scope("prototype") @Scope("prototype")
@Component @Component

View File

@@ -1,32 +1,8 @@
package com.ecep.contract.manager.ds.company.controller; package com.ecep.contract.controller.company;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import com.ecep.contract.manager.SpringApp;
import com.ecep.contract.manager.ds.company.model.Company;
import com.ecep.contract.manager.ds.company.service.CompanyFileService;
import com.ecep.contract.manager.ds.company.service.CompanyService;
import com.ecep.contract.manager.ds.company.tasker.CompanyCompositeUpdateTasker;
import com.ecep.contract.manager.ds.company.tasker.CompanyVerifyTasker;
import com.ecep.contract.manager.ds.company.vo.CompanyViewModel;
import com.ecep.contract.manager.ds.contract.service.ContractService;
import com.ecep.contract.manager.ds.customer.controller.CompanyCustomerWindowController;
import com.ecep.contract.manager.ds.customer.model.CompanyCustomer;
import com.ecep.contract.manager.ds.customer.service.CompanyCustomerService;
import com.ecep.contract.manager.ds.vendor.controller.CompanyVendorWindowController;
import com.ecep.contract.manager.ds.vendor.model.CompanyVendor;
import com.ecep.contract.manager.ds.vendor.service.CompanyVendorService;
import com.ecep.contract.manager.ui.tab.AbstEntityBasedTabSkin;
import com.ecep.contract.manager.ui.AbstEntityController;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.util.DesktopUtils;
import com.ecep.contract.manager.util.UITools;
import javafx.beans.property.SimpleObjectProperty;
import javafx.event.ActionEvent;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import javafx.stage.Window;
import org.hibernate.Hibernate;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -35,25 +11,59 @@ import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import java.util.concurrent.CompletableFuture; import com.ecep.contract.DesktopUtils;
import java.util.function.Function; import com.ecep.contract.controller.AbstEntityController;
import com.ecep.contract.controller.customer.CompanyCustomerWindowController;
import com.ecep.contract.controller.tab.AbstEntityBasedTabSkin;
import com.ecep.contract.controller.tab.CompanyTabSkinBankAccount;
import com.ecep.contract.controller.tab.CompanyTabSkinBase;
import com.ecep.contract.controller.tab.CompanyTabSkinBlackReason;
import com.ecep.contract.controller.tab.CompanyTabSkinContact;
import com.ecep.contract.controller.tab.CompanyTabSkinContract;
import com.ecep.contract.controller.tab.CompanyTabSkinFile;
import com.ecep.contract.controller.tab.CompanyTabSkinInvoice;
import com.ecep.contract.controller.tab.CompanyTabSkinOldName;
import com.ecep.contract.controller.tab.CompanyTabSkinOther;
import com.ecep.contract.controller.tab.CompanyTabSkinPurchaseBillVoucher;
import com.ecep.contract.controller.vendor.CompanyVendorWindowController;
import com.ecep.contract.service.CompanyCustomerService;
import com.ecep.contract.service.CompanyService;
import com.ecep.contract.service.CompanyVendorService;
import com.ecep.contract.task.CompanyCompositeUpdateTasker;
import com.ecep.contract.task.CompanyVerifyTasker;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.CompanyViewModel;
import com.ecep.contract.vo.CompanyCustomerVo;
import com.ecep.contract.vo.CompanyVendorVo;
import com.ecep.contract.vo.CompanyVo;
import javafx.beans.property.SimpleObjectProperty;
import javafx.event.ActionEvent;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.CheckBox;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import javafx.stage.Window;
@Lazy @Lazy
@Scope("prototype") @Scope("prototype")
@Component @Component
@FxmlPath("/ui/company/company.fxml") @FxmlPath("/ui/company/company.fxml")
public class CompanyWindowController public class CompanyWindowController
extends AbstEntityController<Company, CompanyViewModel> { extends AbstEntityController<CompanyVo, CompanyViewModel> {
private static final Logger logger = LoggerFactory.getLogger(CompanyWindowController.class); private static final Logger logger = LoggerFactory.getLogger(CompanyWindowController.class);
public static void show(CompanyVo company, Window window) {
public static void show(Company company, Window window) { show(CompanyViewModel.from(company), window);
CompanyViewModel viewModel = new CompanyViewModel();
if (!Hibernate.isInitialized(company)) {
company = SpringApp.getBean(CompanyService.class).findById(company.getId());
}
viewModel.update(company);
show(viewModel, window);
} }
/** /**
@@ -66,10 +76,6 @@ public class CompanyWindowController
@Autowired @Autowired
private CompanyService companyService; private CompanyService companyService;
@Autowired @Autowired
private CompanyFileService companyFileService;
@Autowired
private ContractService contractService;
@Autowired
private CompanyCustomerService companyCustomerService; private CompanyCustomerService companyCustomerService;
@Autowired @Autowired
private CompanyVendorService companyVendorService; private CompanyVendorService companyVendorService;
@@ -117,12 +123,13 @@ public class CompanyWindowController
public Button companyPathChangeBtn; public Button companyPathChangeBtn;
public Button companyPathSameAsNameBtn; public Button companyPathSameAsNameBtn;
// private final CompanyCustomerViewModel companyCustomerViewModel = new
// CompanyCustomerViewModel();
// private final CompanyVendorViewModel companyVendorViewModel = new
// CompanyVendorViewModel();
// private final CompanyCustomerViewModel companyCustomerViewModel = new CompanyCustomerViewModel(); private final SimpleObjectProperty<CompanyCustomerVo> companyCustomerProperty = new SimpleObjectProperty<>();
// private final CompanyVendorViewModel companyVendorViewModel = new CompanyVendorViewModel(); private final SimpleObjectProperty<CompanyVendorVo> companyVendorProperty = new SimpleObjectProperty<>();
private final SimpleObjectProperty<CompanyCustomer> companyCustomerProperty = new SimpleObjectProperty<>();
private final SimpleObjectProperty<CompanyVendor> companyVendorProperty = new SimpleObjectProperty<>();
public Pane customerTab_pane1; public Pane customerTab_pane1;
public Button customerTab_openBtn; public Button customerTab_openBtn;
@@ -134,7 +141,6 @@ public class CompanyWindowController
public Pane vendorTab_pane2; public Pane vendorTab_pane2;
public Button vendorTab_createBtn; public Button vendorTab_createBtn;
@Override @Override
public void show(Stage stage) { public void show(Stage stage) {
super.show(stage); super.show(stage);
@@ -143,17 +149,6 @@ public class CompanyWindowController
getTitle().set("[" + viewModel.getId().get() + "] " + viewModel.getName().getValue() + " 公司详情"); getTitle().set("[" + viewModel.getId().get() + "] " + viewModel.getName().getValue() + " 公司详情");
} }
@Override
protected Company loadEntity() {
return companyService.findById(viewModel.getId().get());
}
@Override
protected Company saveEntity(Company entity) {
return companyService.save(entity);
}
@Override @Override
protected void registerTabSkins() { protected void registerTabSkins() {
registerTabSkin(baseInfoTab, tab1 -> new CompanyTabSkinBase(this)); registerTabSkin(baseInfoTab, tab1 -> new CompanyTabSkinBase(this));
@@ -161,18 +156,16 @@ public class CompanyWindowController
registerTabSkin(contactTab, tab1 -> new CompanyTabSkinContact(this)); registerTabSkin(contactTab, tab1 -> new CompanyTabSkinContact(this));
registerTabSkin(blackReasonTab, tab1 -> new CompanyTabSkinBlackReason(this)); registerTabSkin(blackReasonTab, tab1 -> new CompanyTabSkinBlackReason(this));
registerTabSkin(bankAccountTab, tab1 -> new CompanyTabSkinBankAccount(this)); registerTabSkin(bankAccountTab, tab1 -> new CompanyTabSkinBankAccount(this));
registerTabSkin(contractTab, this::createContractTabSkin); registerTabSkin(contractTab, tab -> new CompanyTabSkinContract(this));
registerTabSkin(fileTab, this::createFileTabSkin); registerTabSkin(fileTab, tab -> new CompanyTabSkinFile(this));
registerTabSkin(invoiceTab, tab -> new CompanyTabSkinInvoice(this)); registerTabSkin(invoiceTab, tab -> new CompanyTabSkinInvoice(this));
registerTabSkin(purchaseBillVoucherTab, tab -> new CompanyTabSkinPurchaseBillVoucher(this)); registerTabSkin(purchaseBillVoucherTab, tab -> new CompanyTabSkinPurchaseBillVoucher(this));
registerTabSkin(otherTab, tab -> new CompanyTabSkinOther(this)); registerTabSkin(otherTab, tab -> new CompanyTabSkinOther(this));
initializeVendorTab(); initializeVendorTab();
initializeCustomerTab(); initializeCustomerTab();
} }
@Override @Override
protected <K extends AbstEntityBasedTabSkin<?, ?, ?>> K registerTabSkin(Tab tab, Function<Tab, K> func) { protected <K extends AbstEntityBasedTabSkin<?, ?, ?>> K registerTabSkin(Tab tab, Function<Tab, K> func) {
K skin = super.registerTabSkin(tab, func); K skin = super.registerTabSkin(tab, func);
@@ -187,19 +180,6 @@ public class CompanyWindowController
return companyService; return companyService;
} }
private CompanyTabSkinContract createContractTabSkin(Tab tab) {
CompanyTabSkinContract skin = new CompanyTabSkinContract(this);
skin.setContractService(contractService);
return skin;
}
private CompanyTabSkinFile createFileTabSkin(Tab tab) {
CompanyTabSkinFile skin = new CompanyTabSkinFile(this);
skin.setCompanyFileService(companyFileService);
return skin;
}
private void initializeCustomerTab() { private void initializeCustomerTab() {
customerTab.setOnSelectionChanged(event -> { customerTab.setOnSelectionChanged(event -> {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
@@ -210,7 +190,6 @@ public class CompanyWindowController
} }
}); });
customerTab_pane1.visibleProperty().bind(customerTab_pane2.visibleProperty().not()); customerTab_pane1.visibleProperty().bind(customerTab_pane2.visibleProperty().not());
customerTab_pane2.visibleProperty().bind(companyCustomerProperty.isNull()); customerTab_pane2.visibleProperty().bind(companyCustomerProperty.isNull());
customerTab_createBtn.setOnAction(event -> { customerTab_createBtn.setOnAction(event -> {
@@ -283,8 +262,7 @@ public class CompanyWindowController
* 企业合规检查 * 企业合规检查
*/ */
public void onCompanyVerifyAction(ActionEvent event) { public void onCompanyVerifyAction(ActionEvent event) {
Company company = getEntity(); CompanyVo company = getEntity();
CompanyVerifyTasker task = new CompanyVerifyTasker(); CompanyVerifyTasker task = new CompanyVerifyTasker();
task.setCompanyService(companyService); task.setCompanyService(companyService);
task.setCompany(company); task.setCompany(company);
@@ -292,7 +270,7 @@ public class CompanyWindowController
} }
public void onCompanyOpenInExplorerAction(ActionEvent event) { public void onCompanyOpenInExplorerAction(ActionEvent event) {
Company company = getEntity(); CompanyVo company = getEntity();
String path = company.getPath(); String path = company.getPath();
CompletableFuture.runAsync(() -> { CompletableFuture.runAsync(() -> {

View File

@@ -1,20 +1,21 @@
package com.ecep.contract.manager.ds.company.controller.old_name; package com.ecep.contract.controller.company_old_name;
import java.time.format.DateTimeFormatter;
import com.ecep.contract.controller.tab.AbstEntityBasedTabSkin;
import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.service.CompanyOldNameService;
import com.ecep.contract.service.CompanyService;
import com.ecep.contract.vo.CompanyOldNameVo;
import com.ecep.contract.vm.CompanyOldNameViewModel;
import com.ecep.contract.manager.ds.company.model.CompanyOldName;
import com.ecep.contract.manager.ds.company.service.CompanyOldNameService;
import com.ecep.contract.manager.ds.company.service.CompanyService;
import com.ecep.contract.manager.ds.company.vo.CompanyOldNameViewModel;
import com.ecep.contract.manager.ui.tab.AbstEntityBasedTabSkin;
import com.ecep.contract.manager.ui.tab.TabSkin;
import javafx.scene.control.Tab; import javafx.scene.control.Tab;
import javafx.util.converter.LocalDateStringConverter; import javafx.util.converter.LocalDateStringConverter;
import lombok.Setter; import lombok.Setter;
import java.time.format.DateTimeFormatter;
public class CompanyOldNameTabSkinBase public class CompanyOldNameTabSkinBase
extends AbstEntityBasedTabSkin<CompanyOldNameWindowController, CompanyOldName, CompanyOldNameViewModel> extends AbstEntityBasedTabSkin<CompanyOldNameWindowController, CompanyOldNameVo, CompanyOldNameViewModel>
implements TabSkin { implements TabSkin {
@Setter @Setter
private CompanyService companyService; private CompanyService companyService;

View File

@@ -0,0 +1,369 @@
package com.ecep.contract.controller.company_old_name;
import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import org.springframework.util.StringUtils;
import com.ecep.contract.CompanyFileType;
import com.ecep.contract.DesktopUtils;
import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.controller.table.AbstEntityTableTabSkin;
import com.ecep.contract.model.CompanyOldName;
import com.ecep.contract.service.CompanyFileService;
import com.ecep.contract.service.CompanyOldNameService;
import com.ecep.contract.util.ParamUtils;
import com.ecep.contract.util.ParamUtils.Builder;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.CompanyFileViewModel;
import com.ecep.contract.vm.CompanyOldNameViewModel;
import com.ecep.contract.vo.CompanyFileVo;
import com.ecep.contract.vo.CompanyOldNameVo;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.scene.control.Tab;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableView;
import lombok.Setter;
/**
*
*/
public class CompanyOldNameTabSkinFile
extends
AbstEntityTableTabSkin<CompanyOldNameWindowController, CompanyOldNameVo, CompanyOldNameViewModel, CompanyFileVo, CompanyFileViewModel>
implements TabSkin {
@Setter
private CompanyOldNameService companyOldNameService;
@Setter
private CompanyFileService companyFileService;
public CompanyOldNameTabSkinFile(CompanyOldNameWindowController controller) {
super(controller);
setDragAndDrop(true);
setDragAndDropFileHandler(this::moveFileToCompany);
}
@Override
public Tab getTab() {
return controller.fileTab;
}
@Override
public TableView<CompanyFileViewModel> getTableView() {
return controller.fileTable;
}
@Override
protected CompanyFileService getViewModelService() {
return companyFileService;
}
@Override
public Builder getSpecification(CompanyOldNameVo parent) {
return ParamUtils.builder().equals("company", parent.getCompanyId());
}
@Override
public void initializeTab() {
// controller.fileTable_file_move_btn.setOnAction(this::onTableMoveFileAction);
// controller.fileTable_file_retrieve_from_download_dir_btn.setOnAction(this::onTableRetrieveFromDownloadDirAction);
// controller.fileTable_file_reset_btn.setOnAction(this::onTableResetAction);
//
//
// controller.fileTable_idColumn.setCellValueFactory(param ->
// param.getValue().getId());
// ObservableMap<CompanyFileType, CompanyFileTypeLocal> observableMapByLocal =
// getBean(CompanyFileTypeLocalRepository.class).getObservableMapByLocal();
// controller.fileTable_typeColumn.setCellValueFactory(param ->
// Bindings.valueAt(observableMapByLocal,
// param.getValue().getType()).map(CompanyFileTypeLocal::getValue));
// controller.fileTable_filePathColumn.setCellValueFactory(param ->
// param.getValue().getFilePath());
// controller.fileTable_filePathColumn.setCellFactory(param -> new
// FileTableFilePathTableCell());
// controller.fileTable_applyDateColumn.setCellValueFactory(param ->
// param.getValue().getApplyDate());
// controller.fileTable_expiringDateColumn.setCellValueFactory(param ->
// param.getValue().getExpiringDate());
//
//
// controller.fileTable_menu_refresh.setOnAction(this::onTableRefreshAction);
// controller.fileTable_menu_del.setOnAction(this::onTableDeleteAction);
// controller.fileTable_menu_copy_as_matched_by_contract.setOnAction(this::onTableCopyAsMatchedByContractAction);
// controller.fileTable_menu_copy_as_matched_by_contract.setOnMenuValidation(this::onTableCopyAsMatchedMenuValidation);
super.initializeTab();
}
private void onTableResetAction(ActionEvent event) {
CompanyOldNameVo oldName = getParent();
// CompletableFuture.runAsync(() -> {
// if (getCompanyFileService().reBuildingFiles(oldName, this::setStatus)) {
// loadTableDataSet();
// }
// });
}
/**
* 从 下载目录 中查找相关的资质文件
*/
private void onTableRetrieveFromDownloadDirAction(ActionEvent event) {
// CompanyOldName oldName = getParent();
// MyProperties myProperties = getMyProperties();
// File dir = myProperties.getDownloadDirectory();
// if (!dir.exists()) {
// setStatus("下载目录 " + dir.getAbsolutePath() + " 不存在,请检查");
// return;
// }
//
// setStatus("开始检索 下载 文件夹:" + dir.getAbsolutePath() + "...");
// File[] files = dir.listFiles(File::isFile);
// if (files == null) {
// setStatus("检索 下载 文件夹失败");
// return;
// }
// if (files.length == 0) {
// setStatus("下载 文件夹没有文件");
// return;
// }
// setStatus("下载 文件夹中共有文件 " + files.length + " 个文件");
//
// if (getCompanyOldNameService().retrieveFromDownloadFiles(oldName, files,
// this::setStatus)) {
// // fixed if update
// viewModel.update(oldName);
// loadTableDataSet();
// }
}
/**
* 把文件从 老系统中移到 \\10.84.209.8\项目信息\相关方信息 目录中
*/
private void onTableMoveFileAction(ActionEvent event) {
// CompanyFileService companyFileService = getCompanyFileService();
// CompanyOldName oldName = getParent();
// List<CompanyFile> list = companyFileService.findByCompany(oldName);
// if (list.isEmpty()) {
// return;
// }
// if (getCompanyService().makePathAbsent(oldName)) {
// save(oldName);
// }
//
// String path = oldName.getPath();
// if (!StringUtils.hasText(path)) {
// setStatus("异常, 企业目录未设置");
// return;
// }
// File companyPath = new File(path);
// for (CompanyFile companyFile : list) {
// String filePath = companyFile.getFilePath();
// if (StringUtils.hasText(filePath)) {
// File file = new File(filePath);
// if (file.exists()) {
// if (file.getParentFile().equals(companyPath)) {
// continue;
// }
// File dest = new File(companyPath, file.getName());
// if (file.renameTo(dest)) {
// companyFile.setFilePath(dest.getAbsolutePath());
// companyFileService.save(companyFile);
// setStatus(file.getName() + " 移动到 " + companyPath.getName());
// }
// }
// }
// }
}
/**
*
*/
private void onTableCopyAsMatchedByContractAction(ActionEvent event) {
UITools.showDialogAndWait("复制资信评估报告", "按当前评估报告复制一个合同中最匹配的", list -> {
onTableCopyAsMatchedAction_(msg -> {
Platform.runLater(() -> {
list.add(msg);
});
});
});
}
private void onTableCopyAsMatchedAction_(Consumer<String> state) {
// CompanyOldName oldName = getParent();
//
// CompanyFileViewModel selectedItem =
// table.getSelectionModel().getSelectedItem();
// if (selectedItem == null) {
// state.accept("未选择行");
// return;
// }
// if (selectedItem.getApplyDate().get() == null) {
// state.accept("有效日期不能未空");
// return;
// }
//
// LocalDate nextCreditReportDate = null;
// try {
// nextCreditReportDate = companyFileService.getNextCreditReportDate(oldName,
// state);
// if (nextCreditReportDate == null) {
// state.accept("没有找到下一个咨询评估日期");
// return;
// }
// } catch (Exception e) {
// state.accept("获取下一个咨询评估日期失败:" + e.getMessage());
// return;
// }
//
// state.accept("下一个咨询评估日期:" + nextCreditReportDate);
//
// if (!nextCreditReportDate.isBefore(selectedItem.getApplyDate().get())) {
// state.accept("咨询评估日期晚于下一个咨询评估日期");
// return;
// }
//
//
// File src = new File(selectedItem.getFilePath().get());
// if (!src.exists()) {
// state.accept("当前选择行的文件不存在");
// return;
// }
//
// String srcDate = MyDateTimeUtils.format(selectedItem.getApplyDate().get());
// String destDate = MyDateTimeUtils.format(nextCreditReportDate);
// String srcFileName = src.getName();
// String destFileName;
//
// // 天眼查的报告
// if (CloudTycService.isTycReport(srcFileName)) {
// state.accept("天眼查的报告按标准格式命名");
// String name = oldName.getName() + "_" + CloudTycService.NAME;
// if (srcFileName.contains(CloudTycService.TYC_ENTERPRISE_BASIC_REPORT)) {
// name = name + "_" + CloudTycService.TYC_ENTERPRISE_BASIC_REPORT;
// } else if (srcFileName.contains(CloudTycService.TYC_ENTERPRISE_MAJOR_REPORT))
// {
// name = name + "_" + CloudTycService.TYC_ENTERPRISE_MAJOR_REPORT;
// } else if
// (srcFileName.contains(CloudTycService.TYC_ENTERPRISE_ANALYSIS_REPORT)) {
// name = name + "_" + CloudTycService.TYC_ENTERPRISE_ANALYSIS_REPORT;
// }
// destFileName = name + "_" + destDate + "_cp." +
// StringUtils.getFilenameExtension(srcFileName);
// } else {
// if (srcFileName.contains(srcDate)) {
// // 如果文件名中包含日期,则替换为新日期
// destFileName = srcFileName.replace(srcDate, destDate + "_cp");
// } else {
// // 如果文件名中不包含日期,则添加日期
// destFileName = oldName.getName() + "_" + destDate + "_cp." +
// StringUtils.getFilenameExtension(srcFileName);
// }
// }
//
// state.accept("新文件名:" + destFileName);
//
// File dest = new File(src.getParent(), destFileName);
// try {
// FileSystemUtils.copyRecursively(src, dest);
// state.accept("新文件复制成功");
// } catch (IOException e) {
// state.accept("新文件复制失败:" + e.getMessage());
// }
//
// CompanyFile companyFile = new CompanyFile();
// companyFile.setFilePath(dest.getAbsolutePath());
// companyFile.setApplyDate(nextCreditReportDate);
// companyFile.setExpiringDate(nextCreditReportDate.plusYears(1));
// companyFile.setType(CompanyFileType.CreditReport);
// companyFile.setCompany(oldName);
// companyFileService.save(companyFile);
//
// state.accept("新文件已记录");
//
// loadTableDataSet();
// state.accept("文件表已刷新");
}
/**
* 当fileTable选中的行是咨询评估时可用
*
* @param event event
*/
public void onTableCopyAsMatchedMenuValidation(Event event) {
// 当fileTable选中的行是咨询评估时可用
CompanyFileViewModel selectedItem = getSelectedItem();
if (selectedItem == null) {
event.consume();
return;
}
CompanyFileType type = selectedItem.getType().get();
if (type != CompanyFileType.CreditReport) {
event.consume();
return;
}
}
private void moveFileToCompany(List<File> files) {
String path = viewModel.getPath().get();
if (!StringUtils.hasText(path)) {
setStatus("未设置目录");
return;
}
File dir = new File(path);
if (!dir.exists()) {
setStatus("目录错误,不存在");
return;
}
}
@Override
protected void onTableRowDoubleClickedAction(CompanyFileViewModel item) {
String path = item.getFilePath().get();
if (StringUtils.hasText(path)) {
File file = new File(path);
if (!file.exists()) {
setStatus("文件不存在 " + file.getName());
return;
}
DesktopUtils.showInExplorer(file);
}
}
class FileTableFilePathTableCell extends TableCell<CompanyFileViewModel, String> {
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setText("");
return;
}
String path = viewModel.getPath().get();
if (StringUtils.hasText(path)) {
if (item.startsWith(path)) {
item = "~" + item.substring(path.length());
}
}
setText(item);
}
}
private CompanyFileService getCompanyFileService() {
if (companyFileService == null) {
companyFileService = getBean(CompanyFileService.class);
}
return companyFileService;
}
public CompanyOldNameService getCompanyOldNameService() {
if (companyOldNameService == null) {
companyOldNameService = getBean(CompanyOldNameService.class);
}
return companyOldNameService;
}
}

View File

@@ -1,36 +1,44 @@
package com.ecep.contract.manager.ds.company.controller.old_name; package com.ecep.contract.controller.company_old_name;
import java.io.File;
import java.util.concurrent.CompletableFuture;
import com.ecep.contract.manager.ds.company.model.CompanyOldName;
import com.ecep.contract.manager.ds.company.service.CompanyOldNameService;
import com.ecep.contract.manager.ds.company.service.CompanyService;
import com.ecep.contract.manager.ds.company.vo.CompanyFileViewModel;
import com.ecep.contract.manager.ds.company.vo.CompanyOldNameViewModel;
import com.ecep.contract.manager.ui.AbstEntityController;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.ui.ViewModelService;
import com.ecep.contract.manager.util.DesktopUtils;
import com.ecep.contract.manager.util.UITools;
import javafx.event.ActionEvent;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.stage.Window;
import javafx.stage.WindowEvent;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import java.io.File; import com.ecep.contract.DesktopUtils;
import java.util.concurrent.CompletableFuture; import com.ecep.contract.controller.AbstEntityController;
import com.ecep.contract.service.CompanyOldNameService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vo.CompanyOldNameVo;
import com.ecep.contract.vm.CompanyFileViewModel;
import com.ecep.contract.vm.CompanyOldNameViewModel;
import javafx.event.ActionEvent;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.CheckBox;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TableView;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.stage.Window;
import javafx.stage.WindowEvent;
@Lazy @Lazy
@Scope("prototype") @Scope("prototype")
@Component @Component
@FxmlPath("/ui/company/company_old_name.fxml") @FxmlPath("/ui/company/company_old_name.fxml")
public class CompanyOldNameWindowController extends AbstEntityController<CompanyOldName, CompanyOldNameViewModel> { public class CompanyOldNameWindowController extends AbstEntityController<CompanyOldNameVo, CompanyOldNameViewModel> {
private static final Logger logger = LoggerFactory.getLogger(CompanyOldNameWindowController.class); private static final Logger logger = LoggerFactory.getLogger(CompanyOldNameWindowController.class);
/** /**
@@ -45,12 +53,6 @@ public class CompanyOldNameWindowController extends AbstEntityController<Company
public TabPane tabPane; public TabPane tabPane;
public Tab fileTab; public Tab fileTab;
@Autowired
private CompanyOldNameService companyOldNameService;
@Autowired
private CompanyService companyService;
public TextField nameField; public TextField nameField;
public CheckBox ambiguityField; public CheckBox ambiguityField;
public DatePicker startDateField; public DatePicker startDateField;
@@ -62,26 +64,14 @@ public class CompanyOldNameWindowController extends AbstEntityController<Company
public Button saveBtn; public Button saveBtn;
public Button saveBtn2; public Button saveBtn2;
public TableView<CompanyFileViewModel> fileTable; public TableView<CompanyFileViewModel> fileTable;
@Override @Override
public void onShown(WindowEvent windowEvent) { public void onShown(WindowEvent windowEvent) {
super.onShown(windowEvent); super.onShown(windowEvent);
getTitle().set("[" + viewModel.getId().get() + "] " + viewModel.getName().getValue() + " 曾用名详情"); getTitle().set("[" + viewModel.getId().get() + "] " + viewModel.getName().getValue() + " 曾用名详情");
} }
@Override
protected CompanyOldName loadEntity() {
return companyOldNameService.findById(viewModel.getId().get());
}
@Override
protected CompanyOldName saveEntity(CompanyOldName entity) {
return companyOldNameService.save(entity);
}
@Override @Override
protected void registerTabSkins() { protected void registerTabSkins() {
registerTabSkin(baseInfoTab, this::createBaseTabSkin); registerTabSkin(baseInfoTab, this::createBaseTabSkin);
@@ -90,32 +80,31 @@ public class CompanyOldNameWindowController extends AbstEntityController<Company
@Override @Override
public CompanyOldNameService getViewModelService() { public CompanyOldNameService getViewModelService() {
return companyOldNameService; return getCachedBean(CompanyOldNameService.class);
} }
private CompanyOldNameTabSkinBase createBaseTabSkin(Tab tab) { private CompanyOldNameTabSkinBase createBaseTabSkin(Tab tab) {
CompanyOldNameTabSkinBase skin = new CompanyOldNameTabSkinBase(this); CompanyOldNameTabSkinBase skin = new CompanyOldNameTabSkinBase(this);
skin.setCompanyOldNameService(companyOldNameService); skin.setCompanyOldNameService(getViewModelService());
return skin; return skin;
} }
private CompanyOldNameTabSkinFile createFileTabSkin(Tab tab) { private CompanyOldNameTabSkinFile createFileTabSkin(Tab tab) {
CompanyOldNameTabSkinFile skin = new CompanyOldNameTabSkinFile(this); CompanyOldNameTabSkinFile skin = new CompanyOldNameTabSkinFile(this);
skin.setCompanyOldNameService(companyOldNameService); skin.setCompanyOldNameService(getViewModelService());
// skin.setCompanyFileService(companyFileService); // skin.setCompanyFileService(companyFileService);
return skin; return skin;
} }
public void onOldCompanyOpenInExplorerAction(ActionEvent event) { public void onOldCompanyOpenInExplorerAction(ActionEvent event) {
CompanyOldName companyOldName = getEntity(); CompanyOldNameVo companyOldName = getEntity();
String path = companyOldName.getPath(); String path = companyOldName.getPath();
CompletableFuture.runAsync(() -> { CompletableFuture.runAsync(() -> {
if (!StringUtils.hasText(path)) { if (!StringUtils.hasText(path)) {
ButtonType buttonType = UITools.showConfirmation("目录未设置", "是否创建目录").join(); ButtonType buttonType = UITools.showConfirmation("目录未设置", "是否创建目录").join();
if (buttonType == ButtonType.OK) { if (buttonType == ButtonType.OK) {
if (companyOldNameService.makePathAbsent(companyOldName)) { if (getViewModelService().makePathAbsent(companyOldName)) {
save(companyOldName); save(companyOldName);
} }
} else { } else {
@@ -128,4 +117,3 @@ public class CompanyOldNameWindowController extends AbstEntityController<Company
}); });
} }
} }

View File

@@ -0,0 +1,22 @@
package com.ecep.contract.controller.contract;
import com.ecep.contract.controller.tab.AbstEntityBasedTabSkin;
import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.service.ContractService;
import com.ecep.contract.vm.ContractViewModel;
import com.ecep.contract.vo.ContractVo;
public abstract class AbstContractBasedTabSkin
extends AbstEntityBasedTabSkin<ContractWindowController, ContractVo, ContractViewModel>
implements TabSkin {
public AbstContractBasedTabSkin(ContractWindowController controller) {
super(controller);
viewModel = controller.getViewModel();
}
public ContractService getContractService() {
return controller.getViewModelService();
}
}

View File

@@ -0,0 +1,32 @@
package com.ecep.contract.controller.contract;
import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.controller.table.AbstEntityTableTabSkin;
import com.ecep.contract.controller.table.TableOfTabSkin;
import com.ecep.contract.model.IdentityEntity;
import com.ecep.contract.service.ContractService;
import com.ecep.contract.util.ParamUtils;
import com.ecep.contract.vm.ContractViewModel;
import com.ecep.contract.vm.IdentityViewModel;
import com.ecep.contract.vo.ContractVo;
public abstract class AbstContractTableTabSkin<T extends IdentityEntity, TV extends IdentityViewModel<T>>
extends AbstEntityTableTabSkin<ContractWindowController, ContractVo, ContractViewModel, T, TV>
implements TabSkin, TableOfTabSkin<ContractVo, T, TV> {
public AbstContractTableTabSkin(ContractWindowController controller) {
super(controller);
}
public ContractService getContractService() {
return controller.getViewModelService();
}
@Override
public ParamUtils.Builder getSpecification(ContractVo parent) {
ParamUtils.Builder params = getSpecification();
params.equals("contract", parent.getId());
return params;
}
}

View File

@@ -1,4 +1,4 @@
package com.ecep.contract.manager.ds.contract.controller; package com.ecep.contract.controller.contract;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@@ -8,19 +8,16 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.ecep.contract.manager.ds.company.model.Company; import com.ecep.contract.controller.AbstManagerWindowController;
import com.ecep.contract.manager.ds.contract.model.Contract; import com.ecep.contract.controller.tab.ContractManagerSkin;
import com.ecep.contract.manager.ds.contract.model.ContractGroup; import com.ecep.contract.service.ContractService;
import com.ecep.contract.manager.ds.contract.model.ContractKind; import com.ecep.contract.task.ContractFilesRebuildAllTasker;
import com.ecep.contract.manager.ds.contract.model.ContractType; import com.ecep.contract.task.ContractRepairAllTasker;
import com.ecep.contract.manager.ds.contract.service.ContractService; import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.manager.ds.contract.tasker.ContractFilesRebuildAllTasker; import com.ecep.contract.util.UITools;
import com.ecep.contract.manager.ds.contract.tasker.ContractRepairAllTasker; import com.ecep.contract.vm.ContractViewModel;
import com.ecep.contract.manager.ds.contract.vo.ContractViewModel; import com.ecep.contract.vo.ContractGroupVo;
import com.ecep.contract.manager.ds.other.model.Employee; import com.ecep.contract.vo.ContractVo;
import com.ecep.contract.manager.ui.AbstManagerWindowController;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.util.UITools;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.scene.control.CheckBox; import javafx.scene.control.CheckBox;
@@ -33,27 +30,27 @@ import javafx.stage.Stage;
@Component @Component
@FxmlPath("/ui/contract/contract-manager.fxml") @FxmlPath("/ui/contract/contract-manager.fxml")
public class ContractManagerWindowController public class ContractManagerWindowController
extends AbstManagerWindowController<Contract, ContractViewModel, ContractManagerSkin> { extends AbstManagerWindowController<ContractVo, ContractViewModel, ContractManagerSkin> {
public ComboBox<ContractGroup> groupSelector; public ComboBox<ContractGroupVo> groupSelector;
public CheckBox composeViewBtn; public CheckBox composeViewBtn;
// columns // columns
public TableColumn<ContractViewModel, Number> idColumn; public TableColumn<ContractViewModel, Number> idColumn;
public TableColumn<ContractViewModel, String> nameColumn; public TableColumn<ContractViewModel, String> nameColumn;
public TableColumn<ContractViewModel, String> codeColumn; public TableColumn<ContractViewModel, String> codeColumn;
public TableColumn<ContractViewModel, ContractGroup> groupColumn; public TableColumn<ContractViewModel, Integer> groupColumn;
public TableColumn<ContractViewModel, ContractType> typeColumn; public TableColumn<ContractViewModel, Integer> typeColumn;
public TableColumn<ContractViewModel, ContractKind> kindColumn; public TableColumn<ContractViewModel, Integer> kindColumn;
public TableColumn<ContractViewModel, String> parentCodeColumn; public TableColumn<ContractViewModel, String> parentCodeColumn;
public TableColumn<ContractViewModel, LocalDate> setupDateColumn; public TableColumn<ContractViewModel, LocalDate> setupDateColumn;
public TableColumn<ContractViewModel, LocalDate> orderDateColumn; public TableColumn<ContractViewModel, LocalDate> orderDateColumn;
public TableColumn<ContractViewModel, LocalDate> startDateColumn; public TableColumn<ContractViewModel, LocalDate> startDateColumn;
public TableColumn<ContractViewModel, Employee> employeeColumn; public TableColumn<ContractViewModel, Integer> employeeColumn;
public TableColumn<ContractViewModel, LocalDateTime> createdColumn; public TableColumn<ContractViewModel, LocalDateTime> createdColumn;
public TableColumn<ContractViewModel, Number> amountColumn; public TableColumn<ContractViewModel, Number> amountColumn;
public TableColumn<ContractViewModel, Company> companyColumn; public TableColumn<ContractViewModel, Integer> companyColumn;
@Autowired @Autowired
private ContractService contractService; private ContractService contractService;

View File

@@ -1,20 +1,19 @@
package com.ecep.contract.manager.ds.contract.controller; package com.ecep.contract.controller.contract;
import java.util.List; import java.util.List;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import org.hibernate.Hibernate; import com.ecep.contract.SpringApp;
import com.ecep.contract.controller.ComboBoxUtils;
import com.ecep.contract.manager.SpringApp; import com.ecep.contract.model.VendorGroup;
import com.ecep.contract.manager.ds.contract.model.Contract; import com.ecep.contract.service.ExtendVendorInfoService;
import com.ecep.contract.manager.ds.contract.model.ExtendVendorInfo; import com.ecep.contract.service.VendorGroupService;
import com.ecep.contract.manager.ds.contract.service.ExtendVendorInfoService; import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.manager.ds.contract.vo.ExtendVendorInfoViewModel; import com.ecep.contract.util.UITools;
import com.ecep.contract.manager.ds.vendor.model.VendorGroup; import com.ecep.contract.vm.ExtendVendorInfoViewModel;
import com.ecep.contract.manager.ds.vendor.service.VendorGroupService; import com.ecep.contract.vo.ContractVo;
import com.ecep.contract.manager.ui.ComboBoxUtils; import com.ecep.contract.vo.ExtendVendorInfoVo;
import com.ecep.contract.manager.ui.FxmlPath; import com.ecep.contract.vo.VendorGroupVo;
import com.ecep.contract.manager.util.UITools;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.beans.binding.Bindings; import javafx.beans.binding.Bindings;
@@ -29,16 +28,13 @@ import javafx.util.converter.NumberStringConverter;
import lombok.Setter; import lombok.Setter;
@FxmlPath("/ui/contract/contract-tab-ext-vendor-info.fxml") @FxmlPath("/ui/contract/contract-tab-ext-vendor-info.fxml")
public class ContractTabSkinExtendVendorInfo public class ContractTabSkinExtendVendorInfo extends AbstContractBasedTabSkin {
extends AbstContractBasedTabSkin {
@Setter
private ExtendVendorInfoService extendVendorInfoService;
@Setter
private VendorGroupService vendorGroupService;
/**
* VendorGroup
*/
@FXML @FXML
public ComboBox<VendorGroup> vendorGroupField; public ComboBox<VendorGroupVo> vendorGroupField;
@FXML @FXML
public Label vendorGroupLabel; public Label vendorGroupLabel;
@FXML @FXML
@@ -48,7 +44,7 @@ public class ContractTabSkinExtendVendorInfo
@FXML @FXML
public CheckBox prePurchaseField; public CheckBox prePurchaseField;
CompletableFuture<ExtendVendorInfo> loadedFuture; CompletableFuture<ExtendVendorInfoVo> loadedFuture;
private ExtendVendorInfoViewModel viewModel = new ExtendVendorInfoViewModel(); private ExtendVendorInfoViewModel viewModel = new ExtendVendorInfoViewModel();
public ContractTabSkinExtendVendorInfo(ContractWindowController controller) { public ContractTabSkinExtendVendorInfo(ContractWindowController controller) {
@@ -76,13 +72,13 @@ public class ContractTabSkinExtendVendorInfo
if (loadedFuture == null) { if (loadedFuture == null) {
loadedFuture = CompletableFuture.supplyAsync(() -> { loadedFuture = CompletableFuture.supplyAsync(() -> {
initializeTab(); initializeTab();
Contract contract = getEntity(); ContractVo contract = getEntity();
return loadExtendVendorInfo(contract); return loadExtendVendorInfo(contract);
}); });
} }
} }
void updateViewModel(ExtendVendorInfo info) { void updateViewModel(ExtendVendorInfoVo info) {
if (Platform.isFxApplicationThread()) { if (Platform.isFxApplicationThread()) {
viewModel.update(info); viewModel.update(info);
} else { } else {
@@ -90,13 +86,14 @@ public class ContractTabSkinExtendVendorInfo
} }
} }
private ExtendVendorInfo loadExtendVendorInfo(Contract contract) { private ExtendVendorInfoVo loadExtendVendorInfo(ContractVo contract) {
ExtendVendorInfoService service = getExtendVendorInfoService(); ExtendVendorInfoService service = getExtendVendorInfoService();
try { try {
ExtendVendorInfo info = service.findByContract(contract); ExtendVendorInfoVo info = service.findByContract(contract);
if (info == null) { if (info == null) {
info = service.newInstanceByContract(contract); info = new ExtendVendorInfoVo();
info = service.save(info); info.setContractId(contract.getId());
// 注意这里可能需要调整取决于service接口的实现
} }
updateViewModel(info); updateViewModel(info);
viewModel.bindListener(); viewModel.bindListener();
@@ -109,17 +106,11 @@ public class ContractTabSkinExtendVendorInfo
@Override @Override
public void initializeTab() { public void initializeTab() {
List<VendorGroup> groups = getVendorGroupService().findAll(); ComboBoxUtils.initialComboBox(vendorGroupField, viewModel.getGroup(), getVendorGroupService(), true);
ComboBoxUtils.initialComboBox(vendorGroupField, groups, true);
vendorGroupField.valueProperty().bindBidirectional(viewModel.getGroup());
vendorGroupLabel.textProperty().bind(vendorGroupField.valueProperty().map(v -> { vendorGroupLabel.textProperty().bind(vendorGroupField.valueProperty().map(v -> {
if (v == null) { if (v == null) {
return "-"; return "-";
} }
if (!Hibernate.isInitialized(v)) {
v = getVendorGroupService().findById(v.getId());
viewModel.getGroup().set(v);
}
return v.getDescription(); return v.getDescription();
})); }));
@@ -127,7 +118,8 @@ public class ContractTabSkinExtendVendorInfo
new NumberStringConverter()); new NumberStringConverter());
assignedProviderField.selectedProperty().bindBidirectional(viewModel.getAssignedProvider()); assignedProviderField.selectedProperty().bindBidirectional(viewModel.getAssignedProvider());
assignedProviderField.disableProperty().bind(Bindings.createBooleanBinding(() -> { assignedProviderField.disableProperty().bind(Bindings.createBooleanBinding(() -> {
VendorGroup group = viewModel.getGroup().get(); Integer groupId = viewModel.getGroup().get();
VendorGroupVo group = getVendorGroupService().findById(groupId);
if (group == null) { if (group == null) {
return false; return false;
} }
@@ -140,26 +132,21 @@ public class ContractTabSkinExtendVendorInfo
@Override @Override
public void save() { public void save() {
if (loadedFuture != null) { if (loadedFuture != null) {
ExtendVendorInfo vendorInfo = loadedFuture.join(); ExtendVendorInfoVo vendorInfo = loadedFuture.join();
if (viewModel.copyTo(vendorInfo)) { if (viewModel.copyTo(vendorInfo)) {
ExtendVendorInfo saved = getExtendVendorInfoService().save(vendorInfo); // 注意这里需要根据实际service接口实现调整可能需要调用不同的方法
updateViewModel(saved); // ExtendVendorInfoVo saved = getExtendVendorInfoService().saveVo(vendorInfo);
loadedFuture = CompletableFuture.completedFuture(saved); // updateViewModel(saved);
// loadedFuture = CompletableFuture.completedFuture(saved);
} }
} }
} }
public ExtendVendorInfoService getExtendVendorInfoService() { public ExtendVendorInfoService getExtendVendorInfoService() {
if (extendVendorInfoService == null) { return getCachedBean(ExtendVendorInfoService.class);
extendVendorInfoService = SpringApp.getBean(ExtendVendorInfoService.class);
}
return extendVendorInfoService;
} }
public VendorGroupService getVendorGroupService() { public VendorGroupService getVendorGroupService() {
if (vendorGroupService == null) { return getCachedBean(VendorGroupService.class);
vendorGroupService = SpringApp.getBean(VendorGroupService.class);
}
return vendorGroupService;
} }
} }

View File

@@ -1,37 +1,17 @@
package com.ecep.contract.manager.ds.contract.controller; package com.ecep.contract.controller.contract;
import static com.ecep.contract.util.TableViewUtils.bindDoubleClicked;
import static com.ecep.contract.util.TableViewUtils.bindEnterPressed;
import java.io.File;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import com.ecep.contract.manager.ds.contract.ContractPayWay;
import com.ecep.contract.manager.ds.contract.model.Contract;
import com.ecep.contract.manager.ds.contract.service.ContractService;
import com.ecep.contract.manager.ds.contract.tasker.ContractVerifyComm;
import com.ecep.contract.manager.ds.contract.tasker.ContractVerifyResultExportAsExcelFile;
import com.ecep.contract.manager.ui.BaseController;
import com.ecep.contract.manager.ds.other.model.Employee;
import com.ecep.contract.manager.ds.other.service.EmployeeService;
import com.ecep.contract.manager.ds.project.service.SaleTypeService;
import com.ecep.contract.manager.ds.vendor.service.VendorGroupService;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.ui.Message;
import com.ecep.contract.manager.ui.MessageHolder;
import com.ecep.contract.manager.ui.table.cell.EmployeeTableCell;
import com.ecep.contract.manager.util.UITools;
import javafx.application.Platform;
import javafx.beans.property.SimpleListProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXMLLoader;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.layout.HBox;
import javafx.stage.*;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.Hibernate;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -40,21 +20,52 @@ import org.springframework.context.annotation.Scope;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import java.io.File; import com.ecep.contract.Message;
import java.time.LocalDate; import com.ecep.contract.MessageHolder;
import java.util.ArrayList; import com.ecep.contract.controller.BaseController;
import java.util.List; import com.ecep.contract.controller.table.cell.EmployeeTableCell;
import java.util.concurrent.CompletableFuture; import com.ecep.contract.model.Employee;
import java.util.concurrent.atomic.AtomicInteger; import com.ecep.contract.service.ContractService;
import java.util.logging.Level; import com.ecep.contract.service.EmployeeService;
import com.ecep.contract.service.ProjectSaleTypeService;
import com.ecep.contract.service.VendorGroupService;
import com.ecep.contract.task.ContractVerifyComm;
import com.ecep.contract.task.ContractVerifyResultExportAsExcelFileTasker;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.ParamUtils;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vo.ContractVo;
import com.ecep.contract.vo.EmployeeVo;
import static com.ecep.contract.manager.util.TableViewUtils.bindDoubleClicked; import javafx.application.Platform;
import static com.ecep.contract.manager.util.TableViewUtils.bindEnterPressed; import javafx.beans.property.SimpleListProperty;
import static java.util.concurrent.CompletableFuture.runAsync; import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Button;
import javafx.scene.control.CheckMenuItem;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.HBox;
import javafx.stage.FileChooser;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.Window;
import javafx.stage.WindowEvent;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
@Lazy @Lazy
@Scope("prototype") @Scope("prototype")
@@ -78,12 +89,11 @@ public class ContractVerifyWindowController extends BaseController {
} }
} }
@Data @Data
public static class Model implements MessageHolder { public static class Model implements MessageHolder {
private SimpleStringProperty code = new SimpleStringProperty(); private SimpleStringProperty code = new SimpleStringProperty();
private SimpleStringProperty name = new SimpleStringProperty(); private SimpleStringProperty name = new SimpleStringProperty();
private SimpleObjectProperty<Employee> employee = new SimpleObjectProperty<>(); private SimpleObjectProperty<Integer> employee = new SimpleObjectProperty<>();
private SimpleObjectProperty<LocalDate> setupDate = new SimpleObjectProperty<>(); private SimpleObjectProperty<LocalDate> setupDate = new SimpleObjectProperty<>();
private SimpleListProperty<MessageExt> messages = new SimpleListProperty<>(FXCollections.observableArrayList()); private SimpleListProperty<MessageExt> messages = new SimpleListProperty<>(FXCollections.observableArrayList());
@@ -104,9 +114,6 @@ public class ContractVerifyWindowController extends BaseController {
} }
} }
static class StateTableCell extends TableCell<Model, ObservableList<MessageExt>> { static class StateTableCell extends TableCell<Model, ObservableList<MessageExt>> {
Label message2Label(MessageExt message) { Label message2Label(MessageExt message) {
Label label = new Label(message.getMessage()); Label label = new Label(message.getMessage());
@@ -154,7 +161,7 @@ public class ContractVerifyWindowController extends BaseController {
ContractVerifyComm comm = new ContractVerifyComm(); ContractVerifyComm comm = new ContractVerifyComm();
@Autowired @Autowired
private SaleTypeService saleTypeService; private ProjectSaleTypeService saleTypeService;
@Autowired @Autowired
private VendorGroupService vendorGroupService; private VendorGroupService vendorGroupService;
@Autowired @Autowired
@@ -189,7 +196,6 @@ public class ContractVerifyWindowController extends BaseController {
@FXML @FXML
public CheckMenuItem onlyShowVerifiedChecker; public CheckMenuItem onlyShowVerifiedChecker;
@FXML @FXML
public TableView<Model> viewTable; public TableView<Model> viewTable;
private final ObservableList<Model> viewTableDataSet = FXCollections.observableArrayList(); private final ObservableList<Model> viewTableDataSet = FXCollections.observableArrayList();
@@ -198,7 +204,7 @@ public class ContractVerifyWindowController extends BaseController {
@FXML @FXML
public TableColumn<Model, String> viewTable_nameColumn; public TableColumn<Model, String> viewTable_nameColumn;
@FXML @FXML
public TableColumn<Model, Employee> viewTable_employeeColumn; public TableColumn<Model, Integer> viewTable_employeeColumn;
@FXML @FXML
public TableColumn<Model, LocalDate> viewTable_setupDateColumn; public TableColumn<Model, LocalDate> viewTable_setupDateColumn;
@FXML @FXML
@@ -224,8 +230,10 @@ public class ContractVerifyWindowController extends BaseController {
viewTable_employeeColumn.setCellValueFactory(param -> param.getValue().getEmployee()); viewTable_employeeColumn.setCellValueFactory(param -> param.getValue().getEmployee());
viewTable_employeeColumn.setCellFactory(param -> new EmployeeTableCell<>(getEmployeeService())); viewTable_employeeColumn.setCellFactory(param -> new EmployeeTableCell<>(getEmployeeService()));
viewTable_setupDateColumn.setCellValueFactory(param -> param.getValue().getSetupDate()); viewTable_setupDateColumn.setCellValueFactory(param -> param.getValue().getSetupDate());
// viewTable_stateColumn.setCellValueFactory(param -> param.getValue().getMessages().map(messages -> { // viewTable_stateColumn.setCellValueFactory(param ->
// return messages.stream().map(Message::getMessage).collect(Collectors.joining(", ")); // param.getValue().getMessages().map(messages -> {
// return
// messages.stream().map(Message::getMessage).collect(Collectors.joining(", "));
// })); // }));
viewTable_stateColumn.setCellValueFactory(param -> param.getValue().getMessages()); viewTable_stateColumn.setCellValueFactory(param -> param.getValue().getMessages());
viewTable_stateColumn.setCellFactory(param -> new StateTableCell()); viewTable_stateColumn.setCellFactory(param -> new StateTableCell());
@@ -241,11 +249,9 @@ public class ContractVerifyWindowController extends BaseController {
comm.getVerifyCustomerFiles().bind(verifyCustomerFileChecker.selectedProperty()); comm.getVerifyCustomerFiles().bind(verifyCustomerFileChecker.selectedProperty());
comm.getVerifyCustomerSubContractDate().bind(verifyCustomerSubContractDateChecker.selectedProperty()); comm.getVerifyCustomerSubContractDate().bind(verifyCustomerSubContractDateChecker.selectedProperty());
bindDoubleClicked(viewTable, this::showContract); bindDoubleClicked(viewTable, this::showContract);
bindEnterPressed(viewTable, this::reVerifyContract); bindEnterPressed(viewTable, this::reVerifyContract);
} }
/** /**
@@ -257,22 +263,13 @@ public class ContractVerifyWindowController extends BaseController {
viewTableDataSet.clear(); viewTableDataSet.clear();
Pageable pageRequest = PageRequest.ofSize(200); Pageable pageRequest = PageRequest.ofSize(200);
AtomicInteger counter = new AtomicInteger(0); AtomicInteger counter = new AtomicInteger(0);
Specification<Contract> spec = (root, query, builder) -> {
return builder.and( Map<String, Object> params = ParamUtils.builder().
builder.or( between("setupDate", setupDateBeginSelector.getValue(), setupDateEndSelector.getValue())
builder.equal(root.get("payWay"), ContractPayWay.RECEIVE), .build();
builder.and(
builder.equal(root.get("payWay"), ContractPayWay.PAY),
builder.or( long total = contractService.count(params);
builder.isNull(root.get("parentCode")),
builder.equal(root.get("parentCode"), "")
)
)
),
builder.between(root.get("setupDate"), setupDateBeginSelector.getValue(), setupDateEndSelector.getValue())
);
};
long total = contractService.count(spec);
setStatus("合同:" + total + ""); setStatus("合同:" + total + "");
while (true) { while (true) {
@@ -280,17 +277,17 @@ public class ContractVerifyWindowController extends BaseController {
break; break;
} }
Page<Contract> page = contractService.findAll(spec, pageRequest); Page<ContractVo> page = contractService.findAll(params, pageRequest);
for (Contract contract : page) { for (ContractVo contract : page) {
if (isCloseRequested()) { if (isCloseRequested()) {
break; break;
} }
counter.incrementAndGet(); counter.incrementAndGet();
Model model = new Model(); Model model = new Model();
viewTableDataSet.add(model); viewTableDataSet.add(model);
Employee handler = contract.getHandler(); Integer handler = contract.getHandlerId();
if (handler == null) { if (handler == null) {
model.getEmployee().set(contract.getEmployee()); model.getEmployee().set(contract.getEmployeeId());
} else { } else {
model.getEmployee().set(handler); model.getEmployee().set(handler);
} }
@@ -298,6 +295,7 @@ public class ContractVerifyWindowController extends BaseController {
model.getCode().set(contract.getCode()); model.getCode().set(contract.getCode());
model.getName().set(contract.getName()); model.getName().set(contract.getName());
model.getSetupDate().set(contract.getSetupDate()); model.getSetupDate().set(contract.getSetupDate());
comm.verify(contract, model); comm.verify(contract, model);
setStatus("合同验证进度:" + counter.get() + " / " + total); setStatus("合同验证进度:" + counter.get() + " / " + total);
// 移除中间消息 // 移除中间消息
@@ -323,7 +321,6 @@ public class ContractVerifyWindowController extends BaseController {
}); });
} }
public void onContractReVerifyAction(ActionEvent event) { public void onContractReVerifyAction(ActionEvent event) {
Model selectedItem = viewTable.getSelectionModel().getSelectedItem(); Model selectedItem = viewTable.getSelectionModel().getSelectedItem();
if (selectedItem == null) { if (selectedItem == null) {
@@ -338,7 +335,13 @@ public class ContractVerifyWindowController extends BaseController {
return; return;
} }
runAsync(() -> { runAsync(() -> {
Contract contract = contractService.findByCode(contractCode); ContractVo contract = null;
try {
contract = contractService.findByCode(contractCode);
} catch (Exception e) {
handleException("查找合同 " + contractCode + " 时发生错误", e);
return;
}
if (contract == null) { if (contract == null) {
return; return;
} }
@@ -362,7 +365,6 @@ public class ContractVerifyWindowController extends BaseController {
}); });
} }
public void onShowContractDetailAction(ActionEvent event) { public void onShowContractDetailAction(ActionEvent event) {
Model selectedItem = viewTable.getSelectionModel().getSelectedItem(); Model selectedItem = viewTable.getSelectionModel().getSelectedItem();
if (selectedItem == null) { if (selectedItem == null) {
@@ -376,7 +378,13 @@ public class ContractVerifyWindowController extends BaseController {
if (!StringUtils.hasText(contractCode)) { if (!StringUtils.hasText(contractCode)) {
return; return;
} }
Contract contract = contractService.findByCode(contractCode); ContractVo contract = null;
try {
contract = contractService.findByCode(contractCode);
} catch (Exception e) {
handleException("查找合同 " + contractCode + " 时发生错误", e);
return;
}
if (contract == null) { if (contract == null) {
return; return;
} }
@@ -389,7 +397,7 @@ public class ContractVerifyWindowController extends BaseController {
chooser.setInitialFileName("核验结果.xlsx"); chooser.setInitialFileName("核验结果.xlsx");
File selected = chooser.showSaveDialog(viewTable.getScene().getWindow()); File selected = chooser.showSaveDialog(viewTable.getScene().getWindow());
if (selected != null) { if (selected != null) {
ContractVerifyResultExportAsExcelFile task = new ContractVerifyResultExportAsExcelFile(); ContractVerifyResultExportAsExcelFileTasker task = new ContractVerifyResultExportAsExcelFileTasker();
task.setDestFile(selected); task.setDestFile(selected);
task.setModels(new ArrayList<>(viewTableDataSet)); task.setModels(new ArrayList<>(viewTableDataSet));
UITools.showTaskDialogAndWait("导出中...", task, null); UITools.showTaskDialogAndWait("导出中...", task, null);

View File

@@ -1,46 +1,57 @@
package com.ecep.contract.manager.ds.contract.controller; package com.ecep.contract.controller.contract;
import java.io.File;
import com.ecep.contract.manager.ds.company.controller.CompanyWindowController;
import com.ecep.contract.manager.ds.company.model.Company;
import com.ecep.contract.manager.ds.company.service.CompanyService;
import com.ecep.contract.manager.ds.contract.model.Contract;
import com.ecep.contract.manager.ds.contract.service.ContractService;
import com.ecep.contract.manager.ds.contract.tasker.ContractRepairTask;
import com.ecep.contract.manager.ds.contract.tasker.ContractVerifyTasker;
import com.ecep.contract.manager.ds.contract.vo.ContractViewModel;
import com.ecep.contract.manager.ds.project.service.ProjectService;
import com.ecep.contract.manager.ui.AbstEntityController;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.util.DesktopUtils;
import com.ecep.contract.manager.util.UITools;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.stage.Window;
import javafx.stage.WindowEvent;
import javafx.util.converter.LocalDateStringConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import java.io.File; import com.ecep.contract.ContractPayWay;
import java.time.format.DateTimeFormatter; import com.ecep.contract.DesktopUtils;
import com.ecep.contract.controller.AbstEntityController;
import com.ecep.contract.controller.company.CompanyWindowController;
import com.ecep.contract.controller.tab.ContractTabSkinBase;
import com.ecep.contract.controller.tab.ContractTabSkinFiles;
import com.ecep.contract.controller.tab.ContractTabSkinItemsV2;
import com.ecep.contract.controller.tab.ContractTabSkinPayPlan;
import com.ecep.contract.controller.tab.ContractTabSkinPurchaseOrders;
import com.ecep.contract.controller.tab.ContractTabSkinSaleOrders;
import com.ecep.contract.controller.tab.ContractTabSkinSubContract;
import com.ecep.contract.controller.tab.ContractTabSkinVendorBid;
import com.ecep.contract.service.CompanyService;
import com.ecep.contract.service.ContractService;
import com.ecep.contract.task.ContractRepairTask;
import com.ecep.contract.task.ContractVerifyTasker;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.ContractViewModel;
import com.ecep.contract.vo.CompanyVo;
import com.ecep.contract.vo.ContractVo;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.scene.control.Button;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.stage.Window;
import javafx.stage.WindowEvent;
@Lazy @Lazy
@Scope("prototype") @Scope("prototype")
@Component @Component
@FxmlPath("/ui/contract/contract.fxml") @FxmlPath("/ui/contract/contract.fxml")
public class ContractWindowController public class ContractWindowController
extends AbstEntityController<Contract, ContractViewModel> { extends AbstEntityController<ContractVo, ContractViewModel> {
public static void show(ContractVo contract, Window owner) {
public static void show(Contract contract, Window owner) { show(ContractViewModel.from(contract), owner);
ContractViewModel model = new ContractViewModel();
model.update(contract);
show(model, owner);
} }
/** /**
@@ -63,16 +74,6 @@ public class ContractWindowController
public Button openRelativeCompanyCustomerBtn; public Button openRelativeCompanyCustomerBtn;
public Button openRelativeCompanyVendorBtn; public Button openRelativeCompanyVendorBtn;
@Autowired
CompanyService companyService;
@Autowired
ContractService contractService;
@Autowired
ProjectService projectService;
LocalDateStringConverter localDateStringConverter = new LocalDateStringConverter(DateTimeFormatter.ISO_LOCAL_DATE, null);
public TextField nameField; public TextField nameField;
public TextField guidField; public TextField guidField;
public TextField codeField; public TextField codeField;
@@ -124,12 +125,17 @@ public class ContractWindowController
@Override @Override
public ContractService getViewModelService() { public ContractService getViewModelService() {
return contractService; return getCachedBean(ContractService.class);
}
public CompanyService getCompanyService() {
return getCachedBean(CompanyService.class);
} }
public void onShown(WindowEvent windowEvent) { public void onShown(WindowEvent windowEvent) {
super.onShown(windowEvent); super.onShown(windowEvent);
getTitle().bind(viewModel.getName().map(name -> "[" + viewModel.getId().get() + "] " + viewModel.getCode().get() + " " + name + " 合同详情")); getTitle().bind(viewModel.getName()
.map(name -> "[" + viewModel.getId().get() + "] " + viewModel.getCode().get() + " " + name + " 合同详情"));
root.getScene().getStylesheets().add("/ui/contract/contract.css"); root.getScene().getStylesheets().add("/ui/contract/contract.css");
} }
@@ -139,8 +145,8 @@ public class ContractWindowController
ObservableList<Tab> tabs = tabPane.getTabs(); ObservableList<Tab> tabs = tabPane.getTabs();
registerTabSkin(baseInfoTab, tab -> new ContractTabSkinBase(this)); registerTabSkin(baseInfoTab, tab -> new ContractTabSkinBase(this));
switch (viewModel.getPayWay().get()) { ContractPayWay payWay = viewModel.getPayWay().get();
case RECEIVE -> { if (payWay == ContractPayWay.RECEIVE) {
tabs.remove(extendVendorInfo); tabs.remove(extendVendorInfo);
registerTabSkin(contractTab, t -> new ContractTabSkinSubContract(this)); registerTabSkin(contractTab, t -> new ContractTabSkinSubContract(this));
tabs.remove(bidVendorTab); tabs.remove(bidVendorTab);
@@ -148,9 +154,7 @@ public class ContractWindowController
tabs.add(saleOrderTab); tabs.add(saleOrderTab);
registerTabSkin(saleOrderTab, tab -> new ContractTabSkinSaleOrders(this, tab)); registerTabSkin(saleOrderTab, tab -> new ContractTabSkinSaleOrders(this, tab));
tabs.add(new Tab("票据")); tabs.add(new Tab("票据"));
break; } else if (payWay == ContractPayWay.PAY) {
}
case PAY -> {
registerTabSkin(extendVendorInfo, t -> new ContractTabSkinExtendVendorInfo(this)); registerTabSkin(extendVendorInfo, t -> new ContractTabSkinExtendVendorInfo(this));
tabs.remove(contractTab); tabs.remove(contractTab);
registerTabSkin(bidVendorTab, t -> new ContractTabSkinVendorBid(this)); registerTabSkin(bidVendorTab, t -> new ContractTabSkinVendorBid(this));
@@ -162,8 +166,6 @@ public class ContractWindowController
tabs.add(new Tab("发货单")); tabs.add(new Tab("发货单"));
tabs.add(new Tab("签收单")); tabs.add(new Tab("签收单"));
tabs.add(new Tab("付款单")); tabs.add(new Tab("付款单"));
break;
}
} }
registerTabSkin(itemTab, tab -> new ContractTabSkinItemsV2(this)); registerTabSkin(itemTab, tab -> new ContractTabSkinItemsV2(this));
@@ -171,9 +173,8 @@ public class ContractWindowController
registerTabSkin(fileTab, tab -> new ContractTabSkinFiles(this)); registerTabSkin(fileTab, tab -> new ContractTabSkinFiles(this));
} }
public void onContractOpenInExplorerAction(ActionEvent event) { public void onContractOpenInExplorerAction(ActionEvent event) {
Contract contract = getEntity(); ContractVo contract = getEntity();
String path = contract.getPath(); String path = contract.getPath();
if (!StringUtils.hasText(path)) { if (!StringUtils.hasText(path)) {
setStatus("未设置目录"); setStatus("未设置目录");
@@ -188,13 +189,13 @@ public class ContractWindowController
} }
public void onContractOpenRelativeCompanyAction(ActionEvent event) { public void onContractOpenRelativeCompanyAction(ActionEvent event) {
Contract contract = getEntity(); ContractVo contract = getEntity();
if (contract.getCompany() == null) { if (contract.getCompanyId() == null) {
UITools.showAlertAndWait("没有关联的公司,你可以尝试同步修复异常。"); UITools.showAlertAndWait("没有关联的公司,你可以尝试同步修复异常。");
return; return;
} }
Integer companyId = contract.getCompany().getId(); Integer companyId = contract.getCompanyId();
Company company = companyService.findById(companyId); CompanyVo company = getCompanyService().findById(companyId);
if (company != null) { if (company != null) {
CompanyWindowController.show(company, root.getScene().getWindow()); CompanyWindowController.show(company, root.getScene().getWindow());
} }
@@ -202,7 +203,6 @@ public class ContractWindowController
public void onSyncContractAction(ActionEvent event) { public void onSyncContractAction(ActionEvent event) {
ContractRepairTask task = new ContractRepairTask(); ContractRepairTask task = new ContractRepairTask();
task.setContractService(contractService);
task.setContract(getEntity()); task.setContract(getEntity());
UITools.showTaskDialogAndWait("同步合同", task, null); UITools.showTaskDialogAndWait("同步合同", task, null);
if (task.isRepaired()) { if (task.isRepaired()) {
@@ -221,7 +221,7 @@ public class ContractWindowController
} }
} }
if (task.isItemsUpdated()) { if (task.isItemsUpdated()) {
ContractTabSkinItems tabSkin = getTabSkin(ContractTabSkinItems.class); ContractTabSkinItemsV2 tabSkin = getTabSkin(ContractTabSkinItemsV2.class);
if (tabSkin != null) { if (tabSkin != null) {
tabSkin.loadTableDataSet(); tabSkin.loadTableDataSet();
} }
@@ -234,14 +234,12 @@ public class ContractWindowController
} }
} }
/** /**
* 验证合同合规性 * 验证合同合规性
*/ */
public void onContractVerifyAction(ActionEvent event) { public void onContractVerifyAction(ActionEvent event) {
Contract contract = getEntity(); ContractVo contract = getEntity();
ContractVerifyTasker task = new ContractVerifyTasker(); ContractVerifyTasker task = new ContractVerifyTasker();
task.setContractService(contractService);
task.setContract(contract); task.setContract(contract);
UITools.showTaskDialogAndWait("同步合规性验证", task, null); UITools.showTaskDialogAndWait("同步合规性验证", task, null);
} }

View File

@@ -0,0 +1,29 @@
package com.ecep.contract.controller.customer;
import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.controller.table.AbstEntityTableTabSkin;
import com.ecep.contract.model.IdentityEntity;
import com.ecep.contract.service.CompanyCustomerService;
import com.ecep.contract.service.CompanyService;
import com.ecep.contract.vm.CompanyCustomerViewModel;
import com.ecep.contract.vm.IdentityViewModel;
import com.ecep.contract.vo.CompanyCustomerVo;
public abstract class AbstCompanyCustomerTableTabSkin<T extends IdentityEntity, TV extends IdentityViewModel<T>>
extends
AbstEntityTableTabSkin<CompanyCustomerWindowController, CompanyCustomerVo, CompanyCustomerViewModel, T, TV>
implements TabSkin {
public AbstCompanyCustomerTableTabSkin(CompanyCustomerWindowController controller) {
super(controller);
}
public CompanyService getCompanyService() {
return controller.getCompanyService();
}
protected CompanyCustomerService getCompanyCustomerService() {
return getCachedBean(CompanyCustomerService.class);
}
}

View File

@@ -1,27 +1,11 @@
package com.ecep.contract.manager.ds.customer.controller; package com.ecep.contract.controller.customer;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiConsumer;
import com.ecep.contract.manager.ds.customer.model.CompanyCustomerEvaluationFormFile;
import com.ecep.contract.manager.ds.customer.model.CompanyCustomerFile;
import com.ecep.contract.manager.ds.customer.repository.CompanyCustomerEvaluationFormFileRepository;
import com.ecep.contract.manager.ds.customer.repository.CompanyCustomerFileRepository;
import com.ecep.contract.manager.ui.BaseController;
import com.ecep.contract.manager.ds.customer.vo.CompanyCustomerFileViewModel;
import com.ecep.contract.manager.ds.customer.service.CompanyCustomerFileService;
import com.ecep.contract.manager.ds.company.CompanyFileUtils;
import com.ecep.contract.manager.util.FxmlUtils;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.event.ActionEvent;
import javafx.geometry.Bounds;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.PixelWriter;
import javafx.scene.image.WritableImage;
import javafx.stage.*;
import org.apache.pdfbox.Loader; import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer; import org.apache.pdfbox.rendering.PDFRenderer;
@@ -33,24 +17,50 @@ import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import java.awt.image.BufferedImage; import com.ecep.contract.controller.BaseController;
import java.io.File; import com.ecep.contract.vo.CompanyCustomerEvaluationFormFileVo;
import java.util.Objects; import com.ecep.contract.vo.CompanyCustomerFileVo;
import java.util.concurrent.CompletableFuture; import com.ecep.contract.service.CompanyCustomerFileService;
import java.util.function.BiConsumer; import com.ecep.contract.service.CompanyCustomerEvaluationFormFileService;
import com.ecep.contract.util.FileUtils;
import com.ecep.contract.util.FxmlUtils;
import com.ecep.contract.vm.CompanyCustomerEvaluationFormFileViewModel;
import com.ecep.contract.vm.CompanyCustomerFileViewModel;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.event.ActionEvent;
import javafx.geometry.Bounds;
import javafx.scene.control.CheckBox;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.SplitPane;
import javafx.scene.control.TextField;
import javafx.scene.control.Toggle;
import javafx.scene.control.ToggleGroup;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.PixelWriter;
import javafx.scene.image.WritableImage;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.Window;
import javafx.stage.WindowEvent;
@Lazy @Lazy
@Scope("prototype") @Scope("prototype")
@Component @Component
public class CompanyCustomerEvaluationFormFileWindowController extends BaseController { public class CompanyCustomerEvaluationFormFileWindowController extends BaseController {
private static final Logger logger = LoggerFactory.getLogger(CompanyCustomerEvaluationFormFileWindowController.class); private static final Logger logger = LoggerFactory.getLogger(CompanyCustomerEvaluationFormFileWindowController.class);
public static void show(CompanyCustomerFile saved, Window window) { public static void show(CompanyCustomerEvaluationFormFileVo saved, Window window) {
CompanyCustomerFileViewModel model = new CompanyCustomerFileViewModel(); show(CompanyCustomerEvaluationFormFileViewModel.from(saved), window);
model.update(saved);
show(model, window);
} }
public static void show(CompanyCustomerFileViewModel viewModel, Window window) { public static void show(CompanyCustomerEvaluationFormFileViewModel viewModel, Window window) {
String key = viewModel.getClass().getName() + "-" + viewModel.getId().get(); String key = viewModel.getClass().getName() + "-" + viewModel.getId().get();
if (toFront(key)) { if (toFront(key)) {
return; return;
@@ -81,7 +91,7 @@ public class CompanyCustomerEvaluationFormFileWindowController extends BaseContr
public ScrollPane leftPane; public ScrollPane leftPane;
public Label totalCreditScoreLabel; public Label totalCreditScoreLabel;
private CompanyCustomerFileViewModel viewModel; private CompanyCustomerEvaluationFormFileViewModel viewModel;
private final SimpleStringProperty catalogProperty = new SimpleStringProperty(""); private final SimpleStringProperty catalogProperty = new SimpleStringProperty("");
private final SimpleStringProperty levelProperty = new SimpleStringProperty(""); private final SimpleStringProperty levelProperty = new SimpleStringProperty("");
@@ -95,15 +105,15 @@ public class CompanyCustomerEvaluationFormFileWindowController extends BaseContr
private SimpleObjectProperty<Image> imageProperty = new SimpleObjectProperty<>(); private SimpleObjectProperty<Image> imageProperty = new SimpleObjectProperty<>();
private CompletableFuture<CompanyCustomerEvaluationFormFile> loadedFuture; private CompletableFuture<CompanyCustomerEvaluationFormFileVo> loadedFuture;
@Autowired
private CompanyCustomerFileRepository companyCustomerFileRepository;
@Autowired
private CompanyCustomerEvaluationFormFileRepository companyCustomerEvaluationFormFileRepository;
@Lazy @Lazy
@Autowired @Autowired
private CompanyCustomerFileService companyCustomerFileService; private CompanyCustomerFileService companyCustomerFileService;
@Lazy
@Autowired
private CompanyCustomerEvaluationFormFileService evaluationFormFileService;
@Override @Override
public void show(Stage stage) { public void show(Stage stage) {
@@ -132,8 +142,8 @@ public class CompanyCustomerEvaluationFormFileWindowController extends BaseContr
loadedFuture = CompletableFuture.supplyAsync(() -> { loadedFuture = CompletableFuture.supplyAsync(() -> {
int id = viewModel.getId().get(); int id = viewModel.getId().get();
CompanyCustomerFile customerFile = companyCustomerFileService.findById(id); CompanyCustomerFileVo customerFile = companyCustomerFileService.findById(id);
CompanyCustomerEvaluationFormFile formFile = companyCustomerFileService.findCustomerEvaluationFormFileByCustomerFile(customerFile); CompanyCustomerEvaluationFormFileVo formFile = evaluationFormFileService.findByCustomerFile(customerFile);
Platform.runLater(() -> update(formFile)); Platform.runLater(() -> update(formFile));
return formFile; return formFile;
}); });
@@ -249,10 +259,10 @@ public class CompanyCustomerEvaluationFormFileWindowController extends BaseContr
private void initializePane() { private void initializePane() {
idField.textProperty().bind(viewModel.getId().asString()); idField.textProperty().bind(viewModel.getId().asString());
filePathField.textProperty().bind(viewModel.getFilePath()); // filePathField.textProperty().bind(viewModel.getFilePath());
editFilePathField.textProperty().bind(viewModel.getEditFilePath()); // editFilePathField.textProperty().bind(viewModel.getEditFilePath());
signDateField.valueProperty().bindBidirectional(viewModel.getSignDate()); // signDateField.valueProperty().bindBidirectional(viewModel.getSignDate());
validField.selectedProperty().bindBidirectional(viewModel.getValid()); // validField.selectedProperty().bindBidirectional(viewModel.getValid());
initializeRadioGroup(catalog, catalogProperty); initializeRadioGroup(catalog, catalogProperty);
initializeRadioGroup(level, levelProperty); initializeRadioGroup(level, levelProperty);
@@ -283,7 +293,7 @@ public class CompanyCustomerEvaluationFormFileWindowController extends BaseContr
Bindings.createBooleanBinding(() -> { Bindings.createBooleanBinding(() -> {
boolean valid = calcValid(); boolean valid = calcValid();
viewModel.getValid().set(valid); // viewModel.getValid().set(valid);
return valid; return valid;
}, catalogProperty, levelProperty, score1Property, score2Property, score3Property, score4Property, score5Property, creditLevelProperty).addListener(((observable, oldValue, newValue) -> { }, catalogProperty, levelProperty, score1Property, score2Property, score3Property, score4Property, score5Property, creditLevelProperty).addListener(((observable, oldValue, newValue) -> {
logger.info("valid:{}", newValue); logger.info("valid:{}", newValue);
@@ -291,7 +301,7 @@ public class CompanyCustomerEvaluationFormFileWindowController extends BaseContr
imageView.imageProperty().bind(viewModel.getFilePath().map(path -> { imageView.imageProperty().bind(viewModel.getFilePath().map(path -> {
if (CompanyFileUtils.withExtensions(path, CompanyFileUtils.PDF)) { if (FileUtils.withExtensions(path, FileUtils.PDF)) {
File pdfFile = new File(path); File pdfFile = new File(path);
try (PDDocument pdDocument = Loader.loadPDF(pdfFile)) { try (PDDocument pdDocument = Loader.loadPDF(pdfFile)) {
PDFRenderer pdfRenderer = new PDFRenderer(pdDocument); PDFRenderer pdfRenderer = new PDFRenderer(pdDocument);
@@ -367,10 +377,9 @@ public class CompanyCustomerEvaluationFormFileWindowController extends BaseContr
}); });
} }
private void update(CompanyCustomerEvaluationFormFile formFile) { private void update(CompanyCustomerEvaluationFormFileVo formFile) {
viewModel.update(formFile);
viewModel.update(formFile.getCustomerFile());
// formFile.getScoreTemplateVersion(); // formFile.getScoreTemplateVersion();
@@ -383,55 +392,4 @@ public class CompanyCustomerEvaluationFormFileWindowController extends BaseContr
score5Property.set(formFile.getScore5()); score5Property.set(formFile.getScore5());
creditLevelProperty.set(formFile.getCreditLevel()); creditLevelProperty.set(formFile.getCreditLevel());
} }
public void onSaveAction(ActionEvent event) {
boolean modified = false;
int id = viewModel.getId().get();
CompanyCustomerEvaluationFormFile formFile = companyCustomerFileService.findCustomerEvaluationFormFileById(id);
CompanyCustomerFile customerFile = formFile.getCustomerFile();
if (!Objects.equals(catalogProperty.get(), formFile.getCatalog())) {
formFile.setCatalog(catalogProperty.get());
modified = true;
}
if (!Objects.equals(levelProperty.get(), formFile.getLevel())) {
formFile.setLevel(levelProperty.get());
modified = true;
}
if (!Objects.equals(score1Property.get(), formFile.getScore1())) {
formFile.setScore1(score1Property.get());
modified = true;
}
if (!Objects.equals(score2Property.get(), formFile.getScore2())) {
formFile.setScore2(score2Property.get());
modified = true;
}
if (!Objects.equals(score3Property.get(), formFile.getScore3())) {
formFile.setScore3(score3Property.get());
modified = true;
}
if (!Objects.equals(score4Property.get(), formFile.getScore4())) {
formFile.setScore4(score4Property.get());
modified = true;
}
if (!Objects.equals(score5Property.get(), formFile.getScore5())) {
formFile.setScore5(score5Property.get());
modified = true;
}
if (!Objects.equals(creditLevelProperty.get(), formFile.getCreditLevel())) {
formFile.setCreditLevel(creditLevelProperty.get());
modified = true;
}
if (viewModel.copyTo(customerFile)) {
modified = true;
}
if (modified) {
companyCustomerFileService.save(formFile);
}
}
} }

View File

@@ -1,41 +1,45 @@
package com.ecep.contract.manager.ds.customer.controller; package com.ecep.contract.controller.customer;
import com.ecep.contract.manager.SpringApp; import static com.ecep.contract.util.ExcelUtils.setCellValue;
import com.ecep.contract.manager.cloud.tyc.CloudTyc;
import com.ecep.contract.manager.cloud.tyc.CloudTycService;
import com.ecep.contract.manager.ds.company.model.Company;
import com.ecep.contract.manager.ds.company.service.CompanyBasicService;
import com.ecep.contract.manager.ds.company.service.CompanyContactService;
import com.ecep.contract.manager.ds.company.service.CompanyService;
import com.ecep.contract.manager.ds.customer.CompanyCustomerFileType;
import com.ecep.contract.manager.ds.customer.model.CompanyCustomer;
import com.ecep.contract.manager.ds.customer.model.CompanyCustomerEvaluationFormFile;
import com.ecep.contract.manager.ds.customer.model.CompanyCustomerFile;
import com.ecep.contract.manager.ds.customer.service.CompanyCustomerFileService;
import com.ecep.contract.manager.ds.customer.service.CompanyCustomerService;
import javafx.concurrent.Task;
import lombok.Setter;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.ss.util.CellRangeAddress;
import org.hibernate.Hibernate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import java.io.*; import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
import static com.ecep.contract.manager.util.ExcelUtils.setCellValue; import com.ecep.contract.service.*;
import com.ecep.contract.task.Tasker;
import com.ecep.contract.util.CompanyUtils;
import com.ecep.contract.vo.CompanyCustomerFileVo;
import com.ecep.contract.vo.CompanyCustomerVo;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.ss.util.CellRangeAddress;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
public class CompanyCustomerEvaluationFormUpdateTask extends Task<Object> { import com.ecep.contract.CustomerFileType;
import com.ecep.contract.MessageHolder;
import com.ecep.contract.SpringApp;
import com.ecep.contract.vo.CloudTycVo;
import com.ecep.contract.vo.CompanyVo;
import com.ecep.contract.vo.CompanyCustomerEvaluationFormFileVo;
import lombok.Setter;
public class CompanyCustomerEvaluationFormUpdateTask extends Tasker<Object> {
private static final Logger logger = LoggerFactory.getLogger(CompanyCustomerEvaluationFormUpdateTask.class); private static final Logger logger = LoggerFactory.getLogger(CompanyCustomerEvaluationFormUpdateTask.class);
@Setter @Setter
private CompanyCustomer customer; private CompanyCustomerVo customer;
@Setter @Setter
private CompanyService companyService; private CompanyService companyService;
private CompanyContactService companyContactService; private CompanyContactService companyContactService;
@@ -44,13 +48,6 @@ public class CompanyCustomerEvaluationFormUpdateTask extends Task<Object> {
@Setter @Setter
private CompanyCustomerFileService companyCustomerFileService; private CompanyCustomerFileService companyCustomerFileService;
private CompanyService getCompanyService() {
if (companyService == null) {
companyService = SpringApp.getBean(CompanyService.class);
}
return companyService;
}
private CompanyCustomerService getCompanyCustomerService() { private CompanyCustomerService getCompanyCustomerService() {
if (companyCustomerService == null) { if (companyCustomerService == null) {
companyCustomerService = SpringApp.getBean(CompanyCustomerService.class); companyCustomerService = SpringApp.getBean(CompanyCustomerService.class);
@@ -72,32 +69,36 @@ public class CompanyCustomerEvaluationFormUpdateTask extends Task<Object> {
return companyCustomerFileService; return companyCustomerFileService;
} }
@Override private CompanyCustomerEvaluationFormFileService getCompanyCustomerEvaluationFormFileService() {
protected Object call() throws Exception { return getBean(CompanyCustomerEvaluationFormFileService.class);
try {
updateEvaluationForm();
} catch (Exception ex) {
updateMessage(ex.getMessage());
}
return null;
} }
private File getEvaluationFormTemplate() { private File getEvaluationFormTemplate() {
return getCompanyCustomerFileService().getEvaluationFormTemplate(); return getCompanyCustomerFileService().getEvaluationFormTemplate();
} }
public void updateEvaluationForm() { @Override
protected Object execute(MessageHolder holder) throws Exception {
try {
updateEvaluationForm(holder);
} catch (Exception ex) {
updateMessage(ex.getMessage());
}
return null;
}
public void updateEvaluationForm(MessageHolder holder) {
if (!StringUtils.hasText(customer.getPath())) { if (!StringUtils.hasText(customer.getPath())) {
updateMessage("供应商目录未设置,请先设置供应商目录"); holder.error("供应商目录未设置,请先设置供应商目录");
return; return;
} }
File template = getEvaluationFormTemplate(); File template = getEvaluationFormTemplate();
if (template == null) { if (template == null) {
updateMessage("评价表模板文件未设置,请先设置评价表模板文件"); holder.error("评价表模板文件未设置,请先设置评价表模板文件");
return; return;
} }
if (!template.exists()) { if (!template.exists()) {
updateMessage("评价表模板文件 " + template.getAbsolutePath() + " 不存在,请检查"); holder.error("评价表模板文件 " + template.getAbsolutePath() + " 不存在,请检查");
return; return;
} }
@@ -106,78 +107,66 @@ public class CompanyCustomerEvaluationFormUpdateTask extends Task<Object> {
File destFile = new File(dir, template_file_name); File destFile = new File(dir, template_file_name);
if (destFile.exists()) { if (destFile.exists()) {
updateMessage("表单文件已经存在," + destFile.getName()); holder.info("表单文件已经存在," + destFile.getName());
try ( try (
InputStream inp = new FileInputStream(destFile); InputStream inp = new FileInputStream(destFile);
Workbook wb = WorkbookFactory.create(inp) Workbook wb = WorkbookFactory.create(inp)) {
) { updateEvaluationForm(wb, destFile, holder);
updateEvaluationForm(wb, destFile); holder.info("评价表已更新");
updateMessage("评价表已更新");
} catch (Exception e) { } catch (Exception e) {
updateMessage(e.getMessage()); holder.error(e.getMessage());
logger.error(e.getMessage(), e); logger.error(e.getMessage(), e);
} }
} else { } else {
updateMessage("根据模板 " + template_file_name + " 创建表单 " + destFile.getName()); holder.info("根据模板 " + template_file_name + " 创建表单 " + destFile.getName());
try ( try (
InputStream inp = new FileInputStream(template); InputStream inp = new FileInputStream(template);
Workbook wb = WorkbookFactory.create(inp) Workbook wb = WorkbookFactory.create(inp)) {
) { updateEvaluationForm(wb, destFile, holder);
updateEvaluationForm(wb, destFile); holder.info("评价表已创建");
updateMessage("评价表已创建"); CompanyCustomerFileVo customerFile = new CompanyCustomerFileVo();
CompanyCustomerFile customerFile = new CompanyCustomerFile(); customerFile.setCustomer(customer.getId());
customerFile.setCustomer(customer);
customerFile.setFilePath(destFile.getAbsolutePath()); customerFile.setFilePath(destFile.getAbsolutePath());
customerFile.setType(CompanyCustomerFileType.General); customerFile.setType(CustomerFileType.General);
save(customerFile); save(customerFile);
} catch (Exception e) { } catch (Exception e) {
updateMessage(e.getMessage()); holder.error(e.getMessage());
logger.error(e.getMessage(), e); logger.error(e.getMessage(), e);
} }
} }
updateProgress(1, 1); updateProgress(1, 1);
} }
private void save(CompanyCustomerFile customerFile) { private void save(CompanyCustomerFileVo customerFile) {
getCompanyCustomerFileService().save(customerFile); getCompanyCustomerFileService().save(customerFile);
} }
/** /**
* 更新客户评估表依据模板创建如果已经存在生成的文件则更新评估表 * 更新客户评估表依据模板创建如果已经存在生成的文件则更新评估表
* *
* @param wb work book * @param wb work book
* @param destFile 目标文件 * @param destFile 目标文件
*/ */
public void updateEvaluationForm( public void updateEvaluationForm(Workbook wb, File destFile, MessageHolder holder) throws IOException {
Workbook wb, File destFile Integer companyId = customer.getCompanyId();
) throws IOException { CompanyVo company = getCompanyService().findById(companyId);
Company company = customer.getCompany();
if (!Hibernate.isInitialized(company)) {
company = getCompanyService().findById(company.getId());
customer.setCompany(company);
}
Sheet sheet = wb.getSheetAt(0); Sheet sheet = wb.getSheetAt(0);
updateSheet(company, sheet); updateSheet(company, sheet, holder.sub(" - "));
updateProgress(900, 1000);
// 输出到文件 // 输出到文件
try (OutputStream fileOut = new FileOutputStream(destFile)) { try (OutputStream fileOut = new FileOutputStream(destFile)) {
wb.write(fileOut); wb.write(fileOut);
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
updateMessage("写评估表时发生文件错误,请检查评估表是否被打开中"); holder.error("写评估表时发生文件错误,请检查评估表是否被打开中:" + e.getMessage());
updateMessage(e.getMessage());
logger.error(e.getMessage(), e); logger.error(e.getMessage(), e);
} }
} }
private void updateSheet(Company company, Sheet sheet) { private void updateSheet(CompanyVo company, Sheet sheet, MessageHolder holder) {
setCellValue(sheet, "B3", "客户编号:" + CompanyBasicService.formatCompanyVendorId(customer.getId())); setCellValue(sheet, "B3", "客户编号:" + CompanyUtils.formatCompanyVendorId(customer.getId()));
setCellValue(sheet, "B4", "客户名称:" + company.getName()); setCellValue(sheet, "B4", "客户名称:" + company.getName());
LocalDate suggestDate = getCompanyCustomerFileService().getNextSignDate(customer, msg -> { LocalDate suggestDate = getCompanyCustomerFileService().getNextSignDate(customer, holder);
updateMessage(" - " + msg);
});
if (suggestDate == null) { if (suggestDate == null) {
suggestDate = LocalDate.now(); suggestDate = LocalDate.now();
} }
@@ -192,24 +181,24 @@ public class CompanyCustomerEvaluationFormUpdateTask extends Task<Object> {
setCellValue(sheet, "H6", "成立日期:" + company.getSetupDate()); setCellValue(sheet, "H6", "成立日期:" + company.getSetupDate());
// 所属行业 // 所属行业
setCellValue(sheet, "D7", "所属行业:" + company.getIndustry()); setCellValue(sheet, "D7", "所属行业:" + company.getIndustry());
setCellValue(sheet, "D8", "注册资金:" + company.getRegisteredCapital() + " " + company.getRegisteredCapitalCurrency()); setCellValue(sheet, "D8",
"注册资金:" + company.getRegisteredCapital() + " " + company.getRegisteredCapitalCurrency());
// 企业类型 // 企业类型
setCellValue(sheet, "H10", "企业类型:" + company.getEntType()); setCellValue(sheet, "H10", "企业类型:" + company.getEntType());
// 天眼评分 // 天眼评分
CloudTycService cloudTycService = SpringApp.getBean(CloudTycService.class); CloudTycService cloudTycService = SpringApp.getBean(CloudTycService.class);
CloudTyc cloudTyc = cloudTycService.getOrCreateCloudTyc(company); CloudTycVo cloudTyc = cloudTycService.getOrCreateCloudTyc(company);
setCellValue(sheet, "D10", "天眼评分:" + (cloudTyc.getScore() > 0 ? cloudTyc.getScore() : "")); setCellValue(sheet, "D10", "天眼评分:" + (cloudTyc.getScore() > 0 ? cloudTyc.getScore() : ""));
// 检索评估表 // 检索评估表
List<CompanyCustomerEvaluationFormFile> evaluationFormFiles = List<CompanyCustomerFileVo> customerFiles = getCompanyCustomerFileService().findAllByCustomerAndType(customer,
getCompanyCustomerFileService().findAllCustomerEvaluationFormFiles(customer); CustomerFileType.EvaluationForm);
List<CompanyCustomerEvaluationFormFile> filteredList = evaluationFormFiles.stream()
.filter(v -> { List<CompanyCustomerEvaluationFormFileVo> filteredList = customerFiles.stream().filter(file -> {
CompanyCustomerFile file = v.getCustomerFile();
return file.getSignDate() != null && file.isValid(); return file.getSignDate() != null && file.isValid();
}) })
.sorted(Comparator.comparing(v -> v.getCustomerFile().getSignDate())) .sorted(Comparator.comparing(CompanyCustomerFileVo::getSignDate))
.map(getCompanyCustomerEvaluationFormFileService()::findByCustomerFile)
.toList(); .toList();
if (filteredList.isEmpty()) { if (filteredList.isEmpty()) {
@@ -229,8 +218,8 @@ public class CompanyCustomerEvaluationFormUpdateTask extends Task<Object> {
setCellValue(sheet, "G40", "资信等级"); setCellValue(sheet, "G40", "资信等级");
String[] CreditLevelTitles = new String[] { "-", "差★", " 一般★★", " 较好★★★", " 好★★★★", " " }; String[] CreditLevelTitles = new String[] { "-", "差★", " 一般★★", " 较好★★★", " 好★★★★", " " };
int baseRow = 40; int baseRow = 40;
for (CompanyCustomerEvaluationFormFile form : filteredList) { for (CompanyCustomerEvaluationFormFileVo form : filteredList) {
CompanyCustomerFile customerFile = form.getCustomerFile(); CompanyCustomerFileVo customerFile = getCompanyCustomerFileService().findById(form.getCustomerFile());
setCellValue(sheet, baseRow, 2, String.valueOf(customerFile.getSignDate())); setCellValue(sheet, baseRow, 2, String.valueOf(customerFile.getSignDate()));
setCellValue(sheet, baseRow, 4, form.getCatalog()); setCellValue(sheet, baseRow, 4, form.getCatalog());
setCellValue(sheet, baseRow, 5, form.getLevel()); setCellValue(sheet, baseRow, 5, form.getLevel());
@@ -247,4 +236,5 @@ public class CompanyCustomerEvaluationFormUpdateTask extends Task<Object> {
} }
} }
} }
} }

View File

@@ -1,48 +1,61 @@
package com.ecep.contract.manager.ds.customer.controller; package com.ecep.contract.controller.customer;
import com.ecep.contract.manager.ds.company.model.Company; import static com.ecep.contract.util.ExcelUtils.setCellValue;
import com.ecep.contract.manager.ds.customer.model.CompanyCustomer;
import com.ecep.contract.manager.ds.customer.model.CompanyCustomerEntity;
import com.ecep.contract.manager.ds.customer.model.CompanyCustomerEvaluationFormFile;
import com.ecep.contract.manager.ds.customer.model.CompanyCustomerFile;
import com.ecep.contract.manager.ds.customer.service.CompanyCustomerEntityService;
import com.ecep.contract.manager.ds.customer.service.CompanyCustomerFileService;
import com.ecep.contract.manager.ds.customer.service.CompanyCustomerService;
import com.ecep.contract.manager.ui.MessageHolder;
import com.ecep.contract.manager.ui.Tasker;
import com.ecep.contract.manager.util.MyDateTimeUtils;
import com.ecep.contract.manager.util.UITools;
import lombok.Setter;
import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.AreaReference;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFTable;
import org.hibernate.Hibernate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Pageable;
import org.springframework.util.StringUtils;
import java.io.*; import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
import static com.ecep.contract.manager.util.ExcelUtils.*; import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.PrintSetup;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.ss.util.AreaReference;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFTable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Pageable;
import org.springframework.util.StringUtils;
import com.ecep.contract.MessageHolder;
import com.ecep.contract.MyDateTimeUtils;
import com.ecep.contract.service.CompanyCustomerEntityService;
import com.ecep.contract.service.CompanyCustomerEvaluationFormFileService;
import com.ecep.contract.service.CompanyCustomerFileService;
import com.ecep.contract.service.CompanyCustomerService;
import com.ecep.contract.task.Tasker;
import com.ecep.contract.util.ExcelUtils;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vo.CompanyCustomerEntityVo;
import com.ecep.contract.vo.CompanyCustomerEvaluationFormFileVo;
import com.ecep.contract.vo.CompanyCustomerFileVo;
import com.ecep.contract.vo.CompanyCustomerVo;
import com.ecep.contract.vo.CompanyVo;
import lombok.Setter;
public class CompanyCustomerExportExcelTasker extends Tasker<Object> { public class CompanyCustomerExportExcelTasker extends Tasker<Object> {
private static final Logger logger = LoggerFactory.getLogger(CompanyCustomerExportExcelTasker.class); private static final Logger logger = LoggerFactory.getLogger(CompanyCustomerExportExcelTasker.class);
@Setter @Setter
File destFile; File destFile;
CompanyCustomerService customerService; CompanyCustomerService customerService;
CompanyCustomerEntityService customerEntityService; CompanyCustomerEntityService customerEntityService;
CompanyCustomerFileService customerFileService; CompanyCustomerFileService customerFileService;
CompanyCustomerEvaluationFormFileService customerEvaluationFormFileService;
CompanyCustomerService getCustomerService() { CompanyCustomerService getCustomerService() {
if (customerService == null) if (customerService == null)
@@ -55,12 +68,19 @@ public class CompanyCustomerExportExcelTasker extends Tasker<Object> {
customerFileService = getBean(CompanyCustomerFileService.class); customerFileService = getBean(CompanyCustomerFileService.class);
return customerFileService; return customerFileService;
} }
CompanyCustomerEntityService getCustomerEntityService() { CompanyCustomerEntityService getCustomerEntityService() {
if (customerEntityService == null) if (customerEntityService == null)
customerEntityService = getBean(CompanyCustomerEntityService.class); customerEntityService = getBean(CompanyCustomerEntityService.class);
return customerEntityService; return customerEntityService;
} }
CompanyCustomerEvaluationFormFileService getCustomerEvaluationFormFileService() {
if (customerEvaluationFormFileService == null)
customerEvaluationFormFileService = getBean(CompanyCustomerEvaluationFormFileService.class);
return customerEvaluationFormFileService;
}
@Override @Override
protected Object execute(MessageHolder holder) throws Exception { protected Object execute(MessageHolder holder) throws Exception {
if (destFile.exists()) { if (destFile.exists()) {
@@ -78,8 +98,7 @@ public class CompanyCustomerExportExcelTasker extends Tasker<Object> {
} }
try ( try (
InputStream inp = new FileInputStream(template); InputStream inp = new FileInputStream(template);
Workbook wb = WorkbookFactory.create(inp); Workbook wb = WorkbookFactory.create(inp);) {
) {
String sheetName = "客户资信台账"; String sheetName = "客户资信台账";
Sheet sheet = null; Sheet sheet = null;
for (int i = 0; i < wb.getNumberOfSheets(); i++) { for (int i = 0; i < wb.getNumberOfSheets(); i++) {
@@ -99,55 +118,49 @@ public class CompanyCustomerExportExcelTasker extends Tasker<Object> {
setCellValue(sheet, "A19", "Build by CMS @ " + MyDateTimeUtils.format(LocalDateTime.now())); setCellValue(sheet, "A19", "Build by CMS @ " + MyDateTimeUtils.format(LocalDateTime.now()));
int rowIndex = 0; int rowIndex = 0;
for (CompanyCustomer customer : getCustomerService().findAll(null, Pageable.unpaged())) { for (CompanyCustomerVo customer : getCustomerService().findAll(null, Pageable.unpaged())) {
Company company = customer.getCompany(); Integer companyId = customer.getCompanyId();
;
CompanyVo company = getCompanyService().findById(companyId);
if (company == null) { if (company == null) {
holder.warn("客户 #" + customer.getId() + " 不存在对应公司"); holder.warn("客户 #" + customer.getId() + " 不存在对应公司");
continue; continue;
} }
if (!Hibernate.isInitialized(company)) { // VO类不需要延迟加载代理直接使用即可
company = getCompanyService().findById(company.getId());
}
LocalDate devDate = null; LocalDate devDate = null;
List<CompanyCustomerEntity> entities = getCustomerEntityService() .findAllByCustomer(customer); List<CompanyCustomerEntityVo> entities = getCustomerEntityService().findAllByCustomer(customer);
for (CompanyCustomerEntity entity : entities) { for (CompanyCustomerEntityVo entity : entities) {
if (devDate == null || devDate.isAfter(entity.getDevelopDate())) { if (devDate == null || devDate.isAfter(entity.getDevelopDate())) {
devDate = entity.getDevelopDate(); devDate = entity.getDevelopDate();
} }
} }
CompanyCustomerFileVo customerFile = getCustomerFileService()
.findAllByCustomer(customer).stream().filter(v -> v.isValid())
.max(Comparator.comparing(v -> v.getSignDate())).orElse(null);
CompanyCustomerEvaluationFormFile evaluationFormFile = getCustomerFileService().findAllCustomerEvaluationFormFiles(customer).stream().filter(v -> {
CompanyCustomerFile customerFile = v.getCustomerFile();
if (customerFile == null) { if (customerFile == null) {
return false;
}
return customerFile.isValid();
}).max(Comparator.comparing(v -> v.getCustomerFile().getSignDate())).orElse(null);
if (evaluationFormFile == null) {
holder.warn(company.getName() + " 未匹配的客户评估"); holder.warn(company.getName() + " 未匹配的客户评估");
continue; continue;
} }
CompanyCustomerFile customerFile = evaluationFormFile.getCustomerFile();
if (devDate != null && devDate.isAfter(customerFile.getSignDate())) { if (devDate != null && devDate.isAfter(customerFile.getSignDate())) {
holder.debug(company.getName() + " 最新评估日期早于客户开发日期,评估日期:" + customerFile.getSignDate() + ", 开发日期:" + devDate); holder.debug(company.getName() + " 最新评估日期早于客户开发日期,评估日期:" + customerFile.getSignDate() + ", 开发日期:"
+ devDate);
} }
rowIndex++; rowIndex++;
if (rowIndex > 11) { if (rowIndex > 11) {
// 插入行并复制行的格式 // 插入行并复制行的格式
sheet.shiftRows(rowIndex + 3, sheet.getLastRowNum(), 1); sheet.shiftRows(rowIndex + 3, sheet.getLastRowNum(), 1);
Row templateRow = getRow(sheet, rowIndex + 2, true); Row templateRow = ExcelUtils.getRow(sheet, rowIndex + 2, true);
Row newRow = getRow(sheet, rowIndex + 3, true); Row newRow = ExcelUtils.getRow(sheet, rowIndex + 3, true);
if (templateRow != null && newRow != null) { if (templateRow != null && newRow != null) {
for (int i = 0; i < templateRow.getLastCellNum(); i++) { for (int i = 0; i < templateRow.getLastCellNum(); i++) {
Cell templateCell = templateRow.getCell(i); Cell templateCell = templateRow.getCell(i);
Cell newCell = getCell(newRow, i, true); Cell newCell = ExcelUtils.getCell(newRow, i, true);
if (templateCell != null && newCell != null) { if (templateCell != null && newCell != null) {
newCell.setCellStyle(templateCell.getCellStyle()); newCell.setCellStyle(templateCell.getCellStyle());
} }
@@ -155,8 +168,9 @@ public class CompanyCustomerExportExcelTasker extends Tasker<Object> {
} }
} }
Row row = ExcelUtils.getRow(sheet, rowIndex + 3, true);
Row row = getRow(sheet, rowIndex + 3, true); CompanyCustomerEvaluationFormFileVo evaluationFormFile = getCustomerEvaluationFormFileService()
.findByCustomerFile(customerFile);
setCellValue(row, 0, rowIndex); setCellValue(row, 0, rowIndex);
setCellValue(row, 1, company.getName()); setCellValue(row, 1, company.getName());
@@ -173,7 +187,8 @@ public class CompanyCustomerExportExcelTasker extends Tasker<Object> {
for (XSSFTable table : ((XSSFSheet) sheet).getTables()) { for (XSSFTable table : ((XSSFSheet) sheet).getTables()) {
if ("表2".equals(table.getName())) { if ("表2".equals(table.getName())) {
holder.info("找到表=" + table.getName() + ", style=" + table.getStyleName()); holder.info("找到表=" + table.getName() + ", style=" + table.getStyleName());
table.setCellReferences(new AreaReference("$A$4:$H$" + (rowIndex + 4), SpreadsheetVersion.EXCEL2007)); table.setCellReferences(
new AreaReference("$A$4:$H$" + (rowIndex + 4), SpreadsheetVersion.EXCEL2007));
// table.setDataRowCount(rowIndex); // table.setDataRowCount(rowIndex);
// table.getCTTable().setRef("$A$4:$H$" + (rowIndex + 4)); // table.getCTTable().setRef("$A$4:$H$" + (rowIndex + 4));
@@ -200,7 +215,6 @@ public class CompanyCustomerExportExcelTasker extends Tasker<Object> {
UITools.showExceptionAndWait("保存失败", e); UITools.showExceptionAndWait("保存失败", e);
} }
return null; return null;
} }
} }

View File

@@ -1,32 +1,26 @@
package com.ecep.contract.manager.ds.customer.controller; package com.ecep.contract.controller.customer;
import com.ecep.contract.manager.ui.table.cell.CompanyTableCell; import com.ecep.contract.MyDateTimeUtils;
import com.ecep.contract.manager.ds.company.service.CompanyService; import com.ecep.contract.controller.AbstEntityManagerSkin;
import com.ecep.contract.manager.ds.customer.model.CompanyCustomer; import com.ecep.contract.controller.table.cell.CompanyTableCell;
import com.ecep.contract.manager.ds.customer.service.CompanyCustomerService; import com.ecep.contract.service.CompanyCustomerService;
import com.ecep.contract.manager.ds.customer.vo.CompanyCustomerViewModel; import com.ecep.contract.service.CompanyService;
import com.ecep.contract.manager.ui.AbstEntityManagerSkin; import com.ecep.contract.vm.CompanyCustomerViewModel;
import com.ecep.contract.manager.util.MyDateTimeUtils; import com.ecep.contract.vo.CompanyCustomerVo;
import com.ecep.contract.vo.CompanyVo;
import javafx.application.Platform; import javafx.application.Platform;
import lombok.Setter;
public class CompanyCustomerManagerSkin public class CompanyCustomerManagerSkin
extends extends
AbstEntityManagerSkin<CompanyCustomer, CompanyCustomerViewModel, CompanyCustomerManagerSkin, CompanyCustomerManagerWindowController> { AbstEntityManagerSkin<CompanyCustomerVo, CompanyCustomerViewModel, CompanyCustomerManagerSkin, CompanyCustomerManagerWindowController> {
@Setter
private CompanyService companyService;
public CompanyCustomerManagerSkin(CompanyCustomerManagerWindowController controller) { public CompanyCustomerManagerSkin(CompanyCustomerManagerWindowController controller) {
super(controller); super(controller);
} }
public CompanyService getCompanyService() { public CompanyService getCompanyService() {
if (companyService == null) { return getBean(CompanyService.class);
companyService = getBean(CompanyService.class);
}
return companyService;
} }
public CompanyCustomerService getCompanyCustomerService() { public CompanyCustomerService getCompanyCustomerService() {

View File

@@ -1,11 +1,12 @@
package com.ecep.contract.manager.ds.customer.controller; package com.ecep.contract.controller.customer;
import java.io.File; import java.io.File;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import org.hibernate.Hibernate; import com.ecep.contract.vo.CompanyCustomerVo;
import com.ecep.contract.vo.CompanyVo;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
@@ -14,15 +15,13 @@ import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.ecep.contract.manager.ds.company.model.Company; import com.ecep.contract.MyDateTimeUtils;
import com.ecep.contract.manager.ds.company.service.CompanyService; import com.ecep.contract.controller.AbstManagerWindowController;
import com.ecep.contract.manager.ds.customer.model.CompanyCustomer; import com.ecep.contract.service.CompanyCustomerService;
import com.ecep.contract.manager.ds.customer.service.CompanyCustomerService; import com.ecep.contract.service.CompanyService;
import com.ecep.contract.manager.ds.customer.vo.CompanyCustomerViewModel; import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.manager.ui.AbstManagerWindowController; import com.ecep.contract.util.UITools;
import com.ecep.contract.manager.ui.FxmlPath; import com.ecep.contract.vm.CompanyCustomerViewModel;
import com.ecep.contract.manager.util.MyDateTimeUtils;
import com.ecep.contract.manager.util.UITools;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
@@ -45,24 +44,28 @@ import javafx.stage.Stage;
@Component @Component
@FxmlPath("/ui/company/customer/customer_manager.fxml") @FxmlPath("/ui/company/customer/customer_manager.fxml")
public class CompanyCustomerManagerWindowController public class CompanyCustomerManagerWindowController
extends AbstManagerWindowController<CompanyCustomer, CompanyCustomerViewModel, CompanyCustomerManagerSkin> { extends AbstManagerWindowController<CompanyCustomerVo, CompanyCustomerViewModel, CompanyCustomerManagerSkin> {
// columns // columns
public TableColumn<CompanyCustomerViewModel, Number> idColumn; public TableColumn<CompanyCustomerViewModel, Number> idColumn;
public TableColumn<CompanyCustomerViewModel, Company> companyColumn; /**
* 客户所属公司,Company
*/
public TableColumn<CompanyCustomerViewModel, Integer> companyColumn;
public TableColumn<CompanyCustomerViewModel, String> catalogColumn; public TableColumn<CompanyCustomerViewModel, String> catalogColumn;
public TableColumn<CompanyCustomerViewModel, LocalDate> developDateColumn; public TableColumn<CompanyCustomerViewModel, LocalDate> developDateColumn;
public TableColumn<CompanyCustomerViewModel, String> pathColumn; public TableColumn<CompanyCustomerViewModel, String> pathColumn;
public TableColumn<CompanyCustomerViewModel, String> createdColumn; public TableColumn<CompanyCustomerViewModel, String> createdColumn;
@Autowired
private CompanyService companyService;
@Autowired
private CompanyCustomerService companyCustomerService;
@Override @Override
public CompanyCustomerService getViewModelService() { public CompanyCustomerService getViewModelService() {
return companyCustomerService; return getCachedBean(CompanyCustomerService.class);
}
@Autowired
private CompanyService getCompanyService() {
return getCachedBean(CompanyService.class);
} }
@Override @Override
@@ -74,7 +77,6 @@ public class CompanyCustomerManagerWindowController
@Override @Override
protected CompanyCustomerManagerSkin createDefaultSkin() { protected CompanyCustomerManagerSkin createDefaultSkin() {
CompanyCustomerManagerSkin skin = new CompanyCustomerManagerSkin(this); CompanyCustomerManagerSkin skin = new CompanyCustomerManagerSkin(this);
skin.setCompanyService(companyService);
return skin; return skin;
} }
@@ -116,21 +118,18 @@ public class CompanyCustomerManagerWindowController
CompletableFuture.runAsync(() -> { CompletableFuture.runAsync(() -> {
Pageable pageRequest = PageRequest.ofSize(50); Pageable pageRequest = PageRequest.ofSize(50);
while (!canceled.get()) { while (!canceled.get()) {
Page<CompanyCustomer> page = companyCustomerService.findAll(null, pageRequest); Page<CompanyCustomerVo> page = getViewModelService().findAll(null, pageRequest);
int index = page.getNumber() * page.getSize(); int index = page.getNumber() * page.getSize();
int i = 1; int i = 1;
for (CompanyCustomer companyCustomer : page) { for (CompanyCustomerVo companyCustomer : page) {
if (canceled.get()) { if (canceled.get()) {
return; return;
} }
Company company = companyCustomer.getCompany();
if (!Hibernate.isInitialized(company)) {
company = companyService.findById(company.getId());
}
CompanyVo company = getCompanyService().findById(companyCustomer.getCompanyId());
String prefix = (index + i) + "/" + page.getTotalElements() + ", " + company.getName() + "> "; String prefix = (index + i) + "/" + page.getTotalElements() + ", " + company.getName() + "> ";
companyCustomerService.reBuildingFiles(companyCustomer, msg -> { getViewModelService().reBuildingFiles(companyCustomer, (level, msg) -> {
Platform.runLater(() -> { Platform.runLater(() -> {
listViewDataSet.add(prefix + msg); listViewDataSet.add(prefix + msg);
listView.scrollTo(listViewDataSet.size() - 1); listView.scrollTo(listViewDataSet.size() - 1);
@@ -164,7 +163,7 @@ public class CompanyCustomerManagerWindowController
FileChooser fileChooser = new FileChooser(); FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("导出"); fileChooser.setTitle("导出");
fileChooser.setInitialFileName("客户资信台账-" + MyDateTimeUtils.format(LocalDate.now()) + ".xlsx"); fileChooser.setInitialFileName("客户资信台账-" + MyDateTimeUtils.format(LocalDate.now()) + ".xlsx");
fileChooser.setInitialDirectory(companyCustomerService.getBasePath()); fileChooser.setInitialDirectory(getViewModelService().getBasePath());
File destFile = fileChooser.showSaveDialog(table.getScene().getWindow()); File destFile = fileChooser.showSaveDialog(table.getScene().getWindow());
tasker.setDestFile(destFile); tasker.setDestFile(destFile);
UITools.showTaskDialogAndWait("导出Excel", tasker, null); UITools.showTaskDialogAndWait("导出Excel", tasker, null);

View File

@@ -1,20 +1,24 @@
package com.ecep.contract.manager.ds.customer.controller; package com.ecep.contract.controller.customer;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import com.ecep.contract.MyDateTimeUtils;
import com.ecep.contract.SpringApp;
import com.ecep.contract.controller.company.CompanyWindowController;
import com.ecep.contract.controller.tab.AbstEntityBasedTabSkin;
import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.converter.CompanyStringConverter;
import com.ecep.contract.converter.EntityStringConverter;
import com.ecep.contract.vo.CompanyVo;
import com.ecep.contract.vo.CompanyContactVo;
import com.ecep.contract.vo.CompanyCustomerVo;
import com.ecep.contract.service.CompanyContactService;
import com.ecep.contract.service.CompanyCustomerService;
import com.ecep.contract.service.CompanyService;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.CompanyCustomerViewModel;
import com.ecep.contract.manager.SpringApp;
import com.ecep.contract.manager.ds.company.CompanyStringConverter;
import com.ecep.contract.manager.ds.company.controller.CompanyWindowController;
import com.ecep.contract.manager.ds.company.model.Company;
import com.ecep.contract.manager.ds.company.model.CompanyContact;
import com.ecep.contract.manager.ds.company.service.CompanyContactService;
import com.ecep.contract.manager.ds.company.service.CompanyService;
import com.ecep.contract.manager.ds.customer.model.CompanyCustomer;
import com.ecep.contract.manager.ds.customer.service.CompanyCustomerService;
import com.ecep.contract.manager.ds.customer.vo.CompanyCustomerViewModel;
import com.ecep.contract.manager.ds.other.EntityStringConverter;
import com.ecep.contract.manager.ui.tab.AbstEntityBasedTabSkin;
import com.ecep.contract.manager.ui.tab.TabSkin;
import com.ecep.contract.manager.util.MyDateTimeUtils;
import com.ecep.contract.manager.util.UITools;
import javafx.beans.binding.Bindings; import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleObjectProperty;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
@@ -22,11 +26,8 @@ import javafx.scene.control.Tab;
import javafx.scene.control.TextField; import javafx.scene.control.TextField;
import javafx.util.converter.LocalDateStringConverter; import javafx.util.converter.LocalDateStringConverter;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class CompanyCustomerTabSkinBase public class CompanyCustomerTabSkinBase
extends AbstEntityBasedTabSkin<CompanyCustomerWindowController, CompanyCustomer, CompanyCustomerViewModel> extends AbstEntityBasedTabSkin<CompanyCustomerWindowController, CompanyCustomerVo, CompanyCustomerViewModel>
implements TabSkin { implements TabSkin {
public CompanyCustomerTabSkinBase(CompanyCustomerWindowController controller) { public CompanyCustomerTabSkinBase(CompanyCustomerWindowController controller) {
@@ -43,6 +44,8 @@ public class CompanyCustomerTabSkinBase
initializeCompanyFieldAutoCompletion(controller.companyField); initializeCompanyFieldAutoCompletion(controller.companyField);
initializeContactFieldAutoCompletion(controller.contactField); initializeContactFieldAutoCompletion(controller.contactField);
UITools.autoCompletion(controller.contactField, viewModel.getContact(), getCompanyContactService());
LocalDateStringConverter converter = new LocalDateStringConverter(DateTimeFormatter.ISO_LOCAL_DATE, null); LocalDateStringConverter converter = new LocalDateStringConverter(DateTimeFormatter.ISO_LOCAL_DATE, null);
controller.developDateField.setConverter(converter); controller.developDateField.setConverter(converter);
@@ -53,19 +56,20 @@ public class CompanyCustomerTabSkinBase
controller.createdField.textProperty().bind( controller.createdField.textProperty().bind(
Bindings.createStringBinding( Bindings.createStringBinding(
() -> localDateTimeFormatter(viewModel.getCreated()), () -> localDateTimeFormatter(viewModel.getCreated()),
viewModel.getCreated()) viewModel.getCreated()));
);
controller.versionLabel.textProperty().bind(viewModel.getVersion().asString()); controller.versionLabel.textProperty().bind(viewModel.getVersion().asString());
controller.relativeCompanyBtn.disableProperty().bind(viewModel.getCompany().isNull()); controller.relativeCompanyBtn.disableProperty().bind(viewModel.getCompany().isNull());
controller.relativeCompanyBtn.setOnAction(event -> { controller.relativeCompanyBtn.setOnAction(event -> {
Company company = viewModel.getCompany().get(); Integer companyId = viewModel.getCompany().get();
if (companyId != null) {
CompanyVo company = getCompanyService().findById(companyId);
if (company != null) { if (company != null) {
CompanyWindowController.show(company, controller.root.getScene().getWindow()); CompanyWindowController.show(company, controller.root.getScene().getWindow());
} }
}
}); });
controller.createPathBtn.setOnAction(this::onCompanyCustomerCreatePathAction); controller.createPathBtn.setOnAction(this::onCompanyCustomerCreatePathAction);
controller.changePathBtn.setOnAction(this::onCompanyCustomerChangePathAction); controller.changePathBtn.setOnAction(this::onCompanyCustomerChangePathAction);
controller.pathAsNameBtn.setOnAction(this::onCompanyCustomerPathSameAsNameAction); controller.pathAsNameBtn.setOnAction(this::onCompanyCustomerPathSameAsNameAction);
@@ -80,18 +84,15 @@ public class CompanyCustomerTabSkinBase
} }
private void initializeContactFieldAutoCompletion(TextField textField) { private void initializeContactFieldAutoCompletion(TextField textField) {
EntityStringConverter<CompanyContact> stringConverter = new EntityStringConverter<>(); UITools.autoCompletion(textField, viewModel.getContact(), getCompanyContactService());
stringConverter.setInitialized(cc -> getCompanyContactService().findById(cc.getId()));
UITools.autoCompletion(textField, viewModel.getContact(), p -> getCompanyContactService().searchByCompany(viewModel.getCompany().get(), p.getUserText()), stringConverter);
} }
private void initializeCompanyFieldAutoCompletion(TextField textField) { private void initializeCompanyFieldAutoCompletion(TextField textField) {
CompanyStringConverter converter = SpringApp.getBean(CompanyStringConverter.class); UITools.autoCompletion(textField, viewModel.getCompany(), getCompanyService());
UITools.autoCompletion(textField, viewModel.getCompany(), converter::suggest, converter);
} }
public void onCompanyCustomerCreatePathAction(ActionEvent event) { public void onCompanyCustomerCreatePathAction(ActionEvent event) {
CompanyCustomer companyCustomer = getCompanyCustomerService().findById(viewModel.getId().get()); CompanyCustomerVo companyCustomer = getCompanyCustomerService().findById(viewModel.getId().get());
if (getCompanyCustomerService().makePathAbsent(companyCustomer)) { if (getCompanyCustomerService().makePathAbsent(companyCustomer)) {
companyCustomer = getCompanyCustomerService().save(companyCustomer); companyCustomer = getCompanyCustomerService().save(companyCustomer);
viewModel.update(companyCustomer); viewModel.update(companyCustomer);
@@ -100,7 +101,6 @@ public class CompanyCustomerTabSkinBase
} }
} }
public void onCompanyCustomerChangePathAction(ActionEvent event) { public void onCompanyCustomerChangePathAction(ActionEvent event) {
setStatus("未实现"); setStatus("未实现");
} }
@@ -110,14 +110,14 @@ public class CompanyCustomerTabSkinBase
} }
public CompanyCustomerService getCompanyCustomerService() { public CompanyCustomerService getCompanyCustomerService() {
return controller.companyCustomerService; return controller.getCachedBean(CompanyCustomerService.class);
} }
public CompanyContactService getCompanyContactService() { public CompanyContactService getCompanyContactService() {
return controller.companyContactService; return controller.getCachedBean(CompanyContactService.class);
} }
public CompanyService getCompanyService() { public CompanyService getCompanyService() {
return controller.companyService; return controller.getCachedBean(CompanyService.class);
} }
} }

View File

@@ -1,45 +1,49 @@
package com.ecep.contract.manager.ds.customer.controller; package com.ecep.contract.controller.customer;
import com.ecep.contract.manager.ds.company.service.CompanyContactService; import java.io.File;
import com.ecep.contract.manager.ds.company.service.CompanyService;
import com.ecep.contract.manager.ds.customer.model.CompanyCustomer;
import com.ecep.contract.manager.ds.customer.service.CompanyCustomerService;
import com.ecep.contract.manager.ds.customer.vo.CompanyCustomerViewModel;
import com.ecep.contract.manager.ui.AbstEntityController;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.ui.ViewModelService;
import com.ecep.contract.manager.util.DesktopUtils;
import javafx.event.ActionEvent;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.stage.Window;
import javafx.stage.WindowEvent;
import org.hibernate.Hibernate;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import java.io.File; import com.ecep.contract.DesktopUtils;
import com.ecep.contract.controller.AbstEntityController;
import com.ecep.contract.service.CompanyContactService;
import com.ecep.contract.service.CompanyCustomerService;
import com.ecep.contract.service.CompanyService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.vm.CompanyCustomerViewModel;
import com.ecep.contract.vo.CompanyCustomerVo;
import com.ecep.contract.vo.CompanyVo;
import javafx.event.ActionEvent;
import javafx.scene.control.Button;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.stage.Window;
import javafx.stage.WindowEvent;
@Lazy @Lazy
@Scope("prototype") @Scope("prototype")
@Component @Component
@FxmlPath("/ui/company/customer/customer.fxml") @FxmlPath("/ui/company/customer/customer.fxml")
public class CompanyCustomerWindowController extends AbstEntityController<CompanyCustomer, CompanyCustomerViewModel> { public class CompanyCustomerWindowController extends AbstEntityController<CompanyCustomerVo, CompanyCustomerViewModel> {
private static final Logger logger = LoggerFactory.getLogger(CompanyCustomerWindowController.class); private static final Logger logger = LoggerFactory.getLogger(CompanyCustomerWindowController.class);
/** /**
* 显示界面 * 显示界面
*/ */
public static void show(CompanyCustomer customer, Window window) { public static void show(CompanyCustomerVo customer, Window window) {
CompanyCustomerViewModel viewModel = new CompanyCustomerViewModel(); show(CompanyCustomerWindowController.class, CompanyCustomerViewModel.from(customer), window);
viewModel.update(customer);
show(CompanyCustomerWindowController.class, viewModel, window);
} }
public Tab baseInfoTab; public Tab baseInfoTab;
@@ -48,14 +52,6 @@ public class CompanyCustomerWindowController extends AbstEntityController<Compan
public Tab fileTab; public Tab fileTab;
public Tab entityTab; public Tab entityTab;
public Tab satisfactionTab; public Tab satisfactionTab;
@Autowired
CompanyService companyService;
@Autowired
CompanyCustomerService companyCustomerService;
@Autowired
CompanyContactService companyContactService;
public TextField companyField; public TextField companyField;
public TextField contactField; public TextField contactField;
public TextField pathField; public TextField pathField;
@@ -70,18 +66,14 @@ public class CompanyCustomerWindowController extends AbstEntityController<Compan
public Button pathAsNameBtn; public Button pathAsNameBtn;
public Button OpenCustomerPathInExplorerBtn; public Button OpenCustomerPathInExplorerBtn;
@Override @Override
public void show(Stage stage) { public void show(Stage stage) {
super.show(stage); super.show(stage);
getTitle().bind(viewModel.getCompany().map(company -> { getTitle().bind(viewModel.getCompany().map(companyId -> {
if (company == null) { if (companyId == null) {
return "-"; return "-";
} }
if (!Hibernate.isInitialized(company)) { CompanyVo company = getCompanyService().findById(companyId);
company = companyService.findById(company.getId());
viewModel.getCompany().set(company);
}
return getMessage("ui.customer.title", String.valueOf(viewModel.getId().get()), company.getName()); return getMessage("ui.customer.title", String.valueOf(viewModel.getId().get()), company.getName());
})); }));
} }
@@ -96,7 +88,15 @@ public class CompanyCustomerWindowController extends AbstEntityController<Compan
@Override @Override
public CompanyCustomerService getViewModelService() { public CompanyCustomerService getViewModelService() {
return companyCustomerService; return getCachedBean(CompanyCustomerService.class);
}
public CompanyService getCompanyService() {
return getCachedBean(CompanyService.class);
}
public CompanyContactService getCompanyContactService() {
return getCachedBean(CompanyContactService.class);
} }
@Override @Override
@@ -119,6 +119,4 @@ public class CompanyCustomerWindowController extends AbstEntityController<Compan
DesktopUtils.showInExplorer(file); DesktopUtils.showInExplorer(file);
} }
} }

View File

@@ -1,38 +1,36 @@
package com.ecep.contract.manager.ds.customer.controller; package com.ecep.contract.controller.customer;
import com.ecep.contract.manager.SpringApp;
import com.ecep.contract.manager.ds.customer.model.CompanyCustomer;
import com.ecep.contract.manager.ds.customer.model.CompanyCustomerEntity;
import com.ecep.contract.manager.ds.customer.model.CustomerCatalog;
import com.ecep.contract.manager.ds.customer.service.CompanyCustomerEntityService;
import com.ecep.contract.manager.ds.customer.vo.CustomerEntityViewModel;
import com.ecep.contract.manager.ds.other.EmployeeStringConverter;
import com.ecep.contract.manager.ds.other.EntityStringConverter;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.ui.table.cell.LocalDateTimeTableCell;
import com.ecep.contract.manager.util.SpecificationUtils;
import javafx.scene.control.MenuItem;
import javafx.scene.control.Tab;
import javafx.scene.control.TableColumn;
import lombok.Setter;
import org.springframework.data.jpa.domain.Specification;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import com.ecep.contract.controller.table.cell.CustomerCatalogTableCell;
import com.ecep.contract.controller.table.cell.EmployeeTableCell;
import com.ecep.contract.controller.table.cell.LocalDateTimeTableCell;
import com.ecep.contract.service.CompanyCustomerEntityService;
import com.ecep.contract.service.CustomerCatalogService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.ParamUtils;
import com.ecep.contract.vm.CustomerEntityViewModel;
import com.ecep.contract.vo.CompanyCustomerEntityVo;
import com.ecep.contract.vo.CompanyCustomerVo;
import javafx.scene.control.MenuItem;
import javafx.scene.control.Tab;
import javafx.scene.control.TableColumn;
@FxmlPath("/ui/company/customer/customer-tab-entity.fxml") @FxmlPath("/ui/company/customer/customer-tab-entity.fxml")
public class CustomerTabSkinEntity public class CustomerTabSkinEntity
extends AbstCompanyCustomerTableTabSkin<CompanyCustomerEntity, CustomerEntityViewModel> { extends AbstCompanyCustomerTableTabSkin<CompanyCustomerEntityVo, CustomerEntityViewModel> {
// 关联项 tab // 关联项 tab
public TableColumn<CustomerEntityViewModel, Number> entityTable_idColumn; public TableColumn<CustomerEntityViewModel, Number> entityTable_idColumn;
public TableColumn<CustomerEntityViewModel, String> entityTable_catalogColumn; public TableColumn<CustomerEntityViewModel, Integer> entityTable_catalogColumn;
public TableColumn<CustomerEntityViewModel, String> entityTable_nameColumn; public TableColumn<CustomerEntityViewModel, String> entityTable_nameColumn;
public TableColumn<CustomerEntityViewModel, String> entityTable_abbNameColumn; public TableColumn<CustomerEntityViewModel, String> entityTable_abbNameColumn;
public TableColumn<CustomerEntityViewModel, String> entityTable_codeColumn; public TableColumn<CustomerEntityViewModel, String> entityTable_codeColumn;
public TableColumn<CustomerEntityViewModel, String> entityTable_creatorColumn; public TableColumn<CustomerEntityViewModel, Integer> entityTable_creatorColumn;
public TableColumn<CustomerEntityViewModel, LocalDate> entityTable_developDateColumn; public TableColumn<CustomerEntityViewModel, LocalDate> entityTable_developDateColumn;
public TableColumn<CustomerEntityViewModel, String> entityTable_modifierColumn; public TableColumn<CustomerEntityViewModel, Integer> entityTable_modifierColumn;
public TableColumn<CustomerEntityViewModel, LocalDate> entityTable_modifyDateColumn; public TableColumn<CustomerEntityViewModel, LocalDate> entityTable_modifyDateColumn;
public TableColumn<CustomerEntityViewModel, LocalDate> entityTable_updatedDateColumn; public TableColumn<CustomerEntityViewModel, LocalDate> entityTable_updatedDateColumn;
public TableColumn<CustomerEntityViewModel, LocalDateTime> fetchedTimeColumn; public TableColumn<CustomerEntityViewModel, LocalDateTime> fetchedTimeColumn;
@@ -40,9 +38,6 @@ public class CustomerTabSkinEntity
public MenuItem entityTable_menu_refresh; public MenuItem entityTable_menu_refresh;
public MenuItem entityTable_menu_del; public MenuItem entityTable_menu_del;
@Setter
private CompanyCustomerEntityService customerEntityService;
public CustomerTabSkinEntity(CompanyCustomerWindowController controller) { public CustomerTabSkinEntity(CompanyCustomerWindowController controller) {
super(controller); super(controller);
} }
@@ -52,7 +47,6 @@ public class CustomerTabSkinEntity
return controller.entityTab; return controller.entityTab;
} }
@Override @Override
public void initializeTab() { public void initializeTab() {
super.initializeTab(); super.initializeTab();
@@ -61,34 +55,28 @@ public class CustomerTabSkinEntity
entityTable_nameColumn.setCellValueFactory(param -> param.getValue().getName()); entityTable_nameColumn.setCellValueFactory(param -> param.getValue().getName());
entityTable_abbNameColumn.setCellValueFactory(param -> param.getValue().getAbbName()); entityTable_abbNameColumn.setCellValueFactory(param -> param.getValue().getAbbName());
entityTable_codeColumn.setCellValueFactory(param -> param.getValue().getCode()); entityTable_codeColumn.setCellValueFactory(param -> param.getValue().getCode());
initializeEntityTabCatalogColumn(entityTable_catalogColumn);
EmployeeStringConverter stringConverter = SpringApp.getBean(EmployeeStringConverter.class); entityTable_catalogColumn.setCellValueFactory(param -> param.getValue().getCatalog());
entityTable_catalogColumn.setCellFactory(CustomerCatalogTableCell.forTableColumn(getCustomerCatalogService()));
entityTable_developDateColumn.setCellValueFactory(param -> param.getValue().getDevelopDate()); entityTable_developDateColumn.setCellValueFactory(param -> param.getValue().getDevelopDate());
entityTable_modifyDateColumn.setCellValueFactory(param -> param.getValue().getModifyDate()); entityTable_modifyDateColumn.setCellValueFactory(param -> param.getValue().getModifyDate());
entityTable_creatorColumn.setCellValueFactory(param -> param.getValue().getCreator().map(stringConverter::toString));
entityTable_modifierColumn.setCellValueFactory(param -> param.getValue().getModifier().map(stringConverter::toString));
entityTable_updatedDateColumn.setCellValueFactory(param -> param.getValue().getUpdatedDate()); entityTable_updatedDateColumn.setCellValueFactory(param -> param.getValue().getUpdatedDate());
fetchedTimeColumn.setCellValueFactory(param -> param.getValue().getFetchedTime()); fetchedTimeColumn.setCellValueFactory(param -> param.getValue().getFetchedTime());
fetchedTimeColumn.setCellFactory(param -> new LocalDateTimeTableCell<>()); fetchedTimeColumn.setCellFactory(param -> new LocalDateTimeTableCell<>());
entityTable_creatorColumn.setCellValueFactory(param -> param.getValue().getCreator());
entityTable_creatorColumn.setCellFactory(EmployeeTableCell.forTableColumn(getEmployeeService()));
entityTable_modifierColumn.setCellValueFactory(param -> param.getValue().getModifier());
entityTable_modifierColumn.setCellFactory(EmployeeTableCell.forTableColumn(getEmployeeService()));
entityTable_menu_refresh.setOnAction(this::onTableRefreshAction); entityTable_menu_refresh.setOnAction(this::onTableRefreshAction);
entityTable_menu_del.setOnAction(this::onTableDeleteAction); entityTable_menu_del.setOnAction(this::onTableDeleteAction);
} }
private void initializeEntityTabCatalogColumn(TableColumn<CustomerEntityViewModel, String> column) {
EntityStringConverter<CustomerCatalog> converter = new EntityStringConverter<>();
converter.setInitialized(v -> getCompanyCustomerService().findCatalogById(v.getId()));
column.setCellValueFactory(param -> param.getValue().getCatalog().map(converter::toString));
}
CompanyCustomerEntityService getCompanyCustomerEntityService() { CompanyCustomerEntityService getCompanyCustomerEntityService() {
if (customerEntityService == null) { return getCachedBean(CompanyCustomerEntityService.class);
customerEntityService = getBean(CompanyCustomerEntityService.class);
}
return customerEntityService;
} }
@Override @Override
@@ -96,11 +84,15 @@ public class CustomerTabSkinEntity
return getCompanyCustomerEntityService(); return getCompanyCustomerEntityService();
} }
CustomerCatalogService getCustomerCatalogService() {
return getCachedBean(CustomerCatalogService.class);
}
@Override @Override
public Specification<CompanyCustomerEntity> getSpecification(CompanyCustomer parent) { public ParamUtils.Builder getSpecification(CompanyCustomerVo parent) {
return SpecificationUtils.and(getSpecification(), (root, query, builder) -> { ParamUtils.Builder params = getSpecification();
return builder.equal(root.get("customer"), parent); params.equals("customer", parent.getId());
}); return params;
} }
} }

View File

@@ -1,55 +1,63 @@
package com.ecep.contract.manager.ds.customer.controller; package com.ecep.contract.controller.customer;
import com.ecep.contract.manager.SpringApp;
import com.ecep.contract.manager.ds.company.CompanyFileUtils;
import com.ecep.contract.manager.ds.company.model.Company;
import com.ecep.contract.manager.ds.customer.CompanyCustomerFileType;
import com.ecep.contract.manager.ds.customer.model.CompanyCustomer;
import com.ecep.contract.manager.ds.customer.model.CompanyCustomerFile;
import com.ecep.contract.manager.ds.customer.model.CompanyCustomerFileTypeLocal;
import com.ecep.contract.manager.ds.customer.repository.CompanyCustomerFileTypeLocalRepository;
import com.ecep.contract.manager.ds.customer.service.CompanyCustomerFileService;
import com.ecep.contract.manager.ds.customer.service.CompanyCustomerService;
import com.ecep.contract.manager.ds.customer.vo.CompanyCustomerFileViewModel;
import com.ecep.contract.manager.ds.other.model.BaseEnumEntity;
import com.ecep.contract.manager.ui.table.EditableEntityTableTabSkin;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.ui.Message;
import com.ecep.contract.manager.util.DesktopUtils;
import com.ecep.contract.manager.util.MyDateTimeUtils;
import com.ecep.contract.manager.util.SpecificationUtils;
import com.ecep.contract.manager.util.UITools;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.collections.ObservableMap;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.scene.control.*;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;
import lombok.Setter;
import org.hibernate.Hibernate;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.util.StringUtils;
import java.io.File; import java.io.File;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.function.Consumer; import java.util.function.Consumer;
import org.springframework.util.StringUtils;
import com.ecep.contract.CustomerFileType;
import com.ecep.contract.DesktopUtils;
import com.ecep.contract.Message;
import com.ecep.contract.MyDateTimeUtils;
import com.ecep.contract.SpringApp;
import com.ecep.contract.constant.CompanyCustomerConstant;
import com.ecep.contract.controller.table.EditableEntityTableTabSkin;
import com.ecep.contract.model.BaseEnumEntity;
import com.ecep.contract.service.CompanyCustomerEvaluationFormFileService;
import com.ecep.contract.service.CompanyCustomerFileService;
import com.ecep.contract.service.CompanyCustomerFileTypeService;
import com.ecep.contract.service.CompanyCustomerService;
import com.ecep.contract.util.FileUtils;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.ParamUtils;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.CompanyCustomerFileViewModel;
import com.ecep.contract.vo.CompanyCustomerEvaluationFormFileVo;
import com.ecep.contract.vo.CompanyCustomerFileVo;
import com.ecep.contract.vo.CompanyCustomerVo;
import com.ecep.contract.vo.CompanyVo;
import com.ecep.contract.vo.CustomerFileTypeLocalVo;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.collections.FXCollections;
import javafx.collections.ObservableMap;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.MenuItem;
import javafx.scene.control.Tab;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;
import lombok.Setter;
@FxmlPath("/ui/company/customer/customer-tab-file.fxml") @FxmlPath("/ui/company/customer/customer-tab-file.fxml")
public class CustomerTabSkinFile public class CustomerTabSkinFile
extends AbstCompanyCustomerTableTabSkin<CompanyCustomerFile, CompanyCustomerFileViewModel> extends AbstCompanyCustomerTableTabSkin<CompanyCustomerFileVo, CompanyCustomerFileViewModel>
implements EditableEntityTableTabSkin<CompanyCustomerFile, CompanyCustomerFileViewModel> { implements EditableEntityTableTabSkin<CompanyCustomerFileVo, CompanyCustomerFileViewModel> {
@Setter @Setter
private CompanyCustomerFileService companyCustomerFileService; private CompanyCustomerFileService companyCustomerFileService;
public TableColumn<CompanyCustomerFileViewModel, Number> fileTable_idColumn; public TableColumn<CompanyCustomerFileViewModel, Number> fileTable_idColumn;
public TableColumn<CompanyCustomerFileViewModel, String> fileTable_typeColumn; public TableColumn<CompanyCustomerFileViewModel, String> fileTable_typeColumn;
public TableColumn<CompanyCustomerFileViewModel, String> fileTable_filePathColumn; public TableColumn<CompanyCustomerFileViewModel, String> fileTable_filePathColumn;
@@ -83,10 +91,10 @@ public class CustomerTabSkinFile
} }
@Override @Override
public Specification<CompanyCustomerFile> getSpecification(CompanyCustomer parent) { public ParamUtils.Builder getSpecification(CompanyCustomerVo parent) {
return SpecificationUtils.and(getSpecification(), (root, query, builder) -> { ParamUtils.Builder params = getSpecification();
return builder.equal(root.get("customer"), parent); params.equals("customer", parent.getId());
}); return params;
} }
@Override @Override
@@ -97,8 +105,9 @@ public class CustomerTabSkinFile
table.disableProperty().bind(viewModel.getPath().isEmpty()); table.disableProperty().bind(viewModel.getPath().isEmpty());
fileTable_idColumn.setCellValueFactory(param -> param.getValue().getId()); fileTable_idColumn.setCellValueFactory(param -> param.getValue().getId());
CompanyCustomerFileTypeService fileTypeService = getCachedBean(CompanyCustomerFileTypeService.class);
ObservableMap<CompanyCustomerFileType, CompanyCustomerFileTypeLocal> observableMapByLocal = SpringApp.getBean(CompanyCustomerFileTypeLocalRepository.class).getObservableMapByLocal(); ObservableMap<CustomerFileType, CustomerFileTypeLocalVo> observableMapByLocal = FXCollections
.observableMap(fileTypeService.findAll(getLocale()));
fileTable_typeColumn.setCellValueFactory(param -> Bindings.valueAt(observableMapByLocal, fileTable_typeColumn.setCellValueFactory(param -> Bindings.valueAt(observableMapByLocal,
param.getValue().getType()).map(BaseEnumEntity::getValue)); param.getValue().getType()).map(BaseEnumEntity::getValue));
@@ -147,11 +156,15 @@ public class CustomerTabSkinFile
@Override @Override
protected void onTableRowDoubleClickedAction(CompanyCustomerFileViewModel item) { protected void onTableRowDoubleClickedAction(CompanyCustomerFileViewModel item) {
CompanyCustomerFileType fileType = item.getType().get(); CustomerFileType fileType = item.getType().get();
if (fileType == CompanyCustomerFileType.EvaluationForm) { if (fileType == CustomerFileType.EvaluationForm) {
CompanyCustomerEvaluationFormFileVo evaluationFormFile = getCachedBean(
CompanyCustomerEvaluationFormFileService.class).findByCustomerFile(item.getId().get());
// 文件不是 Excel 文件时打开编辑UI // 文件不是 Excel 文件时打开编辑UI
if (!CompanyFileUtils.withExtensions(item.getFilePath().get(), CompanyFileUtils.XLS, CompanyFileUtils.XLSX)) { if (!FileUtils.withExtensions(item.getFilePath().get(), FileUtils.XLS,
CompanyCustomerEvaluationFormFileWindowController.show(item, controller.root.getScene().getWindow()); FileUtils.XLSX)) {
CompanyCustomerEvaluationFormFileWindowController.show(evaluationFormFile,
controller.root.getScene().getWindow());
return; return;
} }
} }
@@ -174,28 +187,35 @@ public class CustomerTabSkinFile
setStatus("目录错误,不存在"); setStatus("目录错误,不存在");
return; return;
} }
CompanyCustomer companyCustomer = getParent(); CompanyCustomerVo companyCustomer = getParent();
LocalDate nextSignDate = getCompanyCustomerFileService().getNextSignDate(companyCustomer, this::setStatus); LocalDate nextSignDate = getCompanyCustomerFileService().getNextSignDate(companyCustomer,
((level, message) -> setStatus(message)));
if (nextSignDate != null && files.size() == 1) { if (nextSignDate != null && files.size() == 1) {
File file = files.getFirst(); File file = files.getFirst();
String fileName = file.getName(); String fileName = file.getName();
if (fileName.startsWith("S")) { if (fileName.startsWith("S")) {
String destFileName = CompanyCustomerService.EVALUATION_FORM_NAME2 + "_" + MyDateTimeUtils.format(nextSignDate) String destFileName = CompanyCustomerConstant.EVALUATION_FORM_NAME2 + "_"
+ MyDateTimeUtils.format(nextSignDate)
+ "." + StringUtils.getFilenameExtension(fileName); + "." + StringUtils.getFilenameExtension(fileName);
File dest = new File(dir, destFileName); File dest = new File(dir, destFileName);
if (file.renameTo(dest)) { if (file.renameTo(dest)) {
CompanyCustomerFile ccf = new CompanyCustomerFile(); CompanyCustomerFileVo ccf = new CompanyCustomerFileVo();
ccf.setCustomer(companyCustomer); ccf.setCustomer(companyCustomer.getId());
ccf.setType(CompanyCustomerFileType.EvaluationForm); ccf.setType(CustomerFileType.EvaluationForm);
ccf.setFilePath(dest.getAbsolutePath()); ccf.setFilePath(dest.getAbsolutePath());
ccf.setSignDate(nextSignDate); ccf.setSignDate(nextSignDate);
ccf.setValid(false); ccf.setValid(false);
CompanyCustomerFile saved = getCompanyCustomerFileService().save(ccf); CompanyCustomerFileVo saved = getCompanyCustomerFileService().save(ccf);
Platform.runLater(() -> { Platform.runLater(() -> {
CompanyCustomerFileViewModel model = new CompanyCustomerFileViewModel(); CompanyCustomerFileViewModel model = new CompanyCustomerFileViewModel();
model.update(saved); model.update(saved);
dataSet.add(model); dataSet.add(model);
CompanyCustomerEvaluationFormFileWindowController.show(model, getTableView().getScene().getWindow());
CompanyCustomerEvaluationFormFileVo evaluationFormFile = getCachedBean(
CompanyCustomerEvaluationFormFileService.class).findByCustomerFile(saved);
CompanyCustomerEvaluationFormFileWindowController.show(evaluationFormFile,
getTableView().getScene().getWindow());
}); });
return; return;
} }
@@ -203,21 +223,17 @@ public class CustomerTabSkinFile
} }
List<CompanyCustomerFile> companyCustomerFiles = new ArrayList<>();
for (File file : files) { for (File file : files) {
File dest = new File(dir, file.getName()); File dest = new File(dir, file.getName());
if (file.renameTo(dest)) { if (file.renameTo(dest)) {
CompanyCustomerFile ccf = new CompanyCustomerFile(); CompanyCustomerFileVo ccf = new CompanyCustomerFileVo();
ccf.setCustomer(companyCustomer); ccf.setCustomer(companyCustomer.getId());
ccf.setType(CompanyCustomerFileType.General); ccf.setType(CustomerFileType.General);
ccf.setFilePath(dest.getAbsolutePath()); ccf.setFilePath(dest.getAbsolutePath());
ccf.setValid(false); ccf.setValid(false);
companyCustomerFiles.add(ccf); getCompanyCustomerFileService().save(ccf);
} }
} }
getCompanyCustomerFileService().saveAll(companyCustomerFiles);
loadTableDataSet(); loadTableDataSet();
} }
@@ -225,8 +241,8 @@ public class CustomerTabSkinFile
CompletableFuture.runAsync(() -> { CompletableFuture.runAsync(() -> {
CompanyCustomerService customerService = getCompanyCustomerService(); CompanyCustomerService customerService = getCompanyCustomerService();
try { try {
CompanyCustomer companyCustomer = customerService.findById(viewModel.getId().get()); CompanyCustomerVo companyCustomer = customerService.findById(viewModel.getId().get());
if (customerService.reBuildingFiles(companyCustomer, this::setStatus)) { if (customerService.reBuildingFiles(companyCustomer, (level, message) -> setStatus(message))) {
loadTableDataSet(); loadTableDataSet();
} }
} catch (Exception e) { } catch (Exception e) {
@@ -236,17 +252,17 @@ public class CustomerTabSkinFile
} }
@Override @Override
public CompanyCustomerFile loadRowData(CompanyCustomerFileViewModel row) { public CompanyCustomerFileVo loadRowData(CompanyCustomerFileViewModel row) {
return getCompanyCustomerFileService().findById(row.getId().get()); return getCompanyCustomerFileService().findById(row.getId().get());
} }
@Override @Override
public CompanyCustomerFile saveRowData(CompanyCustomerFile entity) { public CompanyCustomerFileVo saveRowData(CompanyCustomerFileVo entity) {
return getCompanyCustomerFileService().save(entity); return getCompanyCustomerFileService().save(entity);
} }
@Override @Override
public void deleteRowData(CompanyCustomerFile entity) { public void deleteRowData(CompanyCustomerFileVo entity) {
getCompanyCustomerFileService().delete(entity); getCompanyCustomerFileService().delete(entity);
} }
@@ -270,13 +286,9 @@ public class CustomerTabSkinFile
return false; return false;
} }
public void onFileTableMoveToCompanyPathAction(ActionEvent event) { public void onFileTableMoveToCompanyPathAction(ActionEvent event) {
Company company = viewModel.getCompany().get(); Integer companyId = viewModel.getCompany().get();
if (!Hibernate.isInitialized(company)) { CompanyVo company = getCompanyService().findById(companyId);
company = getCompanyService().findById(company.getId());
viewModel.getCompany().set(company);
}
if (!StringUtils.hasText(company.getPath())) { if (!StringUtils.hasText(company.getPath())) {
setStatus("公司目录未设置"); setStatus("公司目录未设置");
@@ -322,7 +334,6 @@ public class CustomerTabSkinFile
// dataSet.remove(selectedItem); // dataSet.remove(selectedItem);
} }
private void initializeTask(Task<Object> task, String prefix, Consumer<String> consumer) { private void initializeTask(Task<Object> task, String prefix, Consumer<String> consumer) {
task.setOnScheduled(e -> { task.setOnScheduled(e -> {
consumer.accept("正在" + prefix + ",请稍后..."); consumer.accept("正在" + prefix + ",请稍后...");
@@ -351,11 +362,10 @@ public class CustomerTabSkinFile
loadTableDataSet(); loadTableDataSet();
} }
public void onCalcNextSignDateAction(ActionEvent event) { public void onCalcNextSignDateAction(ActionEvent event) {
UITools.showDialogAndWait("计算客户下一个评价日期", "依据已有的客户评估表和登记采购的合同计算下一个评估日期", ds -> { UITools.showDialogAndWait("计算客户下一个评价日期", "依据已有的客户评估表和登记采购的合同计算下一个评估日期", ds -> {
CompanyCustomer companyCustomer = getCompanyCustomerService().findById(viewModel.getId().get()); CompanyCustomerVo companyCustomer = getCompanyCustomerService().findById(viewModel.getId().get());
LocalDate nextSignDate = getCompanyCustomerFileService().getNextSignDate(companyCustomer, msg -> { LocalDate nextSignDate = getCompanyCustomerFileService().getNextSignDate(companyCustomer, (level, msg) -> {
Platform.runLater(() -> { Platform.runLater(() -> {
ds.add(msg); ds.add(msg);
}); });
@@ -368,7 +378,6 @@ public class CustomerTabSkinFile
}); });
} }
class FileTableFilePathTableCell extends TableCell<CompanyCustomerFileViewModel, String> { class FileTableFilePathTableCell extends TableCell<CompanyCustomerFileViewModel, String> {
@Override @Override
protected void updateItem(String item, boolean empty) { protected void updateItem(String item, boolean empty) {
@@ -388,7 +397,6 @@ public class CustomerTabSkinFile
} }
} }
private CompanyCustomerFileService getCompanyCustomerFileService() { private CompanyCustomerFileService getCompanyCustomerFileService() {
if (companyCustomerFileService == null) { if (companyCustomerFileService == null) {
companyCustomerFileService = SpringApp.getBean(CompanyCustomerFileService.class); companyCustomerFileService = SpringApp.getBean(CompanyCustomerFileService.class);

View File

@@ -1,40 +1,41 @@
package com.ecep.contract.manager.ds.customer.controller; package com.ecep.contract.controller.customer;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Map;
import com.ecep.contract.service.CustomerCatalogService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.controller.project.satisfaction_survey.CustomerSatisfactionSurveyWindowController;
import com.ecep.contract.controller.table.cell.EmployeeTableCell;
import com.ecep.contract.controller.table.cell.ProjectTableCell;
import com.ecep.contract.converter.EntityStringConverter;
import com.ecep.contract.vo.CompanyCustomerVo;
import com.ecep.contract.vo.CustomerCatalogVo;
import com.ecep.contract.vo.CustomerSatisfactionSurveyVo;
import com.ecep.contract.vo.EmployeeVo;
import com.ecep.contract.vo.ProjectVo;
import com.ecep.contract.service.CustomerSatisfactionSurveyService;
import com.ecep.contract.service.ProjectService;
import com.ecep.contract.util.ParamUtils;
import com.ecep.contract.vm.CustomerEntityViewModel;
import com.ecep.contract.vm.CustomerSatisfactionSurveyViewModel;
import com.ecep.contract.manager.ds.company.model.Company;
import com.ecep.contract.manager.ds.customer.model.CompanyCustomer;
import com.ecep.contract.manager.ds.customer.model.CustomerCatalog;
import com.ecep.contract.manager.ds.customer.vo.CustomerEntityViewModel;
import com.ecep.contract.manager.ds.other.EntityStringConverter;
import com.ecep.contract.manager.ds.project.service.ProjectService;
import com.ecep.contract.manager.ui.table.cell.EmployeeTableCell;
import com.ecep.contract.manager.ds.other.model.Employee;
import com.ecep.contract.manager.ds.project.controller.satisfaction_survey.CustomerSatisfactionSurveyWindowController;
import com.ecep.contract.manager.ds.project.model.CustomerSatisfactionSurvey;
import com.ecep.contract.manager.ds.project.model.Project;
import com.ecep.contract.manager.ds.project.service.CustomerSatisfactionSurveyService;
import com.ecep.contract.manager.ds.project.vo.CustomerSatisfactionSurveyViewModel;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.ui.table.cell.ProjectTableCell;
import com.ecep.contract.manager.util.SpecificationUtils;
import javafx.scene.control.MenuItem; import javafx.scene.control.MenuItem;
import javafx.scene.control.Tab; import javafx.scene.control.Tab;
import javafx.scene.control.TableColumn; import javafx.scene.control.TableColumn;
import lombok.Setter; import lombok.Setter;
import org.springframework.data.jpa.domain.Specification;
import java.time.LocalDate;
import java.time.LocalDateTime;
@FxmlPath("/ui/company/customer/customer-tab-satisfaction-survey.fxml") @FxmlPath("/ui/company/customer/customer-tab-satisfaction-survey.fxml")
public class CustomerTabSkinSatisfactionSurvey public class CustomerTabSkinSatisfactionSurvey
extends AbstCompanyCustomerTableTabSkin<CustomerSatisfactionSurvey, CustomerSatisfactionSurveyViewModel> { extends AbstCompanyCustomerTableTabSkin<CustomerSatisfactionSurveyVo, CustomerSatisfactionSurveyViewModel> {
// 关联项 tab // 关联项 tab
public TableColumn<CustomerSatisfactionSurveyViewModel, Number> idColumn; public TableColumn<CustomerSatisfactionSurveyViewModel, Number> idColumn;
public TableColumn<CustomerSatisfactionSurveyViewModel, Project> projectColumn; public TableColumn<CustomerSatisfactionSurveyViewModel, Integer> projectColumn;
public TableColumn<CustomerSatisfactionSurveyViewModel, String> codeColumn; public TableColumn<CustomerSatisfactionSurveyViewModel, String> codeColumn;
public TableColumn<CustomerSatisfactionSurveyViewModel, Number> totalScoreColumn; public TableColumn<CustomerSatisfactionSurveyViewModel, Number> totalScoreColumn;
public TableColumn<CustomerSatisfactionSurveyViewModel, Employee> applicantColumn; public TableColumn<CustomerSatisfactionSurveyViewModel, Integer> applicantColumn;
public TableColumn<CustomerSatisfactionSurveyViewModel, LocalDateTime> applyTimeColumn; public TableColumn<CustomerSatisfactionSurveyViewModel, LocalDateTime> applyTimeColumn;
public TableColumn<CustomerSatisfactionSurveyViewModel, String> descriptionColumn; public TableColumn<CustomerSatisfactionSurveyViewModel, String> descriptionColumn;
public TableColumn<CustomerSatisfactionSurveyViewModel, LocalDate> dateColumn; public TableColumn<CustomerSatisfactionSurveyViewModel, LocalDate> dateColumn;
@@ -55,15 +56,15 @@ private ProjectService projectService;
return controller.satisfactionTab; return controller.satisfactionTab;
} }
@Override @Override
public void initializeTab() { public void initializeTab() {
super.initializeTab(); super.initializeTab();
bindNumberColumn(idColumn, CustomerSatisfactionSurveyViewModel::getId); bindNumberColumn(idColumn, CustomerSatisfactionSurveyViewModel::getId);
bindColumn(codeColumn, CustomerSatisfactionSurveyViewModel::getCode); bindColumn(codeColumn, CustomerSatisfactionSurveyViewModel::getCode);
projectColumn.setCellValueFactory(param -> param.getValue().getProject()); projectColumn.setCellValueFactory(param -> param.getValue().getProject());
projectColumn.setCellFactory(cell -> new ProjectTableCell<>(getProjectService())); projectColumn.setCellFactory(ProjectTableCell.forTableColumn(getProjectService()));
bindLocalDateColumn(dateColumn, CustomerSatisfactionSurveyViewModel::getDate); bindLocalDateColumn(dateColumn, CustomerSatisfactionSurveyViewModel::getDate);
bindNumberColumn(totalScoreColumn, CustomerSatisfactionSurveyViewModel::getTotalScore); bindNumberColumn(totalScoreColumn, CustomerSatisfactionSurveyViewModel::getTotalScore);
applicantColumn.setCellValueFactory(param -> param.getValue().getApplicant()); applicantColumn.setCellValueFactory(param -> param.getValue().getApplicant());
@@ -75,13 +76,6 @@ private ProjectService projectService;
entityTable_menu_del.setOnAction(this::onTableDeleteAction); entityTable_menu_del.setOnAction(this::onTableDeleteAction);
} }
private void initializeEntityTabCatalogColumn(TableColumn<CustomerEntityViewModel, String> column) {
EntityStringConverter<CustomerCatalog> converter = new EntityStringConverter<>();
converter.setInitialized(v -> getCompanyCustomerService().findCatalogById(v.getId()));
column.setCellValueFactory(param -> param.getValue().getCatalog().map(converter::toString));
}
private CustomerSatisfactionSurveyService getCustomerSatisfactionSurveyService() { private CustomerSatisfactionSurveyService getCustomerSatisfactionSurveyService() {
if (satisfactionSurveyService == null) { if (satisfactionSurveyService == null) {
satisfactionSurveyService = getBean(CustomerSatisfactionSurveyService.class); satisfactionSurveyService = getBean(CustomerSatisfactionSurveyService.class);
@@ -102,14 +96,10 @@ private ProjectService projectService;
} }
@Override @Override
public Specification<CustomerSatisfactionSurvey> getSpecification(CompanyCustomer parent) { public ParamUtils.Builder getSpecification(CompanyCustomerVo parent) {
return SpecificationUtils.and(getSpecification(), (root, query, builder) -> { ParamUtils.Builder params = getSpecification();
Company company = parent.getCompany(); params.equals("project.customer", parent.getId());
if (company == null) { return params;
return null;
}
return builder.equal(root.get("project").get("customer"), company);
});
} }
@Override @Override

View File

@@ -1,25 +1,33 @@
package com.ecep.contract.manager.ds.contract.controller.sale_order; package com.ecep.contract.controller.customer;
import com.ecep.contract.manager.ds.contract.model.SalesOrder; import com.ecep.contract.vo.SalesOrderVo;
import com.ecep.contract.manager.ds.contract.service.SaleOrdersService;
import com.ecep.contract.manager.ds.contract.vo.SalesOrderViewModel;
import com.ecep.contract.manager.ui.AbstEntityController;
import com.ecep.contract.manager.ui.FxmlPath;
import javafx.scene.control.*;
import javafx.stage.Stage;
import javafx.stage.Window;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.ecep.contract.controller.AbstEntityController;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.controller.tab.SalesOrderTabSkinBase;
import com.ecep.contract.controller.tab.SalesOrderTabSkinBillVoucher;
import com.ecep.contract.controller.tab.SalesOrderTabSkinItems;
import com.ecep.contract.service.SaleOrdersService;
import com.ecep.contract.vm.SalesOrderViewModel;
import javafx.scene.control.Button;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
import javafx.stage.Window;
@Lazy @Lazy
@Scope("prototype") @Scope("prototype")
@Component @Component
@FxmlPath("/ui/contract/sale-orders.fxml") @FxmlPath("/ui/contract/sale-orders.fxml")
public class SalesOrderWindowController extends AbstEntityController<SalesOrder, SalesOrderViewModel> { public class SalesOrderWindowController extends AbstEntityController<SalesOrderVo, SalesOrderViewModel> {
private static final Logger logger = LoggerFactory.getLogger(SalesOrderWindowController.class); private static final Logger logger = LoggerFactory.getLogger(SalesOrderWindowController.class);
public TabPane tabPane; public TabPane tabPane;
public Button saveBtn; public Button saveBtn;
@@ -41,19 +49,6 @@ public class SalesOrderWindowController extends AbstEntityController<SalesOrder,
show(SalesOrderWindowController.class, viewModel, window); show(SalesOrderWindowController.class, viewModel, window);
} }
@Autowired
private SaleOrdersService service;
@Override
protected SalesOrder loadEntity() {
return service.findById(viewModel.getId().get());
}
@Override
protected SalesOrder saveEntity(SalesOrder entity) {
return service.save(entity);
}
@Override @Override
public void show(Stage stage) { public void show(Stage stage) {
super.show(stage); super.show(stage);
@@ -69,6 +64,6 @@ public class SalesOrderWindowController extends AbstEntityController<SalesOrder,
@Override @Override
public SaleOrdersService getViewModelService() { public SaleOrdersService getViewModelService() {
return service; return getCachedBean(SaleOrdersService.class);
} }
} }

View File

@@ -1,27 +1,30 @@
package com.ecep.contract.manager.ds.other.controller.department; package com.ecep.contract.controller.department;
import java.util.List;
import org.springframework.data.domain.Pageable;
import com.ecep.contract.controller.AbstEntityManagerSkin;
import com.ecep.contract.controller.ManagerSkin;
import com.ecep.contract.controller.table.EditableEntityTableTabSkin;
import com.ecep.contract.controller.table.cell.EmployeeTableCell;
import com.ecep.contract.converter.EmployeeStringConverter;
import com.ecep.contract.model.Employee;
import com.ecep.contract.util.ParamUtils;
import com.ecep.contract.vo.DepartmentVo;
import com.ecep.contract.vm.DepartmentViewModel;
import com.ecep.contract.manager.ds.other.EmployeeStringConverter;
import com.ecep.contract.manager.ds.other.model.Department;
import com.ecep.contract.manager.ds.other.model.Employee;
import com.ecep.contract.manager.ds.other.vo.DepartmentViewModel;
import com.ecep.contract.manager.ui.AbstEntityManagerSkin;
import com.ecep.contract.manager.ui.table.EditableEntityTableTabSkin;
import com.ecep.contract.manager.ui.ManagerSkin;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.scene.control.TableColumn; import javafx.scene.control.TableColumn;
import javafx.scene.control.cell.CheckBoxTableCell; import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.control.cell.ComboBoxTableCell; import javafx.scene.control.cell.ComboBoxTableCell;
import javafx.scene.control.cell.TextFieldTableCell; import javafx.scene.control.cell.TextFieldTableCell;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import java.util.List;
public class DepartmentManagerSkin public class DepartmentManagerSkin
extends AbstEntityManagerSkin<Department, DepartmentViewModel, DepartmentManagerSkin, DepartmentManagerWindowController> extends
implements ManagerSkin, EditableEntityTableTabSkin<Department, DepartmentViewModel> { AbstEntityManagerSkin<DepartmentVo, DepartmentViewModel, DepartmentManagerSkin, DepartmentManagerWindowController>
implements ManagerSkin, EditableEntityTableTabSkin<DepartmentVo, DepartmentViewModel> {
public DepartmentManagerSkin(DepartmentManagerWindowController controller) { public DepartmentManagerSkin(DepartmentManagerWindowController controller) {
super(controller); super(controller);
@@ -31,10 +34,7 @@ public class DepartmentManagerSkin
public void initializeTable() { public void initializeTable() {
getTableView().setEditable(true); getTableView().setEditable(true);
Specification<Employee> spec = (root, query, cb) -> { // 不再需要获取所有员工列表因为现在使用的是leaderId和leaderName
return cb.equal(root.get("isActive"), true);
};
List<Employee> employees = controller.getEmployeeService().findAll(spec, Pageable.ofSize(30)).getContent();
controller.idColumn.setCellValueFactory(param -> param.getValue().getId()); controller.idColumn.setCellValueFactory(param -> param.getValue().getId());
@@ -47,8 +47,7 @@ public class DepartmentManagerSkin
controller.codeColumn.setOnEditCommit(this::onCodeColumnEditCommit); controller.codeColumn.setOnEditCommit(this::onCodeColumnEditCommit);
controller.leaderColumn.setCellValueFactory(param -> param.getValue().getLeader()); controller.leaderColumn.setCellValueFactory(param -> param.getValue().getLeader());
controller.leaderColumn.setCellFactory(ComboBoxTableCell.forTableColumn(getBean(EmployeeStringConverter.class), FXCollections.observableArrayList(employees))); controller.leaderColumn.setCellFactory(param -> new EmployeeTableCell<>(controller.getEmployeeService()));
controller.leaderColumn.setOnEditCommit(this::onLeaderColumnEditCommit);
controller.activeColumn.setCellValueFactory(param -> param.getValue().getIsActive()); controller.activeColumn.setCellValueFactory(param -> param.getValue().getIsActive());
controller.activeColumn.setEditable(true); controller.activeColumn.setEditable(true);
@@ -56,7 +55,6 @@ public class DepartmentManagerSkin
controller.activeColumn.setOnEditCommit(this::onActiveColumnEditCommit); controller.activeColumn.setOnEditCommit(this::onActiveColumnEditCommit);
} }
private void onCodeColumnEditCommit(TableColumn.CellEditEvent<DepartmentViewModel, String> event) { private void onCodeColumnEditCommit(TableColumn.CellEditEvent<DepartmentViewModel, String> event) {
DepartmentViewModel row = event.getRowValue(); DepartmentViewModel row = event.getRowValue();
row.getCode().set(event.getNewValue()); row.getCode().set(event.getNewValue());
@@ -69,9 +67,11 @@ public class DepartmentManagerSkin
saveRowData(row); saveRowData(row);
} }
private void onLeaderColumnEditCommit(TableColumn.CellEditEvent<DepartmentViewModel, Employee> event) { private void onLeaderColumnEditCommit(TableColumn.CellEditEvent<DepartmentViewModel, Integer> event) {
DepartmentViewModel row = event.getRowValue(); DepartmentViewModel row = event.getRowValue();
row.getLeader().set(event.getNewValue()); row.getLeader().set(event.getNewValue());
// 注意这里我们只设置了leaderName但没有设置leaderId
// 在实际应用中您可能需要根据leaderName查找对应的leaderId
saveRowData(row); saveRowData(row);
} }
@@ -88,9 +88,9 @@ public class DepartmentManagerSkin
@Override @Override
protected void onTableCreateNewAction(ActionEvent event) { protected void onTableCreateNewAction(ActionEvent event) {
Department employee = new Department(); DepartmentVo department = new DepartmentVo();
employee = controller.getViewModelService().save(employee); department = controller.getViewModelService().save(department);
DepartmentViewModel viewModel = DepartmentViewModel.from(employee); DepartmentViewModel viewModel = DepartmentViewModel.from(department);
dataSet.add(viewModel); dataSet.add(viewModel);
} }
} }

View File

@@ -1,31 +1,31 @@
package com.ecep.contract.manager.ds.other.controller.department; package com.ecep.contract.controller.department;
import com.ecep.contract.manager.ds.other.model.Department;
import com.ecep.contract.manager.ds.other.model.Employee;
import com.ecep.contract.manager.ds.other.service.DepartmentService;
import com.ecep.contract.manager.ds.other.vo.DepartmentViewModel;
import com.ecep.contract.manager.ui.AbstManagerWindowController;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.ui.ViewModelService;
import javafx.event.ActionEvent;
import javafx.scene.control.TableColumn;
import javafx.stage.Stage;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.ecep.contract.controller.AbstManagerWindowController;
import com.ecep.contract.service.DepartmentService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.vm.DepartmentViewModel;
import com.ecep.contract.vo.DepartmentVo;
import javafx.event.ActionEvent;
import javafx.scene.control.TableColumn;
import javafx.stage.Stage;
@Lazy @Lazy
@Scope("prototype") @Scope("prototype")
@Component @Component
@FxmlPath(value = "/ui/employee/department-manager.fxml") @FxmlPath(value = "/ui/employee/department-manager.fxml")
public class DepartmentManagerWindowController public class DepartmentManagerWindowController
extends AbstManagerWindowController<Department, DepartmentViewModel, DepartmentManagerSkin> { extends AbstManagerWindowController<DepartmentVo, DepartmentViewModel, DepartmentManagerSkin> {
public TableColumn<DepartmentViewModel, Number> idColumn; public TableColumn<DepartmentViewModel, Number> idColumn;
public TableColumn<DepartmentViewModel, String> nameColumn; public TableColumn<DepartmentViewModel, String> nameColumn;
public TableColumn<DepartmentViewModel, String> codeColumn; public TableColumn<DepartmentViewModel, String> codeColumn;
public TableColumn<DepartmentViewModel, Employee> leaderColumn; public TableColumn<DepartmentViewModel, Integer> leaderColumn;
public TableColumn<DepartmentViewModel, Boolean> activeColumn; public TableColumn<DepartmentViewModel, Boolean> activeColumn;
@Autowired @Autowired

View File

@@ -1,16 +1,18 @@
package com.ecep.contract.manager.ds.other.controller.employee; package com.ecep.contract.controller.employee;
import com.ecep.contract.manager.ds.other.model.Employee; import com.ecep.contract.controller.tab.AbstEntityBasedTabSkin;
import com.ecep.contract.manager.ds.other.service.EmployeeRoleService; import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.manager.ds.other.service.EmployeeService; import com.ecep.contract.model.Employee;
import com.ecep.contract.manager.ds.other.service.PermissionService; import com.ecep.contract.service.EmployeeRoleService;
import com.ecep.contract.manager.ds.other.vo.EmployeeViewModel; import com.ecep.contract.service.EmployeeService;
import com.ecep.contract.manager.ui.tab.AbstEntityBasedTabSkin; import com.ecep.contract.service.PermissionService;
import com.ecep.contract.manager.ui.tab.TabSkin; import com.ecep.contract.vm.EmployeeViewModel;
import com.ecep.contract.vo.EmployeeVo;
import lombok.Setter; import lombok.Setter;
public abstract class AbstEmployeeBasedTabSkin public abstract class AbstEmployeeBasedTabSkin
extends AbstEntityBasedTabSkin<EmployeeWindowController, Employee, EmployeeViewModel> extends AbstEntityBasedTabSkin<EmployeeWindowController, EmployeeVo, EmployeeViewModel>
implements TabSkin { implements TabSkin {
@Setter @Setter
private PermissionService permissionService; private PermissionService permissionService;

View File

@@ -0,0 +1,44 @@
package com.ecep.contract.controller.employee;
import java.util.Map;
import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.controller.table.AbstEntityTableTabSkin;
import com.ecep.contract.model.Employee;
import com.ecep.contract.model.IdentityEntity;
import com.ecep.contract.service.EmployeeService;
import com.ecep.contract.util.ParamUtils;
import com.ecep.contract.vm.EmployeeBasedViewModel;
import com.ecep.contract.vm.EmployeeViewModel;
import com.ecep.contract.vm.IdentityViewModel;
import com.ecep.contract.vo.EmployeeVo;
public abstract class AbstEmployeeTableTabSkin<T extends IdentityEntity, TV extends IdentityViewModel<T>>
extends AbstEntityTableTabSkin<EmployeeWindowController, EmployeeVo, EmployeeViewModel, T, TV>
implements TabSkin {
public AbstEmployeeTableTabSkin(EmployeeWindowController controller) {
super(controller);
}
public EmployeeService getEmployeeService() {
return controller.employeeService;
}
@Override
protected TV createNewViewModel() {
TV model = super.createNewViewModel();
if (model instanceof EmployeeBasedViewModel m) {
m.getEmployee().set(getEntity().getId());
}
return model;
}
@Override
public ParamUtils.Builder getSpecification(EmployeeVo parent) {
ParamUtils.Builder params = getSpecification();
params.equals("employee", parent.getId());
return params;
}
}

View File

@@ -1,20 +1,20 @@
package com.ecep.contract.manager.ds.other.controller.employee; package com.ecep.contract.controller.employee;
import com.ecep.contract.controller.AbstEntityManagerSkin;
import com.ecep.contract.controller.ManagerSkin;
import com.ecep.contract.controller.table.cell.DepartmentTableCell;
import com.ecep.contract.model.Employee;
import com.ecep.contract.service.DepartmentService;
import com.ecep.contract.util.ParamUtils;
import com.ecep.contract.vm.EmployeeViewModel;
import com.ecep.contract.vo.EmployeeVo;
import com.ecep.contract.manager.ds.other.EntityStringConverter;
import com.ecep.contract.manager.ds.other.model.Department;
import com.ecep.contract.manager.ds.other.model.Employee;
import com.ecep.contract.manager.ds.other.service.DepartmentService;
import com.ecep.contract.manager.ds.other.vo.EmployeeViewModel;
import com.ecep.contract.manager.ui.AbstEntityManagerSkin;
import com.ecep.contract.manager.ui.ManagerSkin;
import com.ecep.contract.manager.ui.table.cell.DepartmentTableCell;
import com.ecep.contract.manager.util.SpecificationUtils;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.scene.control.cell.CheckBoxTableCell; import javafx.scene.control.cell.CheckBoxTableCell;
import org.springframework.data.jpa.domain.Specification;
public class EmployeeManagerSkin public class EmployeeManagerSkin
extends AbstEntityManagerSkin<Employee, EmployeeViewModel, EmployeeManagerSkin, EmployeeManagerWindowController> extends
AbstEntityManagerSkin<EmployeeVo, EmployeeViewModel, EmployeeManagerSkin, EmployeeManagerWindowController>
implements ManagerSkin { implements ManagerSkin {
public EmployeeManagerSkin(EmployeeManagerWindowController controller) { public EmployeeManagerSkin(EmployeeManagerWindowController controller) {
super(controller); super(controller);
@@ -30,14 +30,12 @@ public class EmployeeManagerSkin
} }
@Override @Override
public Specification<Employee> getSpecification() { public ParamUtils.Builder getSpecification() {
Specification<Employee> spec = super.getSpecification(); ParamUtils.Builder params = super.getSpecification();
if (controller.activeCheckBox.isSelected()) { if (controller.activeCheckBox.isSelected()) {
spec = SpecificationUtils.and(spec, (root, query, builder) -> { params.equals("isActive", true);
return builder.isTrue(root.get("isActive"));
});
} }
return spec; return params;
} }
@Override @Override
@@ -51,7 +49,6 @@ public class EmployeeManagerSkin
controller.departmentColumn.setCellValueFactory(param -> param.getValue().getDepartment()); controller.departmentColumn.setCellValueFactory(param -> param.getValue().getDepartment());
controller.departmentColumn.setCellFactory(param -> new DepartmentTableCell<>(getDepartmentService())); controller.departmentColumn.setCellFactory(param -> new DepartmentTableCell<>(getDepartmentService()));
controller.emailColumn.setCellValueFactory(param -> param.getValue().getEmail()); controller.emailColumn.setCellValueFactory(param -> param.getValue().getEmail());
controller.createdColumn.setCellValueFactory(param -> param.getValue().getCreated()); controller.createdColumn.setCellValueFactory(param -> param.getValue().getCreated());
controller.entryDateColumn.setCellValueFactory(param -> param.getValue().getEntryDate()); controller.entryDateColumn.setCellValueFactory(param -> param.getValue().getEntryDate());
@@ -68,7 +65,7 @@ public class EmployeeManagerSkin
@Override @Override
protected void onTableCreateNewAction(ActionEvent event) { protected void onTableCreateNewAction(ActionEvent event) {
Employee employee = new Employee(); EmployeeVo employee = new EmployeeVo();
employee = controller.getViewModelService().save(employee); employee = controller.getViewModelService().save(employee);
EmployeeViewModel viewModel = EmployeeViewModel.from(employee); EmployeeViewModel viewModel = EmployeeViewModel.from(employee);
dataSet.add(viewModel); dataSet.add(viewModel);

View File

@@ -1,39 +1,40 @@
package com.ecep.contract.manager.ds.other.controller.employee; package com.ecep.contract.controller.employee;
import java.time.LocalDate;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import com.ecep.contract.constant.CloudServiceConstant;
import com.ecep.contract.controller.AbstManagerWindowController;
import com.ecep.contract.model.Department;
import com.ecep.contract.service.EmployeeService;
import com.ecep.contract.task.EmployeesSyncTask;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.EmployeeViewModel;
import com.ecep.contract.vo.EmployeeVo;
import com.ecep.contract.manager.cloud.u8.EmployeesSyncTask;
import com.ecep.contract.manager.cloud.u8.YongYouU8Service;
import com.ecep.contract.manager.ds.other.model.Department;
import com.ecep.contract.manager.ds.other.model.Employee;
import com.ecep.contract.manager.ds.other.service.EmployeeService;
import com.ecep.contract.manager.ds.other.vo.EmployeeViewModel;
import com.ecep.contract.manager.ui.AbstManagerWindowController;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.util.UITools;
import javafx.concurrent.Task;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.scene.control.CheckBox; import javafx.scene.control.CheckBox;
import javafx.scene.control.TableColumn; import javafx.scene.control.TableColumn;
import javafx.stage.Stage; import javafx.stage.Stage;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.time.LocalDate;
@Lazy @Lazy
@Scope("prototype") @Scope("prototype")
@Component @Component
@FxmlPath("/ui/employee/employee-manager.fxml") @FxmlPath("/ui/employee/employee-manager.fxml")
public class EmployeeManagerWindowController public class EmployeeManagerWindowController
extends AbstManagerWindowController<Employee, EmployeeViewModel, EmployeeManagerSkin> { extends AbstManagerWindowController<EmployeeVo, EmployeeViewModel, EmployeeManagerSkin> {
@FXML @FXML
public TableColumn<EmployeeViewModel, Number> idColumn; public TableColumn<EmployeeViewModel, Number> idColumn;
@FXML @FXML
public TableColumn<EmployeeViewModel, String> accountColumn; public TableColumn<EmployeeViewModel, String> accountColumn;
@FXML @FXML
public TableColumn<EmployeeViewModel, Department> departmentColumn; public TableColumn<EmployeeViewModel, Integer> departmentColumn;
@FXML @FXML
public TableColumn<EmployeeViewModel, String> nameColumn; public TableColumn<EmployeeViewModel, String> nameColumn;
@FXML @FXML
@@ -68,8 +69,8 @@ public class EmployeeManagerWindowController
* U8系统 同步员工数据 * U8系统 同步员工数据
*/ */
public void onSyncFromU8Action(ActionEvent event) { public void onSyncFromU8Action(ActionEvent event) {
Task<Object> task = new EmployeesSyncTask(); EmployeesSyncTask task = new EmployeesSyncTask();
UITools.showTaskDialogAndWait("" + YongYouU8Service.NAME + " 同步员工数据", task, null); UITools.showTaskDialogAndWait("" + CloudServiceConstant.U8_NAME + " 同步员工数据", task, null);
} }

View File

@@ -1,31 +1,32 @@
package com.ecep.contract.manager.ds.other.controller.employee; package com.ecep.contract.controller.employee;
import com.ecep.contract.manager.ds.other.model.Employee; import com.ecep.contract.Desktop;
import com.ecep.contract.manager.ds.other.model.EmployeeAuthBind; import com.ecep.contract.controller.table.cell.EmployeeTableCell;
import com.ecep.contract.manager.ds.other.service.EmployeeAuthBindService; import com.ecep.contract.model.Employee;
import com.ecep.contract.manager.ds.other.vo.EmployeeAuthBindViewModel; import com.ecep.contract.model.EmployeeAuthBind;
import com.ecep.contract.manager.ui.FxmlPath; import com.ecep.contract.service.EmployeeAuthBindService;
import com.ecep.contract.manager.ui.table.cell.EmployeeTableCell; import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.vm.EmployeeAuthBindViewModel;
import com.ecep.contract.vo.EmployeeAuthBindVo;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.scene.control.ContextMenu; import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem; import javafx.scene.control.MenuItem;
import javafx.scene.control.Tab; import javafx.scene.control.Tab;
import javafx.scene.control.TableColumn; import javafx.scene.control.TableColumn;
import lombok.Setter; import lombok.Setter;
import org.springframework.data.domain.Sort;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List; import java.util.List;
@FxmlPath("/ui/employee/employee-auth-bind.fxml") @FxmlPath("/ui/employee/employee-auth-bind.fxml")
public class EmployeeTabSkinAuthBind public class EmployeeTabSkinAuthBind
extends AbstEmployeeTableTabSkin<EmployeeAuthBind, EmployeeAuthBindViewModel> { extends AbstEmployeeTableTabSkin<EmployeeAuthBindVo, EmployeeAuthBindViewModel> {
public TableColumn<EmployeeAuthBindViewModel, Number> idColumn; public TableColumn<EmployeeAuthBindViewModel, Number> idColumn;
public TableColumn<EmployeeAuthBindViewModel, String> ipColumn; public TableColumn<EmployeeAuthBindViewModel, String> ipColumn;
public TableColumn<EmployeeAuthBindViewModel, String> macColumn; public TableColumn<EmployeeAuthBindViewModel, String> macColumn;
public TableColumn<EmployeeAuthBindViewModel, LocalDateTime> createTime; public TableColumn<EmployeeAuthBindViewModel, LocalDateTime> createTime;
public TableColumn<EmployeeAuthBindViewModel, LocalDateTime> updateTimeColumn; public TableColumn<EmployeeAuthBindViewModel, LocalDateTime> updateTimeColumn;
public TableColumn<EmployeeAuthBindViewModel, Employee> updaterColumn; public TableColumn<EmployeeAuthBindViewModel, Integer> updaterColumn;
public TableColumn<EmployeeAuthBindViewModel, String> descriptionColumn; public TableColumn<EmployeeAuthBindViewModel, String> descriptionColumn;
@Setter @Setter
@@ -79,13 +80,18 @@ public class EmployeeTabSkinAuthBind
protected void createContextMenu(ContextMenu contextMenu) { protected void createContextMenu(ContextMenu contextMenu) {
super.createContextMenu(contextMenu); super.createContextMenu(contextMenu);
MenuItem menuItem = new MenuItem("导入未关联"); MenuItem menuItem = new MenuItem("导入未关联");
int activeEmployeeId = Desktop.instance.getActiveEmployeeId();
if (activeEmployeeId <= 0) {
logger.warn("未登录员工{}", activeEmployeeId);
return;
}
menuItem.setOnAction(event -> { menuItem.setOnAction(event -> {
EmployeeAuthBindService service = getEmployeeAuthBindService(); EmployeeAuthBindService service = getEmployeeAuthBindService();
List<EmployeeAuthBind> authBinds = service.findAllByEmployee(null, Sort.unsorted()); List<EmployeeAuthBindVo> authBinds = service.findAllByEmployee(null);
for (EmployeeAuthBind authBind : authBinds) { for (EmployeeAuthBindVo authBind : authBinds) {
authBind.setEmployee(getEntity()); authBind.setEmployeeId(getEntity().getId());
authBind.setUpdateTime(LocalDateTime.now()); authBind.setUpdateTime(LocalDateTime.now());
authBind.setUpdater(controller.getCurrentUser()); authBind.setUpdaterId(activeEmployeeId);
service.save(authBind); service.save(authBind);
} }
}); });

View File

@@ -1,15 +1,14 @@
package com.ecep.contract.manager.ds.other.controller.employee; package com.ecep.contract.controller.employee;
import com.ecep.contract.manager.ds.other.EntityStringConverter;
import com.ecep.contract.manager.ds.other.model.Department;
import com.ecep.contract.manager.ds.other.service.DepartmentService;
import com.ecep.contract.manager.ui.tab.TabSkin;
import com.ecep.contract.manager.util.UITools;
import javafx.scene.control.Tab;
import javafx.util.converter.LocalDateStringConverter;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.service.DepartmentService;
import com.ecep.contract.util.UITools;
import javafx.scene.control.Tab;
import javafx.util.converter.LocalDateStringConverter;
public class EmployeeTabSkinBase public class EmployeeTabSkinBase
extends AbstEmployeeBasedTabSkin extends AbstEmployeeBasedTabSkin
implements TabSkin { implements TabSkin {
@@ -24,11 +23,8 @@ public class EmployeeTabSkinBase
@Override @Override
public void initializeTab() { public void initializeTab() {
EntityStringConverter<Department> departmentEntityStringConverter = new EntityStringConverter<>();
DepartmentService departmentService = getBean(DepartmentService.class);
departmentEntityStringConverter.setInitialized(department -> departmentService.findById(department.getId()));
UITools.autoCompletion(controller.departmentField, viewModel.getDepartment(), UITools.autoCompletion(controller.departmentField, viewModel.getDepartment(),
p -> departmentService.search(p.getUserText()), departmentEntityStringConverter); getCachedBean(DepartmentService.class));
controller.nameField.textProperty().bindBidirectional(viewModel.getName()); controller.nameField.textProperty().bindBidirectional(viewModel.getName());
controller.aliasField.textProperty().bindBidirectional(viewModel.getAlias()); controller.aliasField.textProperty().bindBidirectional(viewModel.getAlias());
@@ -48,9 +44,10 @@ public class EmployeeTabSkinBase
controller.isActiveField.selectedProperty().bindBidirectional(viewModel.getIsActive()); controller.isActiveField.selectedProperty().bindBidirectional(viewModel.getIsActive());
// Callback<ListView<EmployeeRole>, ListCell<EmployeeRole>> cellFactory =
// Callback<ListView<EmployeeRole>, ListCell<EmployeeRole>> cellFactory = controller.rolesField.getCellFactory(); // controller.rolesField.getCellFactory();
// StringConverter<EmployeeRole> employeeRoleStringConverter = new EntityStringConverter<>(); // StringConverter<EmployeeRole> employeeRoleStringConverter = new
// EntityStringConverter<>();
// controller.rolesField.setCellFactory(param -> { // controller.rolesField.setCellFactory(param -> {
// ListCell<EmployeeRole> cell = cellFactory.call(param); // ListCell<EmployeeRole> cell = cellFactory.call(param);
// if (cell instanceof CheckBoxListCell<EmployeeRole> list) { // if (cell instanceof CheckBoxListCell<EmployeeRole> list) {
@@ -59,10 +56,11 @@ public class EmployeeTabSkinBase
// return cell; // return cell;
// }); // });
// controller.rolesField.getCheckModel().getCheckedItems().setAll(); // controller.rolesField.getCheckModel().getCheckedItems().setAll();
// Property<IndexedCheckModel<EmployeeRole>> selectedRoles = new SimpleObjectProperty<>(); // Property<IndexedCheckModel<EmployeeRole>> selectedRoles = new
// controller.rolesField.getCheckModel().getCheckedItems().addListener((ListChangeListener<? super EmployeeRole>) changed -> { // SimpleObjectProperty<>();
// controller.rolesField.getCheckModel().getCheckedItems().addListener((ListChangeListener<?
// super EmployeeRole>) changed -> {
// System.out.println("newValue = " + changed); // System.out.println("newValue = " + changed);
// }); // });
} }

View File

@@ -1,20 +1,21 @@
package com.ecep.contract.manager.ds.other.controller.employee; package com.ecep.contract.controller.employee;
import java.time.LocalDateTime;
import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.controller.table.cell.LocalDateTimeTableCell;
import com.ecep.contract.service.EmployeeLoginHistoryService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.vo.EmployeeLoginHistoryVo;
import com.ecep.contract.vm.EmployeeLoginHistoryViewModel;
import com.ecep.contract.manager.ds.other.model.EmployeeLoginHistory;
import com.ecep.contract.manager.ds.other.service.EmployeeLoginHistoryService;
import com.ecep.contract.manager.ds.other.vo.EmployeeLoginHistoryViewModel;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.ui.tab.TabSkin;
import com.ecep.contract.manager.ui.table.cell.LocalDateTimeTableCell;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.scene.control.Tab; import javafx.scene.control.Tab;
import javafx.scene.control.TableColumn; import javafx.scene.control.TableColumn;
import java.time.LocalDateTime;
@FxmlPath("/ui/employee/employee-login-history.fxml") @FxmlPath("/ui/employee/employee-login-history.fxml")
public class EmployeeTabSkinLoginHistory public class EmployeeTabSkinLoginHistory
extends AbstEmployeeTableTabSkin<EmployeeLoginHistory, EmployeeLoginHistoryViewModel> extends AbstEmployeeTableTabSkin<EmployeeLoginHistoryVo, EmployeeLoginHistoryViewModel>
implements TabSkin { implements TabSkin {
public TableColumn<EmployeeLoginHistoryViewModel, Number> idColumn; public TableColumn<EmployeeLoginHistoryViewModel, Number> idColumn;
public TableColumn<EmployeeLoginHistoryViewModel, String> ipColumn; public TableColumn<EmployeeLoginHistoryViewModel, String> ipColumn;

View File

@@ -1,18 +1,18 @@
package com.ecep.contract.manager.ds.other.controller.employee; package com.ecep.contract.controller.employee;
import java.util.HashMap;
import java.util.List;
import org.springframework.data.domain.Pageable;
import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.vo.EmployeeRoleVo;
import com.ecep.contract.manager.Desktop;
import com.ecep.contract.manager.ds.other.model.Employee;
import com.ecep.contract.manager.ds.other.model.EmployeeRole;
import com.ecep.contract.manager.ui.tab.TabSkin;
import javafx.beans.property.BooleanProperty; import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleBooleanProperty;
import javafx.collections.ListChangeListener; import javafx.collections.ListChangeListener;
import javafx.scene.control.ListCell; import javafx.scene.control.ListCell;
import javafx.scene.control.Tab; import javafx.scene.control.Tab;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import java.util.List;
public class EmployeeTabSkinRole public class EmployeeTabSkinRole
extends AbstEmployeeBasedTabSkin extends AbstEmployeeBasedTabSkin
@@ -41,24 +41,21 @@ public class EmployeeTabSkinRole
} }
private void loadSelectedRoles() { private void loadSelectedRoles() {
List<EmployeeRole> selectedRoles = getEmployeeService().getRolesByEmployeeId(viewModel.getId().get()); List<EmployeeRoleVo> selectedRoles = getEmployeeService().getRolesByEmployeeId(viewModel.getId().get());
controller.rolesField.getTargetItems().setAll(selectedRoles); controller.rolesField.getTargetItems().setAll(selectedRoles);
changed.set(false); changed.set(false);
} }
private void initializeListView() { private void initializeListView() {
// 非系统内置账户 // 非系统内置账户
Specification<EmployeeRole> spec = null; HashMap<String, Object> params = new HashMap<>();
if (!Desktop.instance.getActiveEmployee().isSystemAdministrator()) { List<EmployeeRoleVo> roles = getEmployeeRoleService().findAll(params, Pageable.ofSize(500)).getContent();
spec = (root, query, cb) -> cb.equal(root.get("systemAdministrator"), false);
}
List<EmployeeRole> roles = getEmployeeRoleService().findAll(spec, Pageable.ofSize(500)).getContent();
controller.rolesField.getSourceItems().setAll(roles); controller.rolesField.getSourceItems().setAll(roles);
controller.rolesField.setCellFactory(param -> { controller.rolesField.setCellFactory(param -> {
return new ListCell<>() { return new ListCell<EmployeeRoleVo>() {
@Override @Override
protected void updateItem(EmployeeRole item, boolean empty) { protected void updateItem(EmployeeRoleVo item, boolean empty) {
super.updateItem(item, empty); super.updateItem(item, empty);
if (item == null || empty) { if (item == null || empty) {
setText(null); setText(null);
@@ -69,10 +66,10 @@ public class EmployeeTabSkinRole
}; };
}); });
controller.rolesField.getTargetItems().addListener((ListChangeListener<EmployeeRole>) change -> { controller.rolesField.getTargetItems().addListener((ListChangeListener<EmployeeRoleVo>) change -> {
while (change.next()) { while (change.next()) {
List<? extends EmployeeRole> added = change.getAddedSubList(); List<? extends EmployeeRoleVo> added = change.getAddedSubList();
List<? extends EmployeeRole> removed = change.getRemoved(); List<? extends EmployeeRoleVo> removed = change.getRemoved();
if (!added.isEmpty() || !removed.isEmpty()) { if (!added.isEmpty() || !removed.isEmpty()) {
changed.set(true); changed.set(true);
} }
@@ -82,9 +79,7 @@ public class EmployeeTabSkinRole
@Override @Override
public void save() { public void save() {
Employee entity = getEntity(); getEmployeeService().getUpdateEmployeeRoles(viewModel.getId().get(), controller.rolesField.getTargetItems());
entity.setRoles(controller.rolesField.getTargetItems());
save(entity);
loadSelectedRoles(); loadSelectedRoles();
} }
} }

View File

@@ -1,18 +1,5 @@
package com.ecep.contract.manager.ds.other.controller.employee; package com.ecep.contract.controller.employee;
import com.ecep.contract.manager.ds.other.model.Employee;
import com.ecep.contract.manager.ds.other.model.EmployeeRole;
import com.ecep.contract.manager.ds.other.service.EmployeeService;
import com.ecep.contract.manager.ds.other.vo.EmployeeViewModel;
import com.ecep.contract.manager.ui.AbstEntityController;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.ui.ViewModelService;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.stage.Window;
import javafx.stage.WindowEvent;
import lombok.Getter;
import org.controlsfx.control.ListSelectionView; import org.controlsfx.control.ListSelectionView;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -21,11 +8,29 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.ecep.contract.controller.AbstEntityController;
import com.ecep.contract.service.EmployeeService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.vm.EmployeeViewModel;
import com.ecep.contract.vo.EmployeeRoleVo;
import com.ecep.contract.vo.EmployeeVo;
import javafx.scene.control.CheckBox;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.stage.Window;
import javafx.stage.WindowEvent;
import lombok.Getter;
@Lazy @Lazy
@Scope("prototype") @Scope("prototype")
@Component @Component
@FxmlPath("/ui/employee/employee.fxml") @FxmlPath("/ui/employee/employee.fxml")
public class EmployeeWindowController extends AbstEntityController<Employee, EmployeeViewModel> { public class EmployeeWindowController extends AbstEntityController<EmployeeVo, EmployeeViewModel> {
private static final Logger logger = LoggerFactory.getLogger(EmployeeWindowController.class); private static final Logger logger = LoggerFactory.getLogger(EmployeeWindowController.class);
/** /**
@@ -55,7 +60,7 @@ public class EmployeeWindowController extends AbstEntityController<Employee, Emp
*/ */
public Tab rolesTab; public Tab rolesTab;
public ListSelectionView<EmployeeRole> rolesField; public ListSelectionView<EmployeeRoleVo> rolesField;
public Tab loginHistoryTab; public Tab loginHistoryTab;
public Tab authBindTab; public Tab authBindTab;
@@ -66,7 +71,7 @@ public class EmployeeWindowController extends AbstEntityController<Employee, Emp
public TableView<Tab> permissionsTable; public TableView<Tab> permissionsTable;
public static void show(Employee employee, Window owner) { public static void show(EmployeeVo employee, Window owner) {
EmployeeViewModel model = EmployeeViewModel.from(employee); EmployeeViewModel model = EmployeeViewModel.from(employee);
show(model, owner); show(model, owner);
} }

View File

@@ -1,16 +1,18 @@
package com.ecep.contract.manager.ds.other.controller.inventory; package com.ecep.contract.controller.inventory;
import java.util.function.Function;
import com.ecep.contract.controller.AbstEntityManagerSkin;
import com.ecep.contract.controller.table.cell.InventoryCatalogTableCell;
import com.ecep.contract.controller.table.cell.LocalDateFieldTableCell;
import com.ecep.contract.controller.table.cell.LocalDateTimeTableCell;
import com.ecep.contract.converter.EntityStringConverter;
import com.ecep.contract.service.InventoryCatalogService;
import com.ecep.contract.service.InventoryService;
import com.ecep.contract.vm.InventoryViewModel;
import com.ecep.contract.vo.InventoryCatalogVo;
import com.ecep.contract.vo.InventoryVo;
import com.ecep.contract.manager.ds.other.EntityStringConverter;
import com.ecep.contract.manager.ds.other.model.Inventory;
import com.ecep.contract.manager.ds.other.model.InventoryCatalog;
import com.ecep.contract.manager.ds.other.service.InventoryCatalogService;
import com.ecep.contract.manager.ds.other.service.InventoryService;
import com.ecep.contract.manager.ds.other.vo.InventoryViewModel;
import com.ecep.contract.manager.ui.AbstEntityManagerSkin;
import com.ecep.contract.manager.ui.table.EditableEntityTableTabSkin;
import com.ecep.contract.manager.ui.ManagerSkin;
import com.ecep.contract.manager.ui.util.LocalDateFieldTableCell;
import com.ecep.contract.manager.ui.table.cell.LocalDateTimeTableCell;
import javafx.beans.property.Property; import javafx.beans.property.Property;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.scene.control.TableColumn; import javafx.scene.control.TableColumn;
@@ -19,11 +21,8 @@ import javafx.util.converter.CurrencyStringConverter;
import javafx.util.converter.NumberStringConverter; import javafx.util.converter.NumberStringConverter;
import lombok.Setter; import lombok.Setter;
import java.util.function.Function; public class InventoryManagerSkin extends
AbstEntityManagerSkin<InventoryVo, InventoryViewModel, InventoryManagerSkin, InventoryManagerWindowController> {
public class InventoryManagerSkin
extends AbstEntityManagerSkin<Inventory, InventoryViewModel, InventoryManagerSkin, InventoryManagerWindowController>
implements ManagerSkin, EditableEntityTableTabSkin<Inventory, InventoryViewModel> {
@Setter @Setter
private InventoryCatalogService catalogService; private InventoryCatalogService catalogService;
@@ -58,18 +57,13 @@ public class InventoryManagerSkin
controller.codeColumn.setOnEditCommit(event -> onColumnEditCommit(event, InventoryViewModel::getCode)); controller.codeColumn.setOnEditCommit(event -> onColumnEditCommit(event, InventoryViewModel::getCode));
controller.catalogColumn.setCellValueFactory(param -> param.getValue().getCatalog()); controller.catalogColumn.setCellValueFactory(param -> param.getValue().getCatalog());
EntityStringConverter<InventoryCatalog> catalogStringConverter = new EntityStringConverter<>(); controller.catalogColumn.setCellFactory(param-> new InventoryCatalogTableCell<>(getInventoryCatalogService()));
catalogStringConverter.setInitialized(v -> getInventoryCatalogService().findById(v.getId()));
catalogStringConverter.setFormater(InventoryCatalog::getName);
catalogStringConverter.setFromString(v -> getInventoryCatalogService().findByName(v));
catalogStringConverter.setSuggestion(getInventoryCatalogService()::search);
controller.catalogColumn.setCellFactory(TextFieldTableCell.forTableColumn(catalogStringConverter));
controller.catalogColumn.setOnEditCommit(event -> onColumnEditCommit(event, InventoryViewModel::getCatalog)); controller.catalogColumn.setOnEditCommit(event -> onColumnEditCommit(event, InventoryViewModel::getCatalog));
controller.specificationColumn.setCellValueFactory(param -> param.getValue().getSpecification()); controller.specificationColumn.setCellValueFactory(param -> param.getValue().getSpecification());
controller.specificationColumn.setCellFactory(TextFieldTableCell.forTableColumn()); controller.specificationColumn.setCellFactory(TextFieldTableCell.forTableColumn());
controller.specificationColumn.setOnEditCommit(event -> onColumnEditCommit(event, InventoryViewModel::getSpecification)); controller.specificationColumn
.setOnEditCommit(event -> onColumnEditCommit(event, InventoryViewModel::getSpecification));
controller.unitColumn.setCellValueFactory(param -> param.getValue().getUnit()); controller.unitColumn.setCellValueFactory(param -> param.getValue().getUnit());
controller.unitColumn.setCellFactory(TextFieldTableCell.forTableColumn()); controller.unitColumn.setCellFactory(TextFieldTableCell.forTableColumn());
@@ -77,44 +71,48 @@ public class InventoryManagerSkin
controller.purchaseTaxRateColumn.setCellValueFactory(param -> param.getValue().getPurchaseTaxRate()); controller.purchaseTaxRateColumn.setCellValueFactory(param -> param.getValue().getPurchaseTaxRate());
controller.purchaseTaxRateColumn.setCellFactory(TextFieldTableCell.forTableColumn(new NumberStringConverter())); controller.purchaseTaxRateColumn.setCellFactory(TextFieldTableCell.forTableColumn(new NumberStringConverter()));
controller.purchaseTaxRateColumn.setOnEditCommit(event -> onColumnEditCommit(event, InventoryViewModel::getPurchaseTaxRate)); controller.purchaseTaxRateColumn
.setOnEditCommit(event -> onColumnEditCommit(event, InventoryViewModel::getPurchaseTaxRate));
controller.purchasePriceColumn.setCellValueFactory(param -> param.getValue().getPurchasePrice()); controller.purchasePriceColumn.setCellValueFactory(param -> param.getValue().getPurchasePrice());
controller.purchasePriceColumn.setCellFactory(TextFieldTableCell.forTableColumn(new CurrencyStringConverter())); controller.purchasePriceColumn.setCellFactory(TextFieldTableCell.forTableColumn(new CurrencyStringConverter()));
// controller.purchasePriceColumn.setOnEditCommit(event -> onColumnEditCommit(event, InventoryViewModel::getPurchasePrice)); // controller.purchasePriceColumn.setOnEditCommit(event ->
// onColumnEditCommit(event, InventoryViewModel::getPurchasePrice));
controller.saleTaxRateColumn.setCellValueFactory(param -> param.getValue().getSaleTaxRate()); controller.saleTaxRateColumn.setCellValueFactory(param -> param.getValue().getSaleTaxRate());
controller.saleTaxRateColumn.setCellFactory(TextFieldTableCell.forTableColumn(new NumberStringConverter())); controller.saleTaxRateColumn.setCellFactory(TextFieldTableCell.forTableColumn(new NumberStringConverter()));
controller.saleTaxRateColumn.setOnEditCommit(event -> onColumnEditCommit(event, InventoryViewModel::getSaleTaxRate)); controller.saleTaxRateColumn
.setOnEditCommit(event -> onColumnEditCommit(event, InventoryViewModel::getSaleTaxRate));
controller.salePriceColumn.setCellValueFactory(param -> param.getValue().getSalePrice()); controller.salePriceColumn.setCellValueFactory(param -> param.getValue().getSalePrice());
controller.salePriceColumn.setCellFactory(TextFieldTableCell.forTableColumn(new CurrencyStringConverter())); controller.salePriceColumn.setCellFactory(TextFieldTableCell.forTableColumn(new CurrencyStringConverter()));
// controller.salePriceColumn.setOnEditCommit(event -> onColumnEditCommit(event, InventoryViewModel::getSalePrice)); // controller.salePriceColumn.setOnEditCommit(event -> onColumnEditCommit(event,
// InventoryViewModel::getSalePrice));
controller.createTimeColumn.setCellValueFactory(param -> param.getValue().getCreateTime()); controller.createTimeColumn.setCellValueFactory(param -> param.getValue().getCreateTime());
controller.createTimeColumn.setCellFactory(LocalDateFieldTableCell.forTableColumn()); controller.createTimeColumn.setCellFactory(LocalDateFieldTableCell.forTableColumn());
controller.createTimeColumn.setOnEditCommit(event -> onColumnEditCommit(event, InventoryViewModel::getCreateTime)); controller.createTimeColumn
.setOnEditCommit(event -> onColumnEditCommit(event, InventoryViewModel::getCreateTime));
controller.updateDateColumn.setCellValueFactory(param -> param.getValue().getUpdateDate()); controller.updateDateColumn.setCellValueFactory(param -> param.getValue().getUpdateDate());
controller.updateDateColumn.setCellFactory(param -> new LocalDateTimeTableCell<>()); controller.updateDateColumn.setCellFactory(param -> new LocalDateTimeTableCell<>());
controller.updateDateColumn.setOnEditCommit(event -> onColumnEditCommit(event, InventoryViewModel::getUpdateDate)); controller.updateDateColumn
.setOnEditCommit(event -> onColumnEditCommit(event, InventoryViewModel::getUpdateDate));
controller.descriptionColumn.setCellValueFactory(param -> param.getValue().getDescription()); controller.descriptionColumn.setCellValueFactory(param -> param.getValue().getDescription());
controller.descriptionColumn.setCellFactory(TextFieldTableCell.forTableColumn()); controller.descriptionColumn.setCellFactory(TextFieldTableCell.forTableColumn());
controller.descriptionColumn.setOnEditCommit(event -> onColumnEditCommit(event, InventoryViewModel::getDescription)); controller.descriptionColumn
.setOnEditCommit(event -> onColumnEditCommit(event, InventoryViewModel::getDescription));
} }
private <T> void onColumnEditCommit( private <T> void onColumnEditCommit(
TableColumn.CellEditEvent<InventoryViewModel, T> event, TableColumn.CellEditEvent<InventoryViewModel, T> event,
Function<InventoryViewModel, Property<T>> supplier Function<InventoryViewModel, Property<T>> supplier) {
) {
InventoryViewModel row = event.getRowValue(); InventoryViewModel row = event.getRowValue();
supplier.apply(row).setValue(event.getNewValue()); supplier.apply(row).setValue(event.getNewValue());
saveRowData(row); saveRowData(row);
} }
@Override @Override
protected void onTableRowDoubleClickedAction(InventoryViewModel item) { protected void onTableRowDoubleClickedAction(InventoryViewModel item) {
showInOwner(InventoryWindowController.class, item); showInOwner(InventoryWindowController.class, item);
@@ -122,7 +120,7 @@ public class InventoryManagerSkin
@Override @Override
protected void onTableCreateNewAction(ActionEvent event) { protected void onTableCreateNewAction(ActionEvent event) {
Inventory inventory = getService().save(getService().createNewInstance()); InventoryVo inventory = getService().save(getService().createNewEntity());
InventoryViewModel viewModel = InventoryViewModel.from(inventory); InventoryViewModel viewModel = InventoryViewModel.from(inventory);
dataSet.add(viewModel); dataSet.add(viewModel);
} }

View File

@@ -1,4 +1,4 @@
package com.ecep.contract.manager.ds.other.controller.inventory; package com.ecep.contract.controller.inventory;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@@ -8,13 +8,14 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.ecep.contract.manager.ds.other.model.Inventory; import com.ecep.contract.controller.AbstManagerWindowController;
import com.ecep.contract.manager.ds.other.model.InventoryCatalog; import com.ecep.contract.service.InventoryService;
import com.ecep.contract.manager.ds.other.service.InventoryService; import com.ecep.contract.task.InventorySyncTask;
import com.ecep.contract.manager.ds.other.vo.InventoryViewModel; import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.manager.ui.AbstManagerWindowController; import com.ecep.contract.util.UITools;
import com.ecep.contract.manager.ui.FxmlPath; import com.ecep.contract.vm.InventoryViewModel;
import com.ecep.contract.manager.util.UITools; import com.ecep.contract.vo.InventoryCatalogVo;
import com.ecep.contract.vo.InventoryVo;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.fxml.FXML; import javafx.fxml.FXML;
@@ -26,7 +27,7 @@ import javafx.stage.Stage;
@Component @Component
@FxmlPath(value = "/ui/inventory/inventory-manager.fxml") @FxmlPath(value = "/ui/inventory/inventory-manager.fxml")
public class InventoryManagerWindowController public class InventoryManagerWindowController
extends AbstManagerWindowController<Inventory, InventoryViewModel, InventoryManagerSkin> { extends AbstManagerWindowController<InventoryVo, InventoryViewModel, InventoryManagerSkin> {
@FXML @FXML
public TableColumn<InventoryViewModel, Number> idColumn; public TableColumn<InventoryViewModel, Number> idColumn;
@@ -34,8 +35,11 @@ public class InventoryManagerWindowController
public TableColumn<InventoryViewModel, String> nameColumn; public TableColumn<InventoryViewModel, String> nameColumn;
@FXML @FXML
public TableColumn<InventoryViewModel, String> codeColumn; public TableColumn<InventoryViewModel, String> codeColumn;
/**
* InventoryCatalogVo
*/
@FXML @FXML
public TableColumn<InventoryViewModel, InventoryCatalog> catalogColumn; public TableColumn<InventoryViewModel, Integer> catalogColumn;
@FXML @FXML
public TableColumn<InventoryViewModel, String> specificationColumn; public TableColumn<InventoryViewModel, String> specificationColumn;
@FXML @FXML

View File

@@ -1,19 +1,25 @@
package com.ecep.contract.manager.ds.other.controller.inventory; package com.ecep.contract.controller.inventory;
import java.text.NumberFormat;
import java.time.format.DateTimeFormatter;
import java.util.function.Consumer;
import org.springframework.util.StringUtils;
import com.ecep.contract.MessageHolder;
import com.ecep.contract.MyDateTimeUtils;
import com.ecep.contract.controller.tab.AbstEntityBasedTabSkin;
import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.controller.table.EditableEntityTableTabSkin;
import com.ecep.contract.converter.EmployeeStringConverter;
import com.ecep.contract.converter.EntityStringConverter;
import com.ecep.contract.service.InventoryCatalogService;
import com.ecep.contract.service.InventoryService;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.InventoryViewModel;
import com.ecep.contract.vo.InventoryCatalogVo;
import com.ecep.contract.vo.InventoryVo;
import com.ecep.contract.manager.cloud.u8.ctx.InventoryCtx;
import com.ecep.contract.manager.ds.other.EmployeeStringConverter;
import com.ecep.contract.manager.ds.other.EntityStringConverter;
import com.ecep.contract.manager.ds.other.model.Inventory;
import com.ecep.contract.manager.ds.other.model.InventoryCatalog;
import com.ecep.contract.manager.ds.other.service.InventoryCatalogService;
import com.ecep.contract.manager.ds.other.service.InventoryService;
import com.ecep.contract.manager.ds.other.vo.InventoryViewModel;
import com.ecep.contract.manager.ui.tab.AbstEntityBasedTabSkin;
import com.ecep.contract.manager.ui.table.EditableEntityTableTabSkin;
import com.ecep.contract.manager.ui.MessageHolder;
import com.ecep.contract.manager.ui.tab.TabSkin;
import com.ecep.contract.manager.util.MyDateTimeUtils;
import com.ecep.contract.manager.util.UITools;
import javafx.beans.binding.Bindings; import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleDoubleProperty; import javafx.beans.property.SimpleDoubleProperty;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
@@ -23,37 +29,21 @@ import javafx.util.converter.CurrencyStringConverter;
import javafx.util.converter.LocalDateStringConverter; import javafx.util.converter.LocalDateStringConverter;
import javafx.util.converter.LocalDateTimeStringConverter; import javafx.util.converter.LocalDateTimeStringConverter;
import javafx.util.converter.NumberStringConverter; import javafx.util.converter.NumberStringConverter;
import lombok.Setter;
import org.springframework.util.StringUtils;
import java.text.NumberFormat;
import java.time.format.DateTimeFormatter;
import java.util.function.Consumer;
public class InventoryTabSkinBase public class InventoryTabSkinBase
extends AbstEntityBasedTabSkin<InventoryWindowController, Inventory, InventoryViewModel> extends AbstEntityBasedTabSkin<InventoryWindowController, InventoryVo, InventoryViewModel>
implements TabSkin, EditableEntityTableTabSkin<Inventory, InventoryViewModel> { implements TabSkin, EditableEntityTableTabSkin<InventoryVo, InventoryViewModel> {
@Setter
private InventoryService service;
@Setter
private InventoryCatalogService catalogService;
public InventoryTabSkinBase(InventoryWindowController controller) { public InventoryTabSkinBase(InventoryWindowController controller) {
super(controller); super(controller);
} }
InventoryService getService() { InventoryService getService() {
if (service == null) { return getCachedBean(InventoryService.class);
service = getBean(InventoryService.class);
}
return service;
} }
InventoryCatalogService getCatalogService() { InventoryCatalogService getCatalogService() {
if (catalogService == null) { return getCachedBean(InventoryCatalogService.class);
catalogService = getBean(InventoryCatalogService.class);
}
return catalogService;
} }
@Override @Override
@@ -77,25 +67,27 @@ public class InventoryTabSkinBase
controller.specificationField.textProperty().bindBidirectional(viewModel.getSpecification()); controller.specificationField.textProperty().bindBidirectional(viewModel.getSpecification());
controller.specificationLockField.selectedProperty().bindBidirectional(viewModel.getSpecificationLock()); controller.specificationLockField.selectedProperty().bindBidirectional(viewModel.getSpecificationLock());
EntityStringConverter<InventoryCatalog> catalogConverter = new EntityStringConverter<>(); UITools.autoCompletion(controller.catalogField, viewModel.getCatalog(), getCatalogService());
catalogConverter.setInitialized(v -> getCatalogService().findById(v.getId()));
catalogConverter.setFormater(InventoryCatalog::getName);
catalogConverter.setSuggestion(getCatalogService()::search);
catalogConverter.setFromString(getCatalogService()::findByName);
UITools.autoCompletion(controller.catalogField, viewModel.getCatalog(), catalogConverter);
controller.purchaseTaxRateField.textProperty().bindBidirectional(viewModel.getPurchaseTaxRate(), new NumberStringConverter()); controller.purchaseTaxRateField.textProperty().bindBidirectional(viewModel.getPurchaseTaxRate(),
new NumberStringConverter());
// 采购价 // 采购价
bindPriceField(controller.purchasePriceField, viewModel.getPurchasePrice(), currencyStringConverter, viewModel::updatePurchasePrice); bindPriceField(controller.purchasePriceField, viewModel.getPurchasePrice(), currencyStringConverter,
bindPriceField(controller.purchaseTaxPriceField, viewModel.getPurchaseTaxPrice(), currencyStringConverter, viewModel::updatePurchaseTaxPrice); viewModel::updatePurchasePrice);
bindPriceField(controller.purchaseTaxPriceField, viewModel.getPurchaseTaxPrice(), currencyStringConverter,
viewModel::updatePurchaseTaxPrice);
controller.saleTaxRateField.textProperty().bindBidirectional(viewModel.getSaleTaxRate(), new NumberStringConverter()); controller.saleTaxRateField.textProperty().bindBidirectional(viewModel.getSaleTaxRate(),
new NumberStringConverter());
// 销售价 // 销售价
bindPriceField(controller.salePriceField, viewModel.getSalePrice(), currencyStringConverter, viewModel::updateSalePrice); bindPriceField(controller.salePriceField, viewModel.getSalePrice(), currencyStringConverter,
bindPriceField(controller.saleTaxPriceField, viewModel.getSaleTaxPrice(), currencyStringConverter, viewModel::updateSaleTaxPrice); viewModel::updateSalePrice);
bindPriceField(controller.saleTaxPriceField, viewModel.getSaleTaxPrice(), currencyStringConverter,
viewModel::updateSaleTaxPrice);
// 采购价不能大于销售价 // 采购价不能大于销售价
Bindings.greaterThan(viewModel.getPurchasePrice(), viewModel.getSalePrice()).addListener((observable, oldValue, newValue) -> { Bindings.greaterThan(viewModel.getPurchasePrice(), viewModel.getSalePrice())
.addListener((observable, oldValue, newValue) -> {
if (newValue) { if (newValue) {
controller.purchasePriceField.getStyleClass().add("error"); controller.purchasePriceField.getStyleClass().add("error");
controller.salePriceField.getStyleClass().add("error"); controller.salePriceField.getStyleClass().add("error");
@@ -104,7 +96,8 @@ public class InventoryTabSkinBase
controller.salePriceField.getStyleClass().remove("error"); controller.salePriceField.getStyleClass().remove("error");
} }
}); });
Bindings.greaterThan(viewModel.getPurchaseTaxPrice(), viewModel.getSaleTaxPrice()).addListener((observable, oldValue, newValue) -> { Bindings.greaterThan(viewModel.getPurchaseTaxPrice(), viewModel.getSaleTaxPrice())
.addListener((observable, oldValue, newValue) -> {
if (newValue) { if (newValue) {
controller.purchaseTaxPriceField.getStyleClass().add("error"); controller.purchaseTaxPriceField.getStyleClass().add("error");
controller.saleTaxPriceField.getStyleClass().add("error"); controller.saleTaxPriceField.getStyleClass().add("error");
@@ -114,35 +107,44 @@ public class InventoryTabSkinBase
} }
}); });
EmployeeStringConverter employeeStringConverter = getBean(EmployeeStringConverter.class); UITools.autoCompletion(controller.creatorField, viewModel.getCreator(), controller.getEmployeeService());
UITools.autoCompletion(controller.creatorField, viewModel.getCreator(), employeeStringConverter);
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(MyDateTimeUtils.DEFAULT_DATE_FORMAT_PATTERN); DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(MyDateTimeUtils.DEFAULT_DATE_FORMAT_PATTERN);
controller.createTimeField.textProperty().bindBidirectional(viewModel.getCreateTime(), new LocalDateStringConverter(dateFormatter, null)); controller.createTimeField.textProperty().bindBidirectional(viewModel.getCreateTime(),
new LocalDateStringConverter(dateFormatter, null));
UITools.autoCompletion(controller.updaterField, viewModel.getUpdater(), employeeStringConverter);
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(MyDateTimeUtils.DEFAULT_DATETIME_FORMAT_PATTERN);
controller.updateDateField.textProperty().bindBidirectional(viewModel.getUpdateDate(), new LocalDateTimeStringConverter(dateTimeFormatter, null));
UITools.autoCompletion(controller.updaterField, viewModel.getUpdater(), controller.getEmployeeService());
DateTimeFormatter dateTimeFormatter = DateTimeFormatter
.ofPattern(MyDateTimeUtils.DEFAULT_DATETIME_FORMAT_PATTERN);
controller.updateDateField.textProperty().bindBidirectional(viewModel.getUpdateDate(),
new LocalDateTimeStringConverter(dateTimeFormatter, null));
controller.weightUnitField.textProperty().bindBidirectional(viewModel.getWeightUnit()); controller.weightUnitField.textProperty().bindBidirectional(viewModel.getWeightUnit());
controller.sizeUnitField.textProperty().bindBidirectional(viewModel.getSizeUnit()); controller.sizeUnitField.textProperty().bindBidirectional(viewModel.getSizeUnit());
controller.volumeUnitField.textProperty().bindBidirectional(viewModel.getVolumeUnit()); controller.volumeUnitField.textProperty().bindBidirectional(viewModel.getVolumeUnit());
controller.weightField.textProperty().bindBidirectional(viewModel.getWeight(), new NumberStringConverter()); controller.weightField.textProperty().bindBidirectional(viewModel.getWeight(), new NumberStringConverter());
controller.packagedWeightField.textProperty().bindBidirectional(viewModel.getPackagedWeight(), new NumberStringConverter()); controller.packagedWeightField.textProperty().bindBidirectional(viewModel.getPackagedWeight(),
controller.sizeLengthField.textProperty().bindBidirectional(viewModel.getSizeLength(), new NumberStringConverter()); new NumberStringConverter());
controller.sizeWidthField.textProperty().bindBidirectional(viewModel.getSizeWidth(), new NumberStringConverter()); controller.sizeLengthField.textProperty().bindBidirectional(viewModel.getSizeLength(),
controller.sizeHeightField.textProperty().bindBidirectional(viewModel.getSizeHeight(), new NumberStringConverter()); new NumberStringConverter());
controller.sizeWidthField.textProperty().bindBidirectional(viewModel.getSizeWidth(),
new NumberStringConverter());
controller.sizeHeightField.textProperty().bindBidirectional(viewModel.getSizeHeight(),
new NumberStringConverter());
controller.volumeField.textProperty().bindBidirectional(viewModel.getVolume(), new NumberStringConverter()); controller.volumeField.textProperty().bindBidirectional(viewModel.getVolume(), new NumberStringConverter());
controller.packagedSizeLengthField.textProperty().bindBidirectional(viewModel.getPackagedSizeLength(), new NumberStringConverter()); controller.packagedSizeLengthField.textProperty().bindBidirectional(viewModel.getPackagedSizeLength(),
controller.packagedSizeWidthField.textProperty().bindBidirectional(viewModel.getPackagedSizeWidth(), new NumberStringConverter()); new NumberStringConverter());
controller.packagedSizeHeightField.textProperty().bindBidirectional(viewModel.getPackagedSizeHeight(), new NumberStringConverter()); controller.packagedSizeWidthField.textProperty().bindBidirectional(viewModel.getPackagedSizeWidth(),
controller.packagedVolumeField.textProperty().bindBidirectional(viewModel.getPackagedVolume(), new NumberStringConverter()); new NumberStringConverter());
controller.packagedSizeHeightField.textProperty().bindBidirectional(viewModel.getPackagedSizeHeight(),
new NumberStringConverter());
controller.packagedVolumeField.textProperty().bindBidirectional(viewModel.getPackagedVolume(),
new NumberStringConverter());
controller.descriptionField.textProperty().bindBidirectional(viewModel.getDescription()); controller.descriptionField.textProperty().bindBidirectional(viewModel.getDescription());
} }
private void bindPriceField(TextField textField, SimpleDoubleProperty property, CurrencyStringConverter stringConverter, Consumer<Double> updater) { private void bindPriceField(TextField textField, SimpleDoubleProperty property,
CurrencyStringConverter stringConverter, Consumer<Double> updater) {
textField.setText(stringConverter.toString(property.get())); textField.setText(stringConverter.toString(property.get()));
property.addListener((observable, oldValue, newValue) -> { property.addListener((observable, oldValue, newValue) -> {
textField.setText(stringConverter.toString(newValue)); textField.setText(stringConverter.toString(newValue));
@@ -154,7 +156,7 @@ public class InventoryTabSkinBase
} }
private void onSyncAction(ActionEvent event) { private void onSyncAction(ActionEvent event) {
Inventory inventory = getEntity(); InventoryVo inventory = getEntity();
setStatus("开始同步数据..."); setStatus("开始同步数据...");
if (inventory == null) { if (inventory == null) {
setStatus("请选择要同步的数据."); setStatus("请选择要同步的数据.");
@@ -165,30 +167,23 @@ public class InventoryTabSkinBase
return; return;
} }
setStatus("正在同步数据..."); setStatus("正在同步数据...");
InventoryCtx ctx = new InventoryCtx();
MessageHolder holder = (lv, msg) -> setStatus(msg); MessageHolder holder = (lv, msg) -> setStatus(msg);
ctx.initializeRepository(holder); getService().syncInventory(inventory, holder);
if (ctx.syncInventoryDetailByCode(inventory, inventory.getCode(), holder)) {
save(inventory);
setStatus("同步数据完成.");
} else {
setStatus("没有数据更新.");
}
} }
@Override @Override
public void deleteRowData(Inventory entity) { public void deleteRowData(InventoryVo entity) {
getService().delete(entity); getService().delete(entity);
} }
@Override @Override
public Inventory loadRowData(InventoryViewModel row) { public InventoryVo loadRowData(InventoryViewModel row) {
return getService().findById(row.getId().get()); return getService().findById(row.getId().get());
} }
@Override @Override
public Inventory saveRowData(Inventory entity) { public InventoryVo saveRowData(InventoryVo entity) {
return getService().save(entity); return getService().save(entity);
} }
} }

View File

@@ -1,34 +1,32 @@
package com.ecep.contract.manager.ds.other.controller.inventory; package com.ecep.contract.controller.inventory;
import java.text.NumberFormat;
import java.time.LocalDate;
import com.ecep.contract.controller.contract.ContractWindowController;
import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.controller.table.AbstEntityTableTabSkin;
import com.ecep.contract.service.ContractItemService;
import com.ecep.contract.service.ContractService;
import com.ecep.contract.service.InventoryHistoryPriceService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.ParamUtils;
import com.ecep.contract.vm.ContractViewModel;
import com.ecep.contract.vm.InventoryViewModel;
import com.ecep.contract.vo.ContractVo;
import com.ecep.contract.vo.InventoryVo;
import com.ecep.contract.manager.ds.contract.controller.ContractWindowController;
import com.ecep.contract.manager.ds.contract.model.Contract;
import com.ecep.contract.manager.ds.contract.model.ContractItem;
import com.ecep.contract.manager.ds.contract.service.ContractItemService;
import com.ecep.contract.manager.ds.contract.service.ContractService;
import com.ecep.contract.manager.ds.contract.vo.ContractViewModel;
import com.ecep.contract.manager.ds.other.model.Inventory;
import com.ecep.contract.manager.ds.other.service.InventoryHistoryPriceService;
import com.ecep.contract.manager.ds.other.vo.InventoryViewModel;
import com.ecep.contract.manager.ui.table.AbstEntityTableTabSkin;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.ui.tab.TabSkin;
import com.ecep.contract.manager.util.SpecificationUtils;
import jakarta.persistence.criteria.Root;
import jakarta.persistence.criteria.Subquery;
import javafx.scene.control.ContextMenu; import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem; import javafx.scene.control.MenuItem;
import javafx.scene.control.Tab; import javafx.scene.control.Tab;
import javafx.scene.control.TableColumn; import javafx.scene.control.TableColumn;
import javafx.util.converter.CurrencyStringConverter; import javafx.util.converter.CurrencyStringConverter;
import lombok.Setter; import lombok.Setter;
import org.springframework.data.jpa.domain.Specification;
import java.text.NumberFormat;
import java.time.LocalDate;
@FxmlPath("/ui/inventory/inventory-contract.fxml") @FxmlPath("/ui/inventory/inventory-contract.fxml")
public class InventoryTabSkinContracts public class InventoryTabSkinContracts
extends AbstEntityTableTabSkin<InventoryWindowController, Inventory, InventoryViewModel, Contract, ContractViewModel> extends
AbstEntityTableTabSkin<InventoryWindowController, InventoryVo, InventoryViewModel, ContractVo, ContractViewModel>
implements TabSkin { implements TabSkin {
public TableColumn<ContractViewModel, Number> idColumn; public TableColumn<ContractViewModel, Number> idColumn;
public TableColumn<ContractViewModel, String> nameColumn; public TableColumn<ContractViewModel, String> nameColumn;
@@ -77,7 +75,6 @@ public class InventoryTabSkinContracts
return controller.contractsTab; return controller.contractsTab;
} }
@Override @Override
public void initializeTable() { public void initializeTable() {
super.initializeTable(); super.initializeTable();
@@ -93,18 +90,10 @@ public class InventoryTabSkinContracts
} }
@Override @Override
public Specification<Contract> getSpecification(Inventory parent) { public ParamUtils.Builder getSpecification(InventoryVo parent) {
return SpecificationUtils.and(getSpecification(), (root, query, builder) -> { ParamUtils.Builder params = getSpecification();
// 创建ContractItem的子查询 params.equals("inventory", parent);
Subquery<Integer> subquery = query.subquery(Integer.class); return params;
Root<ContractItem> from = subquery.from(ContractItem.class);
// 子查询选择与指定库存相关的合同ID
subquery.select(from.get("contract").get("id"))
.where(builder.equal(from.get("inventory"), parent));
// 主查询筛选ID在子查询结果中的合同
return builder.in(root.get("id")).value(subquery);
});
} }
@Override @Override

View File

@@ -1,28 +1,4 @@
package com.ecep.contract.manager.ds.other.controller.inventory; package com.ecep.contract.controller.inventory;
import com.ecep.contract.manager.ds.contract.ContractPayWay;
import com.ecep.contract.manager.ds.contract.model.Contract;
import com.ecep.contract.manager.ds.contract.model.ContractItem;
import com.ecep.contract.manager.ds.contract.service.ContractItemService;
import com.ecep.contract.manager.ds.contract.service.ContractService;
import com.ecep.contract.manager.ds.other.model.HistoryPrice;
import com.ecep.contract.manager.ds.other.model.Inventory;
import com.ecep.contract.manager.ds.other.model.InventoryHistoryPrice;
import com.ecep.contract.manager.ds.other.service.InventoryHistoryPriceService;
import com.ecep.contract.manager.ds.other.vo.InventoryHistoryPriceViewModel;
import com.ecep.contract.manager.ds.other.vo.InventoryViewModel;
import com.ecep.contract.manager.ui.table.AbstEntityTableTabSkin;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.ui.tab.TabSkin;
import com.ecep.contract.manager.util.SpecificationUtils;
import javafx.event.ActionEvent;
import javafx.scene.control.*;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.util.converter.CurrencyStringConverter;
import javafx.util.converter.NumberStringConverter;
import lombok.Setter;
import org.hibernate.Hibernate;
import org.springframework.data.jpa.domain.Specification;
import java.text.NumberFormat; import java.text.NumberFormat;
import java.time.MonthDay; import java.time.MonthDay;
@@ -32,9 +8,41 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.ecep.contract.ContractPayWay;
import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.controller.table.AbstEntityTableTabSkin;
import com.ecep.contract.model.Contract;
import com.ecep.contract.model.ContractItem;
import com.ecep.contract.model.HistoryPrice;
import com.ecep.contract.model.Inventory;
import com.ecep.contract.model.InventoryHistoryPrice;
import com.ecep.contract.service.ContractItemService;
import com.ecep.contract.service.ContractService;
import com.ecep.contract.service.InventoryHistoryPriceService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.ParamUtils;
import com.ecep.contract.util.ProxyUtils;
import com.ecep.contract.vm.InventoryHistoryPriceViewModel;
import com.ecep.contract.vm.InventoryViewModel;
import com.ecep.contract.vo.ContractItemVo;
import com.ecep.contract.vo.ContractVo;
import com.ecep.contract.vo.InventoryHistoryPriceVo;
import com.ecep.contract.vo.InventoryVo;
import javafx.event.ActionEvent;
import javafx.scene.control.Button;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.Tab;
import javafx.scene.control.TableColumn;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.util.converter.CurrencyStringConverter;
import javafx.util.converter.NumberStringConverter;
@FxmlPath("/ui/inventory/inventory-history-price.fxml") @FxmlPath("/ui/inventory/inventory-history-price.fxml")
public class InventoryTabSkinHistoryPrice public class InventoryTabSkinHistoryPrice
extends AbstEntityTableTabSkin<InventoryWindowController, Inventory, InventoryViewModel, InventoryHistoryPrice, InventoryHistoryPriceViewModel> extends
AbstEntityTableTabSkin<InventoryWindowController, InventoryVo, InventoryViewModel, InventoryHistoryPriceVo, InventoryHistoryPriceViewModel>
implements TabSkin { implements TabSkin {
public Button refreshBtn; public Button refreshBtn;
public TableColumn<InventoryHistoryPriceViewModel, Number> idColumn; public TableColumn<InventoryHistoryPriceViewModel, Number> idColumn;
@@ -66,42 +74,25 @@ public class InventoryTabSkinHistoryPrice
public TableColumn<InventoryHistoryPriceViewModel, Number> miniPurchaseTaxPriceColumn; public TableColumn<InventoryHistoryPriceViewModel, Number> miniPurchaseTaxPriceColumn;
public TableColumn<InventoryHistoryPriceViewModel, MonthDay> miniPurchasePriceDateColumn; public TableColumn<InventoryHistoryPriceViewModel, MonthDay> miniPurchasePriceDateColumn;
@Setter
InventoryHistoryPriceService service;
@Setter
ContractService contractService;
@Setter
ContractItemService contractItemService;
public InventoryTabSkinHistoryPrice(InventoryWindowController controller) { public InventoryTabSkinHistoryPrice(InventoryWindowController controller) {
super(controller); super(controller);
} }
@Override @Override
protected InventoryHistoryPriceService getViewModelService() { protected InventoryHistoryPriceService getViewModelService() {
return getService(); return getHistoryPriceService();
} }
InventoryHistoryPriceService getService() { InventoryHistoryPriceService getHistoryPriceService() {
if (service == null) { return getCachedBean(InventoryHistoryPriceService.class);
service = getBean(InventoryHistoryPriceService.class);
}
return service;
} }
ContractItemService getContractItemService() { ContractItemService getContractItemService() {
if (contractItemService == null) { return getCachedBean(ContractItemService.class);
contractItemService = getBean(ContractItemService.class);
}
return contractItemService;
} }
ContractService getContractService() { ContractService getContractService() {
if (contractService == null) { return getCachedBean(ContractService.class);
contractService = getBean(ContractService.class);
}
return contractService;
} }
@Override @Override
@@ -109,7 +100,6 @@ public class InventoryTabSkinHistoryPrice
return controller.historyPriceTab; return controller.historyPriceTab;
} }
@Override @Override
public void initializeTable() { public void initializeTable() {
super.initializeTable(); super.initializeTable();
@@ -176,67 +166,70 @@ public class InventoryTabSkinHistoryPrice
private void onRefreshAction(ActionEvent event) { private void onRefreshAction(ActionEvent event) {
runAsync(() -> { runAsync(() -> {
HashMap<Integer, InventoryHistoryPrice> historyPriceMap = new HashMap<>(); HashMap<Integer, InventoryHistoryPriceVo> historyPriceMap = new HashMap<>();
for (InventoryHistoryPrice historyPrice : getService().findAllByInventory(getParent())) { for (InventoryHistoryPriceVo historyPrice : getHistoryPriceService().findAllByInventory(getParent())) {
InventoryHistoryPrice oldValue = historyPriceMap.put(historyPrice.getYear().getValue(), historyPrice); InventoryHistoryPriceVo oldValue = historyPriceMap.put(historyPrice.getYear().getValue(), historyPrice);
if (oldValue != null) { if (oldValue != null) {
getService().delete(oldValue); getHistoryPriceService().delete(oldValue);
} }
} }
List<ContractItemVo> items = getContractItemService().findAllByInventory(getParent());
List<ContractItem> items = getContractItemService().findAllByInventory(getParent());
items.stream().collect(Collectors.groupingBy(v -> { items.stream().collect(Collectors.groupingBy(v -> {
Contract contract = v.getContract(); Integer contractId = v.getContractId();
if (!Hibernate.isInitialized(contract)) { ContractVo contract = getContractService().findById(contractId);
contract = getContractService().findById(contract.getId());
v.setContract(contract);
}
return contract.getSetupDate().getYear(); return contract.getSetupDate().getYear();
})).forEach((year, list) -> { })).forEach((year, list) -> {
InventoryHistoryPrice historyPrice = historyPriceMap.computeIfAbsent(year, k -> { InventoryHistoryPriceVo historyPrice = historyPriceMap.computeIfAbsent(year, k -> {
InventoryHistoryPrice price = new InventoryHistoryPrice(); InventoryHistoryPriceVo price = new InventoryHistoryPriceVo();
price.setInventory(getParent()); price.setInventoryId(getParent().getId());
price.setYear(year); price.setYear(Year.of(year));
return price; return price;
}); });
list.stream().collect(Collectors.groupingBy(v -> { list.stream().collect(Collectors.groupingBy(v -> {
Contract contract = v.getContract(); Integer contractId = v.getContractId();
ContractVo contract = getContractService().findById(contractId);
return contract.getPayWay(); return contract.getPayWay();
})).forEach((payWay, contractItems) -> { })).forEach((payWay, contractItems) -> {
if (ContractPayWay.RECEIVE.equals(payWay)) { if (ContractPayWay.RECEIVE.equals(payWay)) {
// 销售 // 销售
list.stream().max(Comparator.comparing(v -> { list.stream().max(Comparator.comparing(v -> {
Contract contract = v.getContract(); Integer contractId = v.getContractId();
ContractVo contract = getContractService().findById(contractId);
return contract.getSetupDate(); return contract.getSetupDate();
})).ifPresent(v -> update(historyPrice.getLatestSalePrice(), v)); })).ifPresent(v -> update(historyPrice.getLatestSalePrice(), v));
list.stream().max(Comparator.comparing(ContractItem::getTaxPrice)).ifPresent(v -> update(historyPrice.getMaxSalePrice(), v)); list.stream().max(Comparator.comparing(ContractItemVo::getTaxPrice))
list.stream().min(Comparator.comparing(ContractItem::getTaxPrice)).ifPresent(v -> update(historyPrice.getMiniSalePrice(), v)); .ifPresent(v -> update(historyPrice.getMaxSalePrice(), v));
list.stream().min(Comparator.comparing(ContractItemVo::getTaxPrice))
.ifPresent(v -> update(historyPrice.getMiniSalePrice(), v));
} else if (ContractPayWay.PAY.equals(payWay)) { } else if (ContractPayWay.PAY.equals(payWay)) {
// 采购 // 采购
list.stream().max(Comparator.comparing(v -> { list.stream().max(Comparator.comparing(v -> {
Contract contract = v.getContract(); Integer contractId = v.getContractId();
ContractVo contract = getContractService().findById(contractId);
return contract.getSetupDate(); return contract.getSetupDate();
})).ifPresent(v -> update(historyPrice.getLatestPurchasePrice(), v)); })).ifPresent(v -> update(historyPrice.getLatestPurchasePrice(), v));
list.stream().max(Comparator.comparing(ContractItem::getTaxPrice)).ifPresent(v -> update(historyPrice.getMaxPurchasePrice(), v)); list.stream().max(Comparator.comparing(ContractItemVo::getTaxPrice))
list.stream().min(Comparator.comparing(ContractItem::getTaxPrice)).ifPresent(v -> update(historyPrice.getMiniPurchasePrice(), v)); .ifPresent(v -> update(historyPrice.getMaxPurchasePrice(), v));
list.stream().min(Comparator.comparing(ContractItemVo::getTaxPrice))
.ifPresent(v -> update(historyPrice.getMiniPurchasePrice(), v));
} else { } else {
} }
}); });
getService().save(historyPrice); getHistoryPriceService().save(historyPrice);
}); });
loadTableDataSet(); loadTableDataSet();
}); });
} }
void update(HistoryPrice historyPrice, ContractItem item) { void update(HistoryPrice historyPrice, ContractItemVo item) {
if (item == null) { if (item == null) {
historyPrice.setTaxRate(0); historyPrice.setTaxRate(0);
historyPrice.setPreTaxPrice(0); historyPrice.setPreTaxPrice(0);
@@ -245,22 +238,19 @@ public class InventoryTabSkinHistoryPrice
return; return;
} }
getContractService(); getContractService();
Contract contract = item.getContract(); Integer contractId = item.getContractId();
if (!Hibernate.isInitialized(contract)) { ContractVo contract = getContractService().findById(contractId);
contract = getContractService().findById(contract.getId()); historyPrice.setTaxRate(item.getTaxRate().floatValue());
item.setContract(contract);
}
historyPrice.setTaxRate((float) item.getTaxRate());
historyPrice.setPreTaxPrice(item.getExclusiveTaxPrice()); historyPrice.setPreTaxPrice(item.getExclusiveTaxPrice());
historyPrice.setPostTaxPrice(item.getTaxPrice()); historyPrice.setPostTaxPrice(item.getTaxPrice());
historyPrice.setMonthDay(MonthDay.from(contract.getSetupDate())); historyPrice.setMonthDay(MonthDay.from(contract.getSetupDate()));
} }
@Override @Override
public Specification<InventoryHistoryPrice> getSpecification(Inventory parent) { public ParamUtils.Builder getSpecification(InventoryVo parent) {
return SpecificationUtils.and(getSpecification(), (root, query, builder) -> { ParamUtils.Builder params = getSpecification();
return builder.equal(root.get("inventory"), parent); params.equals("inventory", parent.getId());
}); return params;
} }
@Override @Override

View File

@@ -1,25 +1,31 @@
package com.ecep.contract.manager.ds.other.controller.inventory; package com.ecep.contract.controller.inventory;
import com.ecep.contract.manager.ds.other.model.Inventory;
import com.ecep.contract.manager.ds.other.service.InventoryService;
import com.ecep.contract.manager.ds.other.vo.InventoryViewModel;
import com.ecep.contract.manager.ui.AbstEntityController;
import com.ecep.contract.manager.ui.FxmlPath;
import javafx.beans.binding.Bindings;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.stage.WindowEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.ecep.contract.controller.AbstEntityController;
import com.ecep.contract.service.InventoryService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.vm.InventoryViewModel;
import com.ecep.contract.vo.InventoryVo;
import javafx.beans.binding.Bindings;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.stage.WindowEvent;
@Lazy @Lazy
@Scope("prototype") @Scope("prototype")
@Component @Component
@FxmlPath("/ui/inventory/inventory.fxml") @FxmlPath("/ui/inventory/inventory.fxml")
public class InventoryWindowController extends AbstEntityController<Inventory, InventoryViewModel> { public class InventoryWindowController extends AbstEntityController<InventoryVo, InventoryViewModel> {
@FXML @FXML
public BorderPane root; public BorderPane root;
@FXML @FXML
@@ -31,7 +37,6 @@ public class InventoryWindowController extends AbstEntityController<Inventory, I
@FXML @FXML
public Tab contractsTab; public Tab contractsTab;
@FXML @FXML
public TextField nameField; public TextField nameField;
@FXML @FXML
@@ -97,27 +102,16 @@ public class InventoryWindowController extends AbstEntityController<Inventory, I
@FXML @FXML
public TextField packagedVolumeField; public TextField packagedVolumeField;
@Autowired
private InventoryService service;
@Override @Override
public void onShown(WindowEvent windowEvent) { public void onShown(WindowEvent windowEvent) {
super.onShown(windowEvent); super.onShown(windowEvent);
getTitle().bind(Bindings.createStringBinding(() -> "[" + viewModel.getId().get() + "] 存货详情 " + viewModel.getName().getValue() + " " + viewModel.getSpecification().get(), viewModel.getName(), viewModel.getCode(), viewModel.getSpecification())); getTitle().bind(Bindings.createStringBinding(
() -> "[" + viewModel.getId().get() + "] 存货详情 " + viewModel.getName().getValue() + " "
+ viewModel.getSpecification().get(),
viewModel.getName(), viewModel.getCode(), viewModel.getSpecification()));
root.getScene().getStylesheets().add("/ui/inventory/inventory.css"); root.getScene().getStylesheets().add("/ui/inventory/inventory.css");
} }
@Override
protected Inventory loadEntity() {
return service.findById(viewModel.getId().get());
}
@Override
protected Inventory saveEntity(Inventory entity) {
return service.save(entity);
}
@Override @Override
protected void registerTabSkins() { protected void registerTabSkins() {
registerTabSkin(baseInfoTab, tab -> new InventoryTabSkinBase(this)); registerTabSkin(baseInfoTab, tab -> new InventoryTabSkinBase(this));
@@ -127,6 +121,6 @@ public class InventoryWindowController extends AbstEntityController<Inventory, I
@Override @Override
public InventoryService getViewModelService() { public InventoryService getViewModelService() {
return service; return getCachedBean(InventoryService.class);
} }
} }

View File

@@ -0,0 +1,41 @@
package com.ecep.contract.controller.list.cell;
import com.ecep.contract.ContractFileType;
import com.ecep.contract.Desktop;
import com.ecep.contract.service.ContractFileTypeService;
import com.ecep.contract.vo.ContractFileTypeLocalVo;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.util.Callback;
/**
* @param <T>
*/
public class ContractFileTypeListCell<T> extends ListCell<ContractFileType> {
public static Callback<ListView<ContractFileType>, ListCell<ContractFileType>> forListView(ContractFileTypeService typeService) {
return listView -> new ContractFileTypeListCell<>(typeService);
}
private final ContractFileTypeService service;
public ContractFileTypeListCell(ContractFileTypeService service) {
this.service = service;
}
@Override
protected void updateItem(ContractFileType item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setText(null);
return;
}
ContractFileTypeLocalVo local = service.findByType(Desktop.instance.getActiveEmployee().localeProperty().get(), item);
if (local == null) {
setText(item.name());
} else {
setText(local.getValue());
}
}
}

View File

@@ -0,0 +1,30 @@
package com.ecep.contract.controller.permission;
import com.ecep.contract.controller.tab.AbstEntityBasedTabSkin;
import com.ecep.contract.service.EmployeeRoleService;
import com.ecep.contract.service.FunctionService;
import com.ecep.contract.service.PermissionService;
import com.ecep.contract.vm.EmployeeRoleViewModel;
import com.ecep.contract.vo.EmployeeRoleVo;
public abstract class AbstEmployeeRoleBasedTabSkin
extends AbstEntityBasedTabSkin<EmployeeRoleWindowController, EmployeeRoleVo, EmployeeRoleViewModel> {
public AbstEmployeeRoleBasedTabSkin(EmployeeRoleWindowController controller) {
super(controller);
viewModel = controller.getViewModel();
}
EmployeeRoleService getRoleService() {
return getCachedBean(EmployeeRoleService.class);
}
FunctionService getFunctionService() {
return getCachedBean(FunctionService.class);
}
public PermissionService getPermissionService() {
return controller.permissionService;
}
}

View File

@@ -1,24 +1,23 @@
package com.ecep.contract.manager.ds.other.controller.permission; package com.ecep.contract.controller.permission;
import com.ecep.contract.manager.ds.other.model.Function;
import com.ecep.contract.manager.ds.other.service.FunctionService;
import com.ecep.contract.manager.ds.other.service.PermissionService;
import com.ecep.contract.manager.ds.other.vo.FunctionViewModel;
import com.ecep.contract.manager.ds.other.vo.PermissionViewModel;
import com.ecep.contract.manager.ui.AbstManagerWindowController;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.ui.ViewModelService;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.stage.Stage;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Description; import org.springframework.context.annotation.Description;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.ecep.contract.controller.AbstManagerWindowController;
import com.ecep.contract.service.FunctionService;
import com.ecep.contract.service.PermissionService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.vm.FunctionViewModel;
import com.ecep.contract.vo.FunctionVo;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.TableColumn;
import javafx.stage.Stage;
@Lazy @Lazy
@Scope("prototype") @Scope("prototype")
@@ -26,7 +25,7 @@ import org.springframework.stereotype.Component;
@FxmlPath("/ui/employee/functions-manager.fxml") @FxmlPath("/ui/employee/functions-manager.fxml")
@Component @Component
public class EmployeeFunctionsManagerWindowController public class EmployeeFunctionsManagerWindowController
extends AbstManagerWindowController<Function, FunctionViewModel, FunctionManagerSkin> { extends AbstManagerWindowController<FunctionVo, FunctionViewModel, FunctionManagerSkin> {
@Autowired @Autowired
PermissionService permissionService; PermissionService permissionService;

View File

@@ -1,17 +1,19 @@
package com.ecep.contract.manager.ds.other.controller.permission; package com.ecep.contract.controller.permission;
import com.ecep.contract.controller.AbstEntityManagerSkin;
import com.ecep.contract.controller.ManagerSkin;
import com.ecep.contract.controller.table.EditableEntityTableTabSkin;
import com.ecep.contract.vo.EmployeeRoleVo;
import com.ecep.contract.service.PermissionService;
import com.ecep.contract.vm.EmployeeRoleViewModel;
import com.ecep.contract.manager.ds.other.model.EmployeeRole;
import com.ecep.contract.manager.ds.other.service.PermissionService;
import com.ecep.contract.manager.ds.other.vo.EmployeeRoleViewModel;
import com.ecep.contract.manager.ui.AbstEntityManagerSkin;
import com.ecep.contract.manager.ui.table.EditableEntityTableTabSkin;
import com.ecep.contract.manager.ui.ManagerSkin;
import javafx.scene.control.cell.CheckBoxTableCell; import javafx.scene.control.cell.CheckBoxTableCell;
import lombok.Setter; import lombok.Setter;
public class EmployeeRoleManagerSkin public class EmployeeRoleManagerSkin
extends AbstEntityManagerSkin<EmployeeRole, EmployeeRoleViewModel, EmployeeRoleManagerSkin, EmployeeRoleManagerWindowController> extends
implements ManagerSkin, EditableEntityTableTabSkin<EmployeeRole, EmployeeRoleViewModel> { AbstEntityManagerSkin<EmployeeRoleVo, EmployeeRoleViewModel, EmployeeRoleManagerSkin, EmployeeRoleManagerWindowController>
implements ManagerSkin, EditableEntityTableTabSkin<EmployeeRoleVo, EmployeeRoleViewModel> {
@Setter @Setter
private PermissionService permissionService; private PermissionService permissionService;

View File

@@ -1,4 +1,4 @@
package com.ecep.contract.manager.ds.other.controller.permission; package com.ecep.contract.controller.permission;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -7,15 +7,14 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.ecep.contract.manager.ds.other.model.EmployeeRole; import com.ecep.contract.controller.AbstManagerWindowController;
import com.ecep.contract.manager.ds.other.service.EmployeeRoleService; import com.ecep.contract.service.EmployeeRoleService;
import com.ecep.contract.manager.ds.other.service.PermissionService; import com.ecep.contract.service.PermissionService;
import com.ecep.contract.manager.ds.other.vo.EmployeeRoleViewModel; import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.manager.ui.AbstManagerWindowController; import com.ecep.contract.vm.EmployeeRoleViewModel;
import com.ecep.contract.manager.ui.FxmlPath; import com.ecep.contract.vo.EmployeeRoleVo;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.TableColumn; import javafx.scene.control.TableColumn;
import javafx.stage.Stage; import javafx.stage.Stage;
@@ -24,7 +23,7 @@ import javafx.stage.Stage;
@Component @Component
@FxmlPath("/ui/employee/roles-manager.fxml") @FxmlPath("/ui/employee/roles-manager.fxml")
public class EmployeeRoleManagerWindowController public class EmployeeRoleManagerWindowController
extends AbstManagerWindowController<EmployeeRole, EmployeeRoleViewModel, EmployeeRoleManagerSkin> { extends AbstManagerWindowController<EmployeeRoleVo, EmployeeRoleViewModel, EmployeeRoleManagerSkin> {
private static final Logger logger = LoggerFactory.getLogger(EmployeeRoleManagerWindowController.class); private static final Logger logger = LoggerFactory.getLogger(EmployeeRoleManagerWindowController.class);
@Autowired @Autowired

View File

@@ -1,7 +1,8 @@
package com.ecep.contract.manager.ds.other.controller.permission; package com.ecep.contract.controller.permission;
import com.ecep.contract.Desktop;
import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.manager.Desktop;
import com.ecep.contract.manager.ui.tab.TabSkin;
import javafx.scene.control.Tab; import javafx.scene.control.Tab;
public class EmployeeRoleTabSkinBase extends AbstEmployeeRoleBasedTabSkin implements TabSkin { public class EmployeeRoleTabSkinBase extends AbstEmployeeRoleBasedTabSkin implements TabSkin {

View File

@@ -1,13 +1,13 @@
package com.ecep.contract.manager.ds.other.controller.permission; package com.ecep.contract.controller.permission;
import java.util.List; import java.util.List;
import org.controlsfx.control.ListSelectionView; import org.controlsfx.control.ListSelectionView;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import com.ecep.contract.manager.ds.other.model.EmployeeRole; import com.ecep.contract.util.ParamUtils;
import com.ecep.contract.manager.ds.other.model.Function; import com.ecep.contract.vo.EmployeeRoleVo;
import com.ecep.contract.vo.FunctionVo;
import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleBooleanProperty;
import javafx.collections.ListChangeListener; import javafx.collections.ListChangeListener;
@@ -20,7 +20,7 @@ import javafx.scene.control.Tab;
public class EmployeeRoleTabSkinFunctions extends AbstEmployeeRoleBasedTabSkin { public class EmployeeRoleTabSkinFunctions extends AbstEmployeeRoleBasedTabSkin {
private final SimpleBooleanProperty changed = new SimpleBooleanProperty(false); private final SimpleBooleanProperty changed = new SimpleBooleanProperty(false);
private ListSelectionView<Function> functionsField; private ListSelectionView<FunctionVo> functionsField;
public EmployeeRoleTabSkinFunctions(EmployeeRoleWindowController controller) { public EmployeeRoleTabSkinFunctions(EmployeeRoleWindowController controller) {
super(controller); super(controller);
@@ -50,7 +50,7 @@ public class EmployeeRoleTabSkinFunctions extends AbstEmployeeRoleBasedTabSkin {
} }
private void loadSelectedRoles() { private void loadSelectedRoles() {
List<Function> selectedRoles = getRoleService().getFunctionsByRoleId(viewModel.getId().get()); List<FunctionVo> selectedRoles = getRoleService().getFunctionsByRoleId(viewModel.getId().get());
if (selectedRoles != null) { if (selectedRoles != null) {
functionsField.getTargetItems().setAll(selectedRoles); functionsField.getTargetItems().setAll(selectedRoles);
} }
@@ -59,14 +59,14 @@ public class EmployeeRoleTabSkinFunctions extends AbstEmployeeRoleBasedTabSkin {
private void initializeListView() { private void initializeListView() {
// 非系统内置账户 // 非系统内置账户
Specification<Function> spec = (root, query, cb) -> cb.equal(root.get("active"), true); List<FunctionVo> roles = getFunctionService()
List<Function> roles = getFunctionService().findAll(spec, Pageable.ofSize(500)).getContent(); .findAll(ParamUtils.builder().equals("active", true).build(), Pageable.ofSize(500)).getContent();
functionsField.getSourceItems().setAll(roles); functionsField.getSourceItems().setAll(roles);
functionsField.setCellFactory(param -> { functionsField.setCellFactory(param -> {
return new ListCell<>() { return new ListCell<FunctionVo>() {
@Override @Override
protected void updateItem(Function item, boolean empty) { protected void updateItem(FunctionVo item, boolean empty) {
super.updateItem(item, empty); super.updateItem(item, empty);
if (item == null || empty) { if (item == null || empty) {
setText(null); setText(null);
@@ -77,10 +77,10 @@ public class EmployeeRoleTabSkinFunctions extends AbstEmployeeRoleBasedTabSkin {
}; };
}); });
functionsField.getTargetItems().addListener((ListChangeListener<Function>) change -> { functionsField.getTargetItems().addListener((ListChangeListener<FunctionVo>) change -> {
while (change.next()) { while (change.next()) {
List<? extends Function> added = change.getAddedSubList(); List<? extends FunctionVo> added = change.getAddedSubList();
List<? extends Function> removed = change.getRemoved(); List<? extends FunctionVo> removed = change.getRemoved();
if (!added.isEmpty() || !removed.isEmpty()) { if (!added.isEmpty() || !removed.isEmpty()) {
changed.set(true); changed.set(true);
} }
@@ -99,7 +99,7 @@ public class EmployeeRoleTabSkinFunctions extends AbstEmployeeRoleBasedTabSkin {
} }
private void saveRoles(ActionEvent event) { private void saveRoles(ActionEvent event) {
EmployeeRole entity = getEntity(); EmployeeRoleVo entity = getEntity();
entity.setFunctions(functionsField.getTargetItems()); entity.setFunctions(functionsField.getTargetItems());
save(entity); save(entity);
loadSelectedRoles(); loadSelectedRoles();

View File

@@ -1,18 +1,5 @@
package com.ecep.contract.manager.ds.other.controller.permission; package com.ecep.contract.controller.permission;
import com.ecep.contract.manager.ds.other.model.EmployeeRole;
import com.ecep.contract.manager.ds.other.service.EmployeeRoleService;
import com.ecep.contract.manager.ds.other.service.PermissionService;
import com.ecep.contract.manager.ds.other.vo.EmployeeRoleViewModel;
import com.ecep.contract.manager.ui.AbstEntityController;
import com.ecep.contract.manager.ui.FxmlPath;
import com.ecep.contract.manager.ui.ViewModelService;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.stage.Window;
import javafx.stage.WindowEvent;
import org.controlsfx.control.ListSelectionView; import org.controlsfx.control.ListSelectionView;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -21,12 +8,30 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.ecep.contract.controller.AbstEntityController;
import com.ecep.contract.service.EmployeeRoleService;
import com.ecep.contract.service.PermissionService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.vm.EmployeeRoleViewModel;
import com.ecep.contract.vo.EmployeeRoleVo;
import javafx.fxml.FXML;
import javafx.scene.control.CheckBox;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.stage.Window;
import javafx.stage.WindowEvent;
@Lazy @Lazy
@Scope("prototype") @Scope("prototype")
@Component @Component
@FxmlPath("/ui/employee/role.fxml") @FxmlPath("/ui/employee/role.fxml")
public class EmployeeRoleWindowController extends AbstEntityController<EmployeeRole, EmployeeRoleViewModel> { public class EmployeeRoleWindowController extends AbstEntityController<EmployeeRoleVo, EmployeeRoleViewModel> {
private static final Logger logger = LoggerFactory.getLogger(EmployeeRoleWindowController.class); private static final Logger logger = LoggerFactory.getLogger(EmployeeRoleWindowController.class);
@@ -53,7 +58,7 @@ public class EmployeeRoleWindowController extends AbstEntityController<EmployeeR
*/ */
public Tab functionsTab; public Tab functionsTab;
public ListSelectionView<com.ecep.contract.manager.ds.other.model.Function> functionsField; public ListSelectionView<com.ecep.contract.vo.FunctionVo> functionsField;
/* /*
@@ -66,17 +71,6 @@ public class EmployeeRoleWindowController extends AbstEntityController<EmployeeR
@Autowired @Autowired
EmployeeRoleService employeeRoleService; EmployeeRoleService employeeRoleService;
@Override
protected EmployeeRole loadEntity() {
return employeeRoleService.findById(viewModel.getId().get());
}
@Override
protected EmployeeRole saveEntity(EmployeeRole role) {
return employeeRoleService.save(role);
}
@Override @Override
public void onShown(WindowEvent windowEvent) { public void onShown(WindowEvent windowEvent) {
super.onShown(windowEvent); super.onShown(windowEvent);

View File

@@ -1,10 +1,10 @@
package com.ecep.contract.manager.ds.other.controller.permission; package com.ecep.contract.controller.permission;
import com.ecep.contract.manager.ds.other.model.Function; import com.ecep.contract.controller.AbstEntityManagerSkin;
import com.ecep.contract.manager.ds.other.service.FunctionService; import com.ecep.contract.service.FunctionService;
import com.ecep.contract.manager.ds.other.service.PermissionService; import com.ecep.contract.service.PermissionService;
import com.ecep.contract.manager.ds.other.vo.FunctionViewModel; import com.ecep.contract.vm.FunctionViewModel;
import com.ecep.contract.manager.ui.AbstEntityManagerSkin; import com.ecep.contract.vo.FunctionVo;
import javafx.scene.control.TableColumn; import javafx.scene.control.TableColumn;
import javafx.scene.control.cell.CheckBoxTableCell; import javafx.scene.control.cell.CheckBoxTableCell;
@@ -12,7 +12,7 @@ import javafx.scene.control.cell.TextFieldTableCell;
public class FunctionManagerSkin public class FunctionManagerSkin
extends extends
AbstEntityManagerSkin<Function, FunctionViewModel, FunctionManagerSkin, EmployeeFunctionsManagerWindowController> { AbstEntityManagerSkin<FunctionVo, FunctionViewModel, FunctionManagerSkin, EmployeeFunctionsManagerWindowController> {
public FunctionManagerSkin(EmployeeFunctionsManagerWindowController controller) { public FunctionManagerSkin(EmployeeFunctionsManagerWindowController controller) {
super(controller); super(controller);

View File

@@ -1,13 +1,13 @@
package com.ecep.contract.manager.ds.other.controller.permission; package com.ecep.contract.controller.permission;
import com.ecep.contract.manager.ds.other.model.Function; import com.ecep.contract.controller.tab.AbstEntityBasedTabSkin;
import com.ecep.contract.manager.ds.other.vo.FunctionViewModel; import com.ecep.contract.vm.FunctionViewModel;
import com.ecep.contract.manager.ui.tab.AbstEntityBasedTabSkin; import com.ecep.contract.vo.FunctionVo;
import javafx.scene.control.Tab; import javafx.scene.control.Tab;
public class FunctionTabSkinBase public class FunctionTabSkinBase
extends AbstEntityBasedTabSkin<FunctionWindowController, Function, FunctionViewModel> { extends AbstEntityBasedTabSkin<FunctionWindowController, FunctionVo, FunctionViewModel> {
public FunctionTabSkinBase(FunctionWindowController controller) { public FunctionTabSkinBase(FunctionWindowController controller) {
super(controller); super(controller);

View File

@@ -1,16 +1,17 @@
package com.ecep.contract.manager.ds.other.controller.permission; package com.ecep.contract.controller.permission;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import com.ecep.contract.manager.ds.other.model.Function; import com.ecep.contract.controller.table.AbstEntityTableTabSkin;
import com.ecep.contract.manager.ds.other.model.Permission; import com.ecep.contract.model.Function;
import com.ecep.contract.manager.ds.other.service.PermissionService; import com.ecep.contract.model.Permission;
import com.ecep.contract.manager.ds.other.vo.FunctionViewModel; import com.ecep.contract.service.PermissionService;
import com.ecep.contract.manager.ds.other.vo.PermissionViewModel; import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.manager.ui.table.AbstEntityTableTabSkin; import com.ecep.contract.util.ParamUtils;
import com.ecep.contract.manager.ui.FxmlPath; import com.ecep.contract.vm.FunctionViewModel;
import com.ecep.contract.manager.util.SpecificationUtils; import com.ecep.contract.vm.PermissionViewModel;
import com.ecep.contract.vo.FunctionVo;
import com.ecep.contract.vo.PermissionVo;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.scene.control.Tab; import javafx.scene.control.Tab;
@@ -19,7 +20,7 @@ import javafx.scene.control.TableColumn;
@FxmlPath("/ui/employee/function-tab-permission.fxml") @FxmlPath("/ui/employee/function-tab-permission.fxml")
public class FunctionTabSkinPermission public class FunctionTabSkinPermission
extends extends
AbstEntityTableTabSkin<FunctionWindowController, Function, FunctionViewModel, Permission, PermissionViewModel> { AbstEntityTableTabSkin<FunctionWindowController, FunctionVo, FunctionViewModel, PermissionVo, PermissionViewModel> {
@FXML @FXML
public TableColumn<PermissionViewModel, Number> idColumn; public TableColumn<PermissionViewModel, Number> idColumn;
@@ -61,10 +62,10 @@ public class FunctionTabSkinPermission
} }
@Override @Override
public Specification<Permission> getSpecification(Function parent) { public ParamUtils.Builder getSpecification(FunctionVo parent) {
return SpecificationUtils.and(getSpecification(), (root, query, criteriaBuilder) -> { ParamUtils.Builder params = getSpecification();
return criteriaBuilder.equal(root.get("function"), parent); params.equals("function", parent.getId());
}); return params;
} }
} }

View File

@@ -1,16 +1,5 @@
package com.ecep.contract.manager.ds.other.controller.permission; package com.ecep.contract.controller.permission;
import com.ecep.contract.manager.ds.other.model.Function;
import com.ecep.contract.manager.ds.other.service.FunctionService;
import com.ecep.contract.manager.ds.other.vo.FunctionViewModel;
import com.ecep.contract.manager.ui.AbstEntityController;
import com.ecep.contract.manager.ui.FxmlPath;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.fxml.FXML;
import javafx.stage.Window;
import javafx.stage.WindowEvent;
import lombok.Getter;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -18,11 +7,29 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.ecep.contract.controller.AbstEntityController;
import com.ecep.contract.service.FunctionService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.vm.FunctionViewModel;
import com.ecep.contract.vo.FunctionVo;
import javafx.fxml.FXML;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.stage.Window;
import javafx.stage.WindowEvent;
import lombok.Getter;
@Lazy @Lazy
@Scope("prototype") @Scope("prototype")
@Component @Component
@FxmlPath("/ui/employee/function.fxml") @FxmlPath("/ui/employee/function.fxml")
public class FunctionWindowController extends AbstEntityController<Function, FunctionViewModel> { public class FunctionWindowController extends AbstEntityController<FunctionVo, FunctionViewModel> {
private static final Logger logger = LoggerFactory.getLogger(FunctionWindowController.class); private static final Logger logger = LoggerFactory.getLogger(FunctionWindowController.class);
/** /**
@@ -55,8 +62,8 @@ public class FunctionWindowController extends AbstEntityController<Function, Fun
@FXML @FXML
public Label versionLabel; public Label versionLabel;
public static void show(Function function, Window owner) { public static void show(FunctionVo functionVo, Window owner) {
FunctionViewModel model = FunctionViewModel.from(function); FunctionViewModel model = FunctionViewModel.from(functionVo);
show(model, owner); show(model, owner);
} }

View File

@@ -1,11 +1,21 @@
package com.ecep.contract.manager.ds.other.controller.permission; package com.ecep.contract.controller.permission;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ecep.contract.controller.ManagerSkin;
import com.ecep.contract.controller.table.TableTabSkin;
import com.ecep.contract.util.ParamUtils;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.FunctionViewModel;
import com.ecep.contract.vm.PermissionViewModel;
import com.ecep.contract.vo.PermissionVo;
import com.ecep.contract.manager.ds.other.model.Permission;
import com.ecep.contract.manager.ds.other.vo.FunctionViewModel;
import com.ecep.contract.manager.ds.other.vo.PermissionViewModel;
import com.ecep.contract.manager.ui.ManagerSkin;
import com.ecep.contract.manager.ui.table.TableTabSkin;
import com.ecep.contract.manager.util.UITools;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.beans.property.Property; import javafx.beans.property.Property;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
@@ -16,16 +26,8 @@ import javafx.scene.control.MenuItem;
import javafx.scene.control.TableColumn; import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView; import javafx.scene.control.TableView;
import lombok.Setter; import lombok.Setter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.jpa.domain.Specification;
import java.util.ArrayList; public class PermissionManagerSkin implements ManagerSkin, TableTabSkin<PermissionVo, PermissionViewModel> {
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
public class PermissionManagerSkin implements ManagerSkin, TableTabSkin<Permission, PermissionViewModel> {
private static final Logger logger = LoggerFactory.getLogger(PermissionManagerSkin.class); private static final Logger logger = LoggerFactory.getLogger(PermissionManagerSkin.class);
EmployeeFunctionsManagerWindowController controller; EmployeeFunctionsManagerWindowController controller;
@@ -56,7 +58,6 @@ public class PermissionManagerSkin implements ManagerSkin, TableTabSkin<Permissi
return table; return table;
} }
@Override @Override
public void install() { public void install() {
initializeTable(); initializeTable();
@@ -64,12 +65,12 @@ public class PermissionManagerSkin implements ManagerSkin, TableTabSkin<Permissi
loadTableDataSet(); loadTableDataSet();
} }
@Override @Override
public void initializeTable() { public void initializeTable() {
table.setEditable(true); table.setEditable(true);
// controller.permissionTable_descriptionColumn.setCellValueFactory(param -> param.getValue().getDescription()); // controller.permissionTable_descriptionColumn.setCellValueFactory(param ->
// param.getValue().getDescription());
// controller.permissionTable_descriptionColumn.setCellFactory(TextFieldTableCell.forTableColumn()); // controller.permissionTable_descriptionColumn.setCellFactory(TextFieldTableCell.forTableColumn());
// controller.permissionTable_descriptionColumn.setOnEditCommit(this::onSignMethodTableDescriptionColumnEditCommitAction); // controller.permissionTable_descriptionColumn.setOnEditCommit(this::onSignMethodTableDescriptionColumnEditCommitAction);
@@ -97,11 +98,9 @@ public class PermissionManagerSkin implements ManagerSkin, TableTabSkin<Permissi
} }
protected void onTableCreateNewAction(ActionEvent event) { protected void onTableCreateNewAction(ActionEvent event) {
Permission newRow = new Permission(); PermissionVo newRow = new PermissionVo();
com.ecep.contract.manager.ds.other.model.Function function = controller.functionService.findById(viewModel.getId().get()); newRow.setFunctionId(viewModel.getId().get());
newRow.setFunction(function); PermissionVo saved = controller.getPermissionService().save(newRow);
Permission saved = controller.permissionService.save(newRow);
PermissionViewModel row = PermissionViewModel.from(saved); PermissionViewModel row = PermissionViewModel.from(saved);
dataSet.add(row); dataSet.add(row);
} }
@@ -126,7 +125,17 @@ public class PermissionManagerSkin implements ManagerSkin, TableTabSkin<Permissi
} }
protected boolean deleteRow(PermissionViewModel row) { protected boolean deleteRow(PermissionViewModel row) {
throw new UnsupportedOperationException("未实现"); try {
int id = row.getId().get();
PermissionVo permissionVo = controller.permissionService.findById(id);
if (permissionVo != null) {
controller.permissionService.delete(permissionVo);
return true;
}
} catch (Exception e) {
handleException("删除权限失败", e);
}
return false;
} }
private void onNameColumnEditCommitAction(TableColumn.CellEditEvent<PermissionViewModel, String> event) { private void onNameColumnEditCommitAction(TableColumn.CellEditEvent<PermissionViewModel, String> event) {
@@ -141,7 +150,8 @@ public class PermissionManagerSkin implements ManagerSkin, TableTabSkin<Permissi
if (viewModel == null) { if (viewModel == null) {
return List.of(); return List.of();
} }
return controller.permissionService.findByFunctionId(viewModel.getId().get()).stream().map(PermissionViewModel::from).toList(); return controller.permissionService.findByFunctionId(viewModel.getId().get()).stream()
.map(PermissionViewModel::from).toList();
} }
public void loadTableDataSet() { public void loadTableDataSet() {
@@ -161,12 +171,14 @@ public class PermissionManagerSkin implements ManagerSkin, TableTabSkin<Permissi
} }
@Override @Override
public Specification<Permission> getSpecification() { public ParamUtils.Builder getSpecification() {
ParamUtils.Builder params = ParamUtils.builder();
return controller.permissionService.getSpecification(null); // 使用permissionService的specification逻辑
return params;
} }
private <K> void acceptSignMethodCellEditEvent(TableColumn.CellEditEvent<PermissionViewModel, K> event, Function<PermissionViewModel, Property<K>> function) { private <K> void acceptSignMethodCellEditEvent(TableColumn.CellEditEvent<PermissionViewModel, K> event,
Function<PermissionViewModel, Property<K>> function) {
PermissionViewModel row = event.getRowValue(); PermissionViewModel row = event.getRowValue();
Property<K> property = function.apply(row); Property<K> property = function.apply(row);
property.setValue(event.getNewValue()); property.setValue(event.getNewValue());
@@ -179,12 +191,11 @@ public class PermissionManagerSkin implements ManagerSkin, TableTabSkin<Permissi
protected void save(PermissionViewModel row) { protected void save(PermissionViewModel row) {
int id = row.getId().get(); int id = row.getId().get();
Permission type = controller.permissionService.findById(id); PermissionVo permissionVo = controller.permissionService.findById(id);
if (row.copyTo(type)) { if (permissionVo != null && row.copyTo(permissionVo)) {
Permission saved = controller.permissionService.save(type); PermissionVo saved = controller.permissionService.save(permissionVo);
row.update(saved); row.update(saved);
} }
} }
} }

View File

@@ -1,13 +1,14 @@
package com.ecep.contract.manager.ds.project.controller; package com.ecep.contract.controller.project;
import com.ecep.contract.manager.ds.project.model.Project; import com.ecep.contract.controller.tab.AbstEntityBasedTabSkin;
import com.ecep.contract.manager.ds.project.service.ProjectService; import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.manager.ds.project.vo.ProjectViewModel; import com.ecep.contract.model.Project;
import com.ecep.contract.manager.ui.tab.AbstEntityBasedTabSkin; import com.ecep.contract.service.ProjectService;
import com.ecep.contract.manager.ui.tab.TabSkin; import com.ecep.contract.vm.ProjectViewModel;
import com.ecep.contract.vo.ProjectVo;
public abstract class AbstProjectBasedTabSkin public abstract class AbstProjectBasedTabSkin
extends AbstEntityBasedTabSkin<ProjectWindowController, Project, ProjectViewModel> extends AbstEntityBasedTabSkin<ProjectWindowController, ProjectVo, ProjectViewModel>
implements TabSkin { implements TabSkin {
public AbstProjectBasedTabSkin(ProjectWindowController controller) { public AbstProjectBasedTabSkin(ProjectWindowController controller) {

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